I made an AI that uses the Adaline algorythm. It seemed to work but it results in an overflow if it's used with my own dataset.
Here's the code:
import sys
import numpy as np
from random import choice
import matplotlib.pyplot as plt
from sklearn.base import BaseEstimator,ClassifierMixin
from sklearn.utils.validation import check_X_y,check_array,check_is_fitted,check_random_state
from sklearn.utils.multiclass import unique_labels
class AdalineEstimator(BaseEstimator,ClassifierMixin):
def __init__(self,eta=.001,n_iterations=500,random_state=None,):
'''
:param eta: Learning rate
:param n_iterations: number of iterations to go through the dataset
:param random_state: you should not change that
'''
self.eta=eta
self.n_iterations=n_iterations
self.random_state=random_state
# creating arrays
self.errors=[]
self.w=[] # creating the weight array
self.wAll=[] # Weights for plotting.
def net_i(self,x):
return np.dot(x,self.w) # input array * weight array
def activation(self,x):
# Linear activation function
return self.net_i(x)
def output(self,x):
# Heaviside function
if self.activation(x) >= 0.0:
return 1
else:
return -1
def fit(self,X=None,y=None):
'''
The learning function. Adjusts the weights.
:param x: Input array
:param y: Answers
'''
random_state=check_random_state(self.random_state) # checking the random_state
self.w=random_state.random_sample(np.size(X,1))
X, y = check_X_y(X, y) # checking X and y
self.X_=X
self.y_=y
for i in range(self.n_iterations):
# Choosing a random user out of the array
rand_index=random_state.randint(0,np.size(X,0))
x_=X[rand_index]
y_=y[rand_index]
s=np.dot(x_,self.w)
print("S is: ",s)
if s != s:
print("nan encountered in S")
sys.exit(1)
error=(y_ -s)**2
self.errors.append(error)
self.w =self.eta * x_ * (y_-s)
self.wAll.append(self.w.copy())
def predict(self,x):
check_is_fitted(self,['X_','y_']) # Was the model trained before?
y_hat=self.output(x)
return y_hat
def plot(self):
""" Ausgabe des Fehlers und der Lernkurve
Die im Fehlerarray gespeicherten Fehler als Grafik ausgeben
Die Trenngeraden aus den gespeicherten Gewichten ausgeben
"""
x1 = []
x2 = []
colors = []
for i in range(self.X_.shape[0]):
x1.append(self.X_[i][1])
x2.append(self.X_[i][2])
y = self.y_[i]
if y == 1:
colors.append('r') # rot
else:
colors.append('b') # blau
# Raster
plt.style.use('seaborn-whitegrid')
# Errors
plt.plot(self.errors)
# Learning Curve
plt.figure(1)
plt.show()
# Scatter
plt.figure(2)
plt.scatter(x1, x2, c=colors)
# Result Line
x1Line = np.linspace(0.0, 1.0, 2)
x2Line = lambda x1, w0, w1, w2: (-x1 * w1 - w0) / w2;
alpha = 0.0
for idx, weight in enumerate(self.wAll):
# alpha = Transparenz, je näher zum Ziel desto dunkler
if (idx % 100 == 0):
alpha = 1.0 # ( idx / len(self.wAll) )
plt.plot(x1Line, x2Line(x1Line, weight[0], weight[1], weight[2]), alpha=alpha, linestyle='solid',
label=str(idx), linewidth=1.5)
# Ergebnisgerade
plt.plot(x1Line, x2Line(x1Line, weight[0], weight[1], weight[2]), alpha=alpha, linestyle='solid',
label=str(idx), linewidth=2.0)
plt.legend(loc='best', shadow=True)
data = []
with open('data.txt') as file:
for line in file:
dataline=float(line.rstrip())
dataline=round(dataline,-3)
data.append(dataline)
data=np.array(data)
data=data.reshape(-1,6)
X=data[:,0:5]
y=data[:,5]
#X=X[~np.isnan(X)]
Adaline = AdalineEstimator(eta=0.01, n_iterations=200, random_state=10)
Adaline.fit(X, y)
Adaline.plot()
And the dataset is here: https://pastebin.com/Vziav3Q9
The error message is somehow on the beginning (I am using pycharm at the moment, not sure if related) of the output.
RuntimeWarning:
overflow encountered in double_scalars
error=(y_ -s)**2
And then:
RuntimeWarning: invalid value encountered in multiply
self.w =self.eta * x_ * (y_-s)
How can I fix this?
This is an example:
S is: 1.9288464662803013e 290
[0. 0. 0. 0. 0.]
S is: 0.0
[ 433000. 18000. 6369000. 0. 0.]
S is: -8.776351721574362e 301
[ 5000. 0. 26000. 0. 0.]
S is: inf
[0. 0. 0. 0. 0.]
S is: nan
S is the weighted x:
s=np.dot(x_,self.w)
CodePudding user response:
Eta should be lowered as the weights are too large (I first thought that the inputs are too large but they aren't larger than one billion (or not USA: one million).
eta=0.00000001
does it. 100% correct (400 iterations needed).