#!/usr/bin/env python
# coding: utf-8
# # Identificando pajaritos con Python
# ## Angie K. Reyes
# ### Mayo 2018
# # AGENDA
# ### Introducción
# #### - ¿Quién soy?
# #### - Temas de interes
#
# ### Antecedentes
# #### - LifeClef Challenge
# #### - Motivación
#
# ### Contenido
# #### - ¿Cómo identificar especies de aves usando Python?
# # Acerca de mi ....
#
#
# ## https://github.com/angiereyesbet/
# ### Ingeniera de sistemas y computación
# ### 25 años de edad
# ### Chica TIC 2016
#
# ### Estudiante del doctorado en Ciencia Aplicada - UAN
# ### Desarrollador Back-End
# ### Temáticas
#
# # Por qué Python?
#
# # "Desarrolle una pasión por el aprendizaje.
# # Si lo hace, usted nunca dejará de crecer."
# ### Anthony J.D' Angelo.
# # BACKGROUND
# # Motivación
# ### - Se necesitan Ornitologos expertos
# ### - Los pajaros tienen acentos distintos dependientes de la región
# ### - Indentificar la migración de audios
# ### - Pajaros no identificados o en peligro de extinción
# ### - Colombia es el segundo país con mayor biodiversidad
# ### - En 2013 Colombia, la cantidad de especies de aves ascendio a 1.903
# # Life Cleft Challenge
# ### El objetivo de la tarea es identificar todas las especies de aves a partir de un conjunto de audios.
#
#
# # Acerca del aprendizaje de máquina
#
# # Support Vector Machine
#
# # Clustering
#
# # ¿Cómo identificar especies de aves usando Python?
# ## Dataset
# ### Xeno Canto (https://www.xeno-canto.org)
# ### 34.496 grabaciones de audio
# ### 1.500 tipos de especies
# #### ---------------------------------------------------------------------
# ### 7.860 grabaciones de audio Colombianas
# ### 789 tipos de especies
# #### ---------------------------------------------------------------------
# ### 3.440 grabaciones de audio
# ### 100 tipos de especies
# # Paso 1: Procesamiento de datos
#
# # Paso 2: Procesamiento de señal
#
#
# # Paso 3: Clasificación
#
#
# # Ahora sí .... lo Divertido!!!
# ## (El Código)
# In[1]:
import os
import json
import speechpy
import numpy as np
import IPython.display as ipd
import scipy.io.wavfile as wav
import xml.etree.ElementTree as ET
from urllib.request import urlopen
# ### Ejemplo de archivo XML
# In[2]:
cwd = os.getcwd()
xml_path = "LIFECLEF2015_BIRDAMAZON_XC_WAV_RN15568.xml"
xml_dict = {}
tree = ET.parse(xml_path)
root = tree.getroot()
for child in root:
xml_dict[child.tag] = root.find(child.tag).text
# In[3]:
for key in xml_dict:
print(key, ":", xml_dict[key])
# ### Ejemplo de archivo de Audio
# In[4]:
audio_path = "LIFECLEF2015_BIRDAMAZON_XC_WAV_RN15568.wav"
ipd.Audio(audio_path)
# ### Ejemplo para obtener pais con el API de Google
# In[5]:
password = os.environ["PASS_GOOGLE"]
latitude = xml_dict['Latitude'].lower().strip()
longitude = xml_dict['Longitude'].lower().strip()
url ="https://maps.googleapis.com/maps/api/geocode/json?latlng="+latitude+","+longitude+"&key="+password
jsonResponse=json.load(urlopen(url))
jsonRes= jsonResponse['results']
for x in jsonRes:
res= x['address_components']
for x in res:
country = x['long_name']
print(country)
# # Eliminar ruido en los archivos de audio
# In[6]:
new_audio_noise = str(audio_path).replace('.wav','_noise.wav')
# remove noise
resp = os.system("sox " + audio_path + " " + new_audio_noise + " noisered speech.noise-profile .5")
ipd.Audio(new_audio_noise)
# # Eliminar los silencios del audio
# In[7]:
new_audio_silence = str(audio_path).replace('.wav','_silence.wav')
# create new file without silence
resp = os.system("sox " + new_audio_noise + " " + new_audio_silence + " silence 1 0.1 1% -1 0.1 1%")
ipd.Audio(new_audio_silence)
# ### Extraer características
#
# In[8]:
fs, signal = wav.read(audio_path)
# mfcc features
mfcc = speechpy.feature.mfcc(signal, sampling_frequency=fs,
frame_length=0.020, frame_stride=0.01,
num_filters=40, fft_length=512,
low_frequency=0, high_frequency=None)
print("mfcc features:", np.shape(mfcc))
# mfcc(mean + variance normalized) features
mfcc_cmvn = speechpy.processing.cmvnw(mfcc, win_size=301,
variance_normalization=True)
print("mfcc(mean + variance normalized) features:", np.shape(mfcc_cmvn))
# mfcc feature cube
mfcc_feature_cube = speechpy.feature.extract_derivative_feature(mfcc)
print("mfcc feature cube:", np.shape(mfcc_feature_cube))
# ### Clasificador con características globales
#
# In[9]:
import numpy as np
import collections
from sklearn.svm import SVC
from sklearn.externals import joblib
from sklearn.model_selection import train_test_split as database_split
# ### Support Vector Machine
# In[10]:
def classifier(feat_train, feat_test, lab_train, lab_test):
clf = SVC(C=2**0, cache_size=300, class_weight=None, coef0=0.0,
decision_function_shape=None, degree=3,
gamma='auto', kernel='rbf', probability=False,
random_state=None, shrinking=True,
tol=0.001, verbose=False)
clf.fit(feat_train, lab_train)
score_test = clf.score(feat_test, lab_test)
return score_test
# ### Las características globales se conforma de la media de los datos
# In[11]:
# Extract global features
def globalFeatures(features):
return features.mean(0)
# ### Crear conjuntos de datos
# In[12]:
# Classifier and model evaluation
def main(dataset, labels):
# Split data into two set (training set, test set)
feat_train, feat_test, lab_train, lab_test = database_split(dataset,
labels, test_size=0.3)
print("Train set shape:", np.shape(feat_train))
print("Test set shape:", np.shape(feat_test))
counter = collections.Counter(lab_train)
counter = dict(counter)
print("Distribution labels (train set):", counter)
counter=collections.Counter(lab_test)
counter = dict(counter)
print("Distribution labels (test set):", counter)
score = classifier(feat_train, feat_test,
lab_train, lab_test)
print("Done!", "Score:", score)
# ### Importar datos
# In[13]:
data = joblib.load("mfcc_features.pkl.compressed")
mfcc_data = list()
mfcc_cmvn_data = list()
mfcc_feature_cube_data = list()
labels_data = list()
for key in data:
mfcc = data[key]["mfcc"]
mfcc_cmvn = data[key]["mfcc_cmvn"]
mfcc_feature_cube = data[key]["mfcc_feature_cube"]
mfcc_feature_cube = mfcc_feature_cube.reshape((len(mfcc_feature_cube), 39))
label = data[key]["label"]
mfcc_global = globalFeatures(mfcc)
mfcc_cmvn_global = globalFeatures(mfcc_cmvn)
mfcc_feature_global = globalFeatures(mfcc_feature_cube)
mfcc_data.append(mfcc_global)
mfcc_cmvn_data.append(mfcc_cmvn_global)
mfcc_feature_cube_data.append(mfcc_feature_global)
labels_data.append(label)
# ### Clasificador para los 3 conjuntos de datos
# In[14]:
# Process for mfcc
main(mfcc_data, labels_data)
print("\n")
# Process for mfcc (mean + variance normalized)
main(mfcc_cmvn_data, labels_data)
print("\n")
# Process for mfcc (cube)
main(mfcc_feature_cube_data, labels_data)
# ### Clasificador con características "Bag of features"
#
# In[15]:
import numpy as np
import collections
from sklearn.svm import SVC
from sklearn.externals import joblib
from scipy.spatial.distance import cdist
from sklearn.cluster import MiniBatchKMeans
from sklearn.model_selection import train_test_split
# # Paso 3: Clasificación
#
#
# ### Función para normalizar la información
# In[16]:
def normalize(data):
std_dev = np.std(data, axis=0)
zero_std_mask = std_dev == 0
if zero_std_mask.any():
std_dev[zero_std_mask] = 1.0
result = data / std_dev
return result, std_dev
# ### Función para crear los grupos de características
#
# In[17]:
def k_means(data, k_guess):
batch_size = 100
mbk = MiniBatchKMeans(init='k-means++', n_clusters=k_guess,
batch_size=batch_size, n_init=10,
max_no_improvement=10, verbose=0)
codebook = mbk.fit(data)
return codebook.cluster_centers_
# ### Función para crear el histograma
# In[18]:
def histogram(std_dev, features, codebook, index):
histogram_= [0] * index
distance = cdist(features, codebook, 'euclidean')
short = ((np.argsort(distance)).transpose()[0]).tolist()
counter = dict(collections.Counter(short))
for key in counter:
histogram_[key] = int(counter[key])
return histogram_
# ### Bag of features (visual words)
# In[19]:
def bagOfWords(features, n_clusters):
features, std_dev = normalize(mfcc)
codebook = k_means(features, n_clusters)
histogram_ = histogram(std_dev, features, codebook, n_clusters)
return histogram_
# ### Importar los datos y procesarlos
#
# In[20]:
mfcc_data = list()
mfcc_cmvn_data = list()
mfcc_feature_cube_data = list()
labels_data = list()
n_clusters = 100
# In[21]:
for key in data:
mfcc = data[key]["mfcc"]
mfcc_cmvn = data[key]["mfcc_cmvn"]
mfcc_feature_cube = data[key]["mfcc_feature_cube"]
mfcc_feature_cube = mfcc_feature_cube.reshape((len(mfcc_feature_cube), 39))
label = data[key]["label"]
n_clusterster = int ( len(mfcc) / 2)
mfcc_histogram = bagOfWords(mfcc, n_clusters)
mfcc_cmvn_histogram = bagOfWords(mfcc_cmvn, n_clusters)
mfcc_feature_cube_histogram = bagOfWords(mfcc_feature_cube, n_clusters)
mfcc_data.append(mfcc_histogram)
mfcc_cmvn_data.append(mfcc_cmvn_histogram)
mfcc_feature_cube_data.append(mfcc_feature_cube_histogram)
labels_data.append(label)
# ### Clasificador para los 3 conjuntos de datos
#
# In[22]:
# process for mfcc
main(mfcc_data, labels_data)
print("\n")
# Process for mfcc (mean + variance normalized)
main(mfcc_cmvn_data, labels_data)
print("\n")
# Process for mfcc (cube)
main(mfcc_feature_cube_data, labels_data)
# ## Puertas abiertas
#
# ### - Modificación de algoritmos y experimentación
#
# ### - Participación en retos
#
# ### - Clasificación con imágenes
#
# ### - Incluir datos en la clasificación
# # GRACIAS!!
#
# ### angreyes@outlook.com
# ### angiereyes.bet@gmail.com