Ошибки :
- Нет смещения, используемого в нейроне
- error = training_output-Ожидаемый_output (не наоборот) для градиента приличного
- Правило обновления веса i-го веса
w_i = w_i + learning_rate * delta_w_i
, (delta_w_i - градиент потерь по отношению к w_i) - Для квадрата потерь
delta_w_i = error*sample[i]
(i-е значение входной выборки вектора) - Поскольку у вас есть только один нейрон (один скрытый слой или размер 1), ваша модель может изучать только линейно разделимые данные (это только линейный классификатор).Примерами линейно разделяемых данных являются данные, сгенерированные такими функциями, как логические
AND
, OR
.Обратите внимание, что логическое значение XOR
не является линейно разделяемым.
Код с исправленными ошибками
import numpy as np
from scipy.special import expit as ex
rand.seed(10)
training_set=[[0,1,0],[1,0,1],[0,0,0],[1,1,1]] #The training sets and their outputs
training_outputs=[1,1,0,1] # Boolean OR of input vector
#training_outputs=[0,0,,1] # Boolean AND of input vector
weightlst=[rand.uniform(-1,1),rand.uniform(-1,1),rand.uniform(-1,1)] #Weights are randomly set with a value between -1 and 1
bias = rand.uniform(-1,1)
print('Random weights\n'+str(weightlst))
def calcout(inputs,weights, bias): #Calculate the expected output with given inputs and weights
output=bias
for i in range(len(inputs)):
output=output+(inputs[i]*weights[i])
#print('\nmy output is ' + str(ex(output)))
return ex(output) #Return the output on a sigmoid curve between 0 and 1
def adj(expected_output,training_output,weights,bias,inputs): #Adjust the weights based on the expected output, true (training) output and the weights
adjweights=[]
error=training_output-expected_output
lr = 0.1
for j, i in enumerate(weights):
adjweights.append(i+error*inputs[j]*lr)
adjbias = bias+error*lr
return adjweights, adjbias
#Train the network, adjusting weights each time
training_iterations=10000
for k in range(training_iterations):
for l in range(len(training_set)):
expected=calcout(training_set[l],weightlst, bias)
weightlst, bias =adj(expected,training_outputs[l],weightlst,bias,training_set[l])
new_instance=[1,0,0] #Calculate and return the expected output of a new instance
print('Adjusted weights\n'+str(weightlst))
print('\nExpected output of new instance = ' + str(calcout(new_instance,weightlst, bias)))
Вывод:
Random weights
[0.142805189379827, -0.14222189064977075, 0.15618260226894076]
Adjusted weights
[6.196759842119063, 11.71208191137411, 6.210137255008176]
Expected output of new instance = 0.6655563851223694
Как видно на входе [1,0,0]
, модель предсказала вероятность 0.66
, которая является классом 1 (с 0,66> 0,5).Это правильно, так как выходной класс - ИЛИ входного вектора.
Примечание:
Для изучения / понимания того, как обновляется каждый вес, можно кодировать, как описано выше, но на практике все операции векторизованы.Проверьте ссылку для векторизованной реализации.