Un campo demasiado atractivo sin duda es el machine learning, campo perteneciente a la inteligencia artificial, todo comienza cuando alguien se da cuenta que hacer programas extensos con if y else por doquier con el fin de crear secuencias lógicas complejas era una completa aberración. Así nace esta bella ciencia. Bueno aqui presento un ejercicio hecho a la medida de aquellos que quieran iniciarse en el machine learning, se aborda el uso de la clasificacion lineal, o linear classifier, en el cual se hace uno de una formulita llamada gradient descent.
Hay que darnos una idea primero de como funciona el machine learning, y comenzaré con decir que cuando la mayoría de las personas habla de machine learning habla del supervizado o supervized que es el tipo de aprendizaje automático más usado por programadores, roboticistas o científicos, etc. Se trata de “entrenar” al algoritmo usando una base de datos ya establecida y limpia. Se toma el 25% para el test y el 75% para el entrenamiento. Esto es tomar un trozo de nuestra base de datos y extraer las features para poder llevar a cabo el fin principal del algoritmo usado en tu código: la inferencia o predicción.
Pon tú que tienes un monton de informacion sobre 700 pacientes con cancer, tu algoritmo de ML lo que hará es diferenciar aquellos patrones que delimitan un tipo específico de cancer y otros patrones que delimiten otro tipo específico de cancer.
Con esto se entrenará y se testeará para poder hacer predicciones de otros pacientes con una exactitud de por ahí del 97% más o menos según tu problema en cuestión.
Bien, pero como se codifica esta maravilla del computer science?..
Comenzamos importando las librerías, justamente en python 3 la idea de que el machine learning es una tarea complicada solo para aquellos cuyo mero campo de trabajo es un laboratorio científico queda descartado. La aplicación de un clasificador se simplifica a un par de lineas y el entrenamiento y el test en otro par, aquí vamos:
#Procura instalarte primero las librerías usadas y tener python 3
#Clasificacion Lineal
from sklearn.cross_validation import train_test_split
from sklearn import preprocessing
from sklearn import datasets
from sklearn.linear_model import SGDClassifier
import matplotlib.pyplot as plt
from matplotlib import style
import numpy as np
style.use(“fivethirtyeight”)
#gracias a Newton la librería sklearn tiene un data set para que “entrenes” en lo que consigues
#uno según tu trabajo, el database de aqui lo puedes buscar en google para ver como
#seleccionamos los atributos, esta parte es muy importante para hacer las predicciones #correctamente, unos atributos o features que no tienen nada que aportar simplemente #generan incertidumbre, pierdes el tiempo
iris = datasets.load_iris()
X_iris, y_iris = iris.data, iris.target
#consigues la base de datos con solamente dos atributos con los que trabajaremos
#de hecho aqui trabajaremos con length y width de las flores
#ojo: X_iris[:, :2] es notacion de arrays en python
X,y = X_iris[:,:2],y_iris
#Con este pequeño trocillo de código partimos el dataset en testing y training data
#El test se toma con 25% de la base de datos tomados aleatoriamente, randomizado
""“Porque tomamos de forma randomizada?
Puede que nuestro data set tenga de cienta forma una distribucion no homogenea por lo que nos aseguramos de que estemos tomando una buena representacion de nuestros datos”""
X_train,X_test, y_train, y_test = train_test_split(X,y,test_size=0.25,random_state=33)
print(X_train.shape,y_train.shape)
#Estandarizamos los features
#Escalamos. Lo que se hizo aqui es para cada atributo calculamos el promedion sustraemos
#es claro que este campo usa mucha estadística, preparate para amarlas!
scaler = preprocessing.StandardScaler().fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)
#despues de escalar cada atributo tendrá cero promedio con una desviacion estandar de uno
#esto lo veras mejor cuando se presente el gráfico, esta estandarizacion no cambia la #distribucion, es un requerimiento de los métodos del machine learning, para evitar atributos
#con valores que pesen mucho en los resultados finales
colors = [‘red’,‘greenyellow’,‘blue’]
for i in range(len(colors)):
xs = X_train[:, 0][y_train ==i]
ys = X_train[:, 1][y_train ==i]
plt.scatter(xs,ys,c=colors[i])
plt.legend(iris.target_names)
plt.xlabel(“Sepal length”)
plt.ylabel(“Sepal width”)
plt.show()
#graficamos aqui arriba, te debe salir como arribita
#aplicamos gradient descent o gradiente descendiente
#este algoritmo se llama Stochastic Gradient Descent y scikit-learn es amable de brindarnoslo
#y esto es el core de nuestro entrenamiento para realizar las predicciones
clf = SGDClassifier()
clf.fit(X_train,y_train)
#fit es super importante aqui va el data para el training, todos los metodos en
#sklearn(la libreria de python) lo implementan
print(clf.coef_)
print()
print(clf.intercept_)
#Si te das cuenta al imprimir el coeficiente, hay una matriz de dos columnas
#y tres dilas, y en la intercepcion encontramos un arreglo de tres valores
#echale ojo y date cuenta como sale esta ecuacion de ahi:
-17.62477802 - 28.53692691 * x1 + 15.05517618 * x2 = 0
#esto simplemente construye una recta que va a partir los puntos obtenidos en dos,
#flores de puntos rojos del resto
#asi nuestro algoritmo podra predecir cualquier dato de otra flor que nosotros le demos
#aqui plotearemos esto, osea graficaremos:
x_min,x_max = X_train[:, 0].min() - 0.5, X_train[:, 0].max() + 0.5
y_min, y_max = X_train[:, 1].min() - 0.5, X_train[:, 1].max() + 0.5
xs = np.arange(x_min,x_max,0.5)
fig, axes = plt.subplots(1,3)
fig.set_size_inches(10,6)
for i in [0,1,2]:
axes[i].set_aspect(“equal”)
axes[i].set_title(‘Class’+str(i)+‘versus the rest’)
axes[i].set_xlabel(‘Sepal length’)
axes[i].set_ylabel(‘Sepal Width’)
axes[i].set_xlim(x_min,x_max)
axes[i].set_ylim(y_min,y_max)
plt.sca(axes[i])
plt.scatter(X_train[:, 0],X_train[:, 1],c=y_train,cmap=plt.cm.prism)
ys = (-clf.intercept_[i] - xs * clf.coef_[i, 0])/clf.coef_[i, 1]
plt.plot(xs,ys,hold=True)
plt.show()
#ahora ejecutalo y observa la prediccion que hará de una nueva florecilla que le des
print(clf.predict(scaler.transform([[4.7,3.1]])))
#florecilla que queremos predecir su tipo solo #dandole su altura y ancho: length y width
this = clf.predict(scaler.transform([[4.7,3.1]]))
print(“Predicción: flor {}”.format(iris.target_names[this[0]]))
input()
Puede que si tienes un buen sentido común te des cuenta que la separación que hace la clasificacion lineal no es tan buena como parece, aqui la prueba es como divide unas flores de otras. Verás que hay métodos más exactos y presentaré formas de comprobar la exactitud del método.
El cero [0] que da al final es el tipo de flor, en este caso se trata de la flor roja
Hasta aqui podemos decir que nuestro algoritmo va a predecir todas las flores que le demos y funcionará incluso si conseguimos nuevos datasets? La respuesta es que no, existe algo llamado overfitting, esto es otro tema extenso que veremos a futuro, pero para explicarlo con la practica vamos a meter en nuestro anterior código las siguientes lineas, antes del input() :
print("bad idea: ")
y_train_pred = clf.predict(X_train)
print(metrics.accuracy_score(y_train,y_train_pred))
Bueno lo que esas dos lineas de código quieren decir es que estamos midiendo la accuracy o la exactitud de nuestro predictor, puedes ver el numero en tu terminal en pantalla, es algo entre 75%-85% de precisión, pero oh! Estamos midiendo la precisión sobre el train data, el dato entrenado, de hecho esto está mal es una mala idea medir la exactitud por medion del 75% de los datos que entrenamos, pero para eso dejamos el otro 25% del data test sin tocar, para hacer un testing, en esa porción de datos que es dato original, que teníamos al principio. Ahora si testeamos:
print()
print(“good practice to test on test_data 😃”)
y_pred = clf.predict(X_test)
print("real accuracy: ", metrics.accuracy_score(y_test,y_pred))
Voilá! Que pasada verdad? Es algo bajo pero del 50% no desciende, ademas nuestras features o atributos son poquitas. Ya veremos con otros datasets que podemos obtener mejor exactitud.
Echale ojo y ve probando el código, para comprender como hace esto nuestro algoritmo voy a subir la siguiente parte, la implementación sin el uso de la librería scikit-learn. Éxito!