Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import numpy as np
- from sklearn.model_selection import train_test_split
- from sklearn import datasets
- import matplotlib.pyplot as plt
- # Só para mostrar uma barrinha durante o processo de treino, para poder
- # monitorar a etapa do processo, pois a geração de gráfico em tempo
- # real (plt.ion()) é bem chatinha no que diz respeito a desempenho.
- from tqdm import tqdm
- #Classe do Perceptron
- class Perceptron:
- # Definindo o numero de iterações e a taxa de aprendizado
- def __init__(self, learning_rate=0.01, n_iters=1000):
- self.lr = learning_rate
- self.n_iters = n_iters
- self.activation_func = self._unit_step_func
- self.weights = None
- self.bias = None
- #Aqui você define o tempo de delay (em segundos) entre cada render do
- #plot. Veja que, independente do hardware, implementar um render em
- #tempo real sempre reduz o desempenho do seu algoritmo, pois é
- #necerssário forçar um delay entre as iterações.
- self.delay = 1e-5
- #Adicionei o argumento optativo de plotar o gráfico do treinamento em
- #tempo real. Por padrão ele é True, forçando o plot do treinamento em
- #tempo real, mas se chamar esse metodo com
- #"obj.fit(x_train, y_train, plot_train=False)", o algoritmo irá rodar
- #como você fez inicialmente. Fiz essa implementação só para que você
- #pudesse comparar desempenho com maior facilidade.
- def fit(self, X, y, plot_train: bool=True):
- n_samples, n_features = X.shape
- # inicializando os parametros
- self.weights = np.zeros(n_features)
- self.bias = 0
- y_ = np.array([1 if i > 0 else 0 for i in y])
- if plot_train:
- #Aqui gerou-se o gráfico inicial, veja que o gráfico iterativo não
- #funciona com o render "inline", portanto use outro render, caso
- #esteja usando ipython/jupyter ("%matplotlib qt", por exemplo)
- self._x_init = np.amin(X[:,0])
- self._x_end = np.amax(X[:,0])
- y_init = 0
- y_end = 0
- plt.ion() #Liga o modo de gráfico iterativo
- self.fig = plt.figure()
- plt.scatter(X[:,0], X[:,1], marker='o', c=y)
- self.plt_ax = self.fig.add_subplot(1, 1, 1)
- self.plt_ax.grid(True)
- self.plt_line = self.plt_ax.plot([self._x_init, self._x_end],
- [y_init, y_end], 'k')
- plt.draw() #Desenha a linha do plot
- self.fig.show()
- #Pausa necessária para que o render não trave,
- #dependendo da máquina talvez seja necessário aumentar esse tempo.
- #Subir ele até "1e-3" no máximo usualmente resolve os problemas
- #caso estes existam.
- plt.pause(self.delay)
- #Veja que o "tqdm" foi aplicado no "iterator", mas, como citei no
- #import, é só estético, se quiser tirar a barrinha, pode
- #tirar o "tqdm".
- for _ in tqdm(range(self.n_iters)):
- for idx, x_i in enumerate(X):
- linear_output = np.dot(x_i, self.weights) + self.bias
- y_predicted = self.activation_func(linear_output)
- # Perceptron update rule
- update = self.lr * (y_[idx] - y_predicted)
- self.weights += update * x_i
- self.bias += update
- if plot_train:
- #Chama o método para atualizar o plot a cada iteração.
- self._update_train_plot()
- def predict(self, X):
- linear_output = np.dot(X, self.weights) + self.bias
- y_predicted = self.activation_func(linear_output)
- return y_predicted
- def _unit_step_func(self, x):
- return np.where(x>=0, 1, 0)
- def _update_train_plot(self):
- y_init = (-self.weights[0] * self._x_init - self.bias) \
- / self.weights[1]
- y_end = (-self.weights[0] * self._x_end - self.bias) \
- / self.weights[1]
- #Essas duas linhas (pop e remove) são responsáveis por apagar a
- #linha antiga do plot.
- self.plt_line = self.plt_line.pop(0)
- self.plt_line.remove()
- #Cria a nova linha
- self.plt_line = self.plt_ax.plot([self._x_init, self._x_end],
- [y_init, y_end], 'k')
- #Assim como no plot inicial, desenha a nova linha e espera um tempo
- #para que o novo plot seja renderizado.
- plt.draw()
- plt.pause(self.delay)
- def accuracy(y_true, y_pred):
- accuracy = np.sum(y_true == y_pred) / len(y_true)
- return accuracy
- # Gerando duas classes de dados que são linearmente separaveis
- X, y = datasets.make_blobs(n_samples=150,n_features=2,centers=2,cluster_std=1.05,random_state=2)
- X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=123)
- p = Perceptron(learning_rate=0.01, n_iters=1000)
- p.fit(X_train, y_train, plot_train=True)
- predictions = p.predict(X_test)
- print("Perceptron classification accuracy", accuracy(y_test, predictions))
- fig = plt.figure()
- ax = fig.add_subplot(1,1,1)
- plt.scatter(X_train[:,0], X_train[:,1],marker='o',c=y_train)
- x0_1 = np.amin(X_train[:,0])
- x0_2 = np.amax(X_train[:,0])
- x1_1 = (-p.weights[0] * x0_1 - p.bias) / p.weights[1]
- x1_2 = (-p.weights[0] * x0_2 - p.bias) / p.weights[1]
- ax.plot([x0_1, x0_2],[x1_1, x1_2], 'k')
- ymin = np.amin(X_train[:,1])
- ymax = np.amax(X_train[:,1])
- ax.set_ylim([ymin-3,ymax+3])
- plt.show()
- #Este seu problema converge muito rapidamente pois seus conjuntos já estão
- #bem agrupados, assim, não é possível acompanhar a linha se movendo em tempo
- #real. Se quiser verificar este efeito, aumente o tempo de delay
- #na propriedade self.delay. Se você colocar 1 segundo, verá nitidamente o
- #avanço do treinamento mas as iteraçãoes demorarão MUITO, talvez sendo
- #necessário interromper o prcesso. Tenta usar outro conjunto de dados,
- #menos organizados, para testar.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement