Nesta trabalho, treinaremos um modelo de regressão linear usando descendência de gradiente estocástico no conjunto de dados da Qualidade do Vinho. O exemplo pressupõe que uma cópia CSV do conjunto de dados está no diretório de trabalho atual com o nome do arquivo winequality-white.csv.
O conjunto de dados de qualidade do vinho envolve a previsão da qualidade dos vinhos brancos em uma escala, com medidas químicas de cada vinho. É um problema de classificação multiclasse, mas também pode ser enquadrado como um problema de regressão. O número de observações para cada classe não é equilibrado. Existem 4.898 observações com 11 variáveis de entrada e 1 variável de saída. Os nomes das variáveis são os seguintes:
O desempenho de referencia de predição do valor médio é um RMSE de aproximadamente 0.148 pontos de qualidade.
Utilize o exemplo apresentado no tutorial e altere-o de forma a carregar os dados e analisar a acurácia de sua solução.
In [1]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
In [2]:
def RMSE(errors):
return np.sqrt(1/errors.shape[1] * np.sum(errors**2))
def predict(X, coef, addOnes=False):
if(addOnes): X = np.append(np.ones([X.shape[0], 1]), X, axis=1)
return np.dot(X, coef).reshape(1, X.shape[0])
def stochasticGD(X, y, alfa=0.00001, maxEpoch=50):
X = np.append(np.ones([X.shape[0], 1]), X, axis=1)
coef = np.random.randn(X.shape[1], 1)
errorHist = []
for epoch in range(maxEpoch):
error = predict(X, coef) - y
errorHist.append(RMSE(error))
for i in range(X.shape[0]):
coef[0] -= alfa * error[0,i]
for j in range(len(coef)-1):
coef[j+1] -= alfa * error[0,i] * X[i,j]
print("Epoch: {} | RMSE: {}".format(epoch, errorHist[-1]))
print("Coefficients: \n", coef.T)
print("\n###")
return coef, errorHist
In [3]:
data = pd.read_csv("winequality-white.csv", delimiter=";")
X = MinMaxScaler().fit_transform(data.values[:,:-1])
y = data.values[:,-1]
In [4]:
[coef, errorHist] = stochasticGD(X, y)
In [5]:
print("Gradiente Descendente Estocástico\nRMSE: {}".format(RMSE(y - predict(X, coef, True))))
print("Coeficientes:\n", coef.T)
In [6]:
plt.plot(errorHist)
plt.show()
In [7]:
X = np.append(np.ones([X.shape[0], 1]), X, axis=1)
beta = np.dot(np.dot(np.linalg.pinv(np.dot(X.T,X)), X.T), y)
print("Métodos dos Mínimos Quadrados\nRMSE: {}".format(RMSE(y - predict(X,beta))))
print("Coeficientes:\n", beta)
Obs.: Os dados desse dataset foram disponibilizados pela Universidade do Minho (Portugal) :P
Primeiramente, é interessante notar que os dados de saída ($Y$), o atributo "Quality", possue apenas valores discretos e bastante baixos. Em contra-partida, os atributos de entrada ($X$) se apresentam em várias escalas, e podem ser bem maiores que os valores de saída. Por esse motivo, para manter a estabilidade do Stochastic Gradient Descent, é necessário realizar algum tipo de Feature Scaling para normalizar os dados de entrada, gerando assim um treinamento mais estável.
No meu código, utilizei a classe MinMaxScaler do próprio Scikit-Learn para realizar essa normalização de forma rápida. O Min-Max Scaling consiste em, para cada atributo, subtrair todos os valores pelo menor valor e dividir isso pela diferença entre o maior e menor valor. Isso garante, então, que todos os dados serão dispostos no intervalo fechado [0, 1].
No meu código, também, utilizei a notação matricial das operações entre os coeficientes ($\beta$) e os dados de entrada ($X$). Isso permite uma computação mais rápida, com menos linhas de códigos, e ainda mantém todas as características originais do problema. Uma outra estivativa de coeficientes, utilizando o Método dos Mínimos Quadrados, também foi apresentada e mostrou resultados similares aos do Gradiente Descendente Estocástico.