1

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)

france1
  • 141
  • 2
  • 12
  • Is the overflow occurring on a particular value from that dataset? Could your reproduce it with a much smaller dataset? – Stef Apr 21 '22 at 08:43
  • It's always the same (edited the post) – france1 Apr 22 '22 at 08:15
  • I don't know why the values are that large, take a look at this question: https://stackoverflow.com/questions/71920991/how-can-i-format-a-file-to-a-multidimensional-numpy-array-for-my-ai – france1 Apr 22 '22 at 08:17
  • Restoring the old s and trying to continue does not work too. – france1 Apr 22 '22 at 09:07
  • A much smaller dataset doesn't work too (120/6) – france1 Apr 22 '22 at 09:17
  • The point of using a much smaller dataset is that you can pinpoint the issue more precisely. And you can include your dataset, hardcoded in your code, so that the code you include in your question forms a [mre]. Then it's easier for people who read your question to help you. – Stef Apr 22 '22 at 09:24
  • The problem is that my dataset has 5 inputs, so it'd be hard to actually make one. – france1 Apr 22 '22 at 11:38
  • If **you** can't reproduce the issue, we probably can't either ;-) – Stef Apr 22 '22 at 11:55
  • I can reproduce the issue but it would be too much work to create a smaller dataset by hand. – france1 Apr 22 '22 at 15:52

1 Answers1

1

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 million.

eta=0.00000001 does it. 100% correct (400 iterations needed).

france1
  • 141
  • 2
  • 12
  • That is not how millions work. One million is one million, USA or not. One USA billion is a thousand millions. One non-USA billion is a thousand USA billions. – Stef May 03 '22 at 07:49
  • I got confused but if I remember correctly a USA trillion is a real billion. – france1 May 03 '22 at 13:17
  • Indeed. USA -llions go 1000 by 1000; whereas non-USA -llions go million by million. Here is a correspondence table: `[('usa', 'non-usa', 'power of 10'), ('million', 'million', 6), ('billion', '1000 millions', 9), ('trillion', 'billion', 12), ('quadrillion', '1000 billions', 15), ('quintillion', 'trillion', 18)]` – Stef May 03 '22 at 13:20