
Сегодня мы поговорим о нейронах и степенных рядах. Поехали!
Рассмотрим функцию синуса.








Как можно заметить,с увеличением степенного ряда также увеличивается и точность
Рассмотрим один нейрон с одним входом и одним выходом
Как вы считаете, сколько входов должно быть у нейрона с одним входом и одним выходом для корректной работы?
У этого нейрона должно быть два входа. Один вход - x (переменная, которая поступает на вход нейрона) и единичка (биас).
Следующий вопрос. Какое преобразование нужно сделать с любым числом для того,чтобы превратить это число в 1 (единичку).
Правильно, возвести любое число в нулевую степень.

Это было предположение для одного нейрона. Напишем нейронную сеть,которая будет классифицировать наборы одежды fashion_mnist (футболки, кеды, штаны и т.д.). На вход нейросети подается 28*28 8-битная черно-белая картинка. Нейросеть содержит скрытый слой из 300 нейронов,и имеет 10 выходов. При обучении набора каждому из предметов одежды назначен класс от 0 до 10. Нейросеть должна научиться распознавать элементы одежды (отличать брюки от футболок и т.д.).
Я скачал тренировочный и тестовый наборы одежды с гитхаба по ссылке
Нейросеть будет состоять из входных (виртуальных) входов и связанных с весами(действительных) входов.
Примерная схема нейросети с двумя входными (виртуальными) нейронами,одним выходным и шестью(действительными) нейронами на входе нейросети.

x,x2,x3-это виртуальные входы нейросети,а x^0,x^1,x^2,x2^0,x2^1,x2^2 - действительные (связанные с весами)
err2=w1*err1
err3=w2*err1
err4=w3*err1
err5=w4*err1
err6=w5*err1
err6=w6*err1
err8=err2+err3+err4
err9=err5+err6+err7
w1+=speed_edication*x^0*err2*f(x^0)*(1-f(x^0))
w2+=speed_edication*x^1*err3*f(x^0)*(f-f(x^1))
w3+=speed_edication*x^2*err2*f(x^0)*(1-f(x^0))
w4+=speed_edication*x2^0*err3*f(x2^0)*(f-f(x2^0))
w5+=speed_edication*x2^1*err2*f(x2^1)*(1-f(x2^1))
w6+=speed_edication*x2^2*err3*f(x2^2)*(f-f(x2^2))
где f(x) = 1/(1+exp(-x))
Осталось сделать нейросеть для обучения её на тренировочном наборе и проверки её на тестовом наборе.
Написал простую нейросеть для проверки.
import numpy as np from numpy import genfromtxt OUT_CLASSES=10 HIDDEN_LEN=300 SPEED_EDICATION=0.00001 EPOCHS=3000 power1=2 power2=2 train = genfromtxt('fashion_train.csv', delimiter=',') train=train[1:,:] train_x=np.array(train[:,:-1]) train_x/=255 train_y=np.array(train[:,-1]) train_y = train_y.astype(int) out = np.zeros(OUT_CLASSES*len(train_y)) index_arr=np.reshape(train_y,(1,len(train_y))) out = np.reshape(out,(OUT_CLASSES,len(train_y))) np.put_along_axis(out,np.array(index_arr),1,axis=0) train_y=out.T test = genfromtxt('fashion_test.csv', delimiter=',') test=test[1:,:] test_x=np.array(test[:,:-1]) test_x/=255 test_y=np.array(test[:,-1]) test_y = test_y.astype(int) out = np.zeros(OUT_CLASSES*len(test_y)) index_arr=np.reshape(test_y,(1,len(test_y))) out = np.reshape(out,(OUT_CLASSES,len(test_y))) np.put_along_axis(out,np.array(index_arr),1,axis=0) test_y=out.T weight1=2*np.random.random((power1*int(train_x.size/len(train_x)),HIDDEN_LEN))-1 weight2=2*np.random.random((HIDDEN_LEN*power2,OUT_CLASSES))-1 power1_arr = np.tile(np.arange(power1),train_x.size).reshape(train_x.size,power1) power2_arr = np.tile(np.arange(power2),HIDDEN_LEN*len(train_x)).reshape(HIDDEN_LEN*len(train_x),power2) power1_arr_test = np.tile(np.arange(power1),test_x.size).reshape(test_x.size,power1) power2_arr_test = np.tile(np.arange(power2),HIDDEN_LEN*len(test_x)).reshape(HIDDEN_LEN*len(test_x),power2) train_x2=np.reshape(train_x,(train_x.size,1)) test_x2=np.reshape(test_x,(test_x.size,1)) virtual_train_x = np.power(train_x2,power1_arr).reshape(len(train_x),int(power1*train_x.size/len(train_x))) virtual_test_x = np.power(test_x2,power1_arr_test).reshape(len(test_x),int(power1*test_x.size/len(test_x))) someones = np.ones(power1) persent_train = np.ones(OUT_CLASSES).reshape(OUT_CLASSES,1) persent_test = np.ones(OUT_CLASSES).reshape(OUT_CLASSES,1) max_persent = 0 error_test_list=[] error_train_list=[] error_test_list_persent=[] error_train_list_persent=[] for step in range(EPOCHS): hidden_layer = 1/(1+np.exp(-(np.dot(virtual_train_x,weight1)))) hidden_layer2 = np.reshape(hidden_layer,(hidden_layer.size,1)) virtual_hidden_layer_train = np.power(hidden_layer2,power2_arr).reshape(len(hidden_layer),int(power2*hidden_layer.size/len(hidden_layer))) out_with_error = 1/(1+np.exp(-(np.dot(virtual_hidden_layer_train,weight2)))) error_w2 = (train_y-out_with_error) weight2+=SPEED_EDICATION*virtual_hidden_layer_train.T.dot(error_w2*out_with_error*(1-out_with_error)) error_w1 = error_w2.dot(weight2.T) error_w1_reshaped = np.reshape(error_w1,(int(error_w1.size/power1),power1)) error_w1_virtual = np.reshape(np.dot(error_w1_reshaped,someones),(len(error_w1),int(error_w1.size/power1/len(error_w1)))) weight1+=SPEED_EDICATION*virtual_train_x.T.dot(error_w1_virtual) hidden_layer_test = 1/(1+np.exp(-(np.dot(virtual_test_x,weight1)))) hidden_layer2_test = np.reshape(hidden_layer_test,(hidden_layer_test.size,1)) virtual_hidden_layer_test = np.power(hidden_layer2_test,power2_arr_test).reshape(len(hidden_layer_test),int(power2*hidden_layer_test.size/len(hidden_layer_test))) out_with_error_test = 1/(1+np.exp(-(np.dot(virtual_hidden_layer_test,weight2)))) error_w2_test = (test_y-out_with_error_test) p_train = np.dot(np.abs(train_y-np.around(out_with_error)),persent_train) p_test = np.dot(np.abs(test_y-np.around(out_with_error_test)),persent_test) err_p_train = 100*(1-np.sum(np.logical_and(p_train,True))/len(train_y)) err_p_test = 100*(1-np.sum(np.logical_and(p_test,True))/len(test_y)) if max_persent<err_p_test: max_persent=err_p_test error_test_list.append(np.sum(np.square(error_w2_test))/2) error_train_list.append(np.sum(np.square(error_w2))/2) error_test_list_persent.append(err_p_test) error_train_list_persent.append(err_p_train) print("step =",step,"/",EPOCHS," error train = ",np.sum(np.square(error_w2))/2," error test = ",np.sum(np.square(error_w2_test)/2)) print("step =",step,"/",EPOCHS," error train = ",err_p_train,"%"," error test = ",err_p_test,"%") print("step =",step,"/",EPOCHS," max persent test = ",max_persent,"%") list_size = len(error_train_list) data = error_train_list data.extend(error_test_list) data.extend(error_train_list_persent) data.extend(error_test_list_persent) data = np.reshape(data,(4,list_size)) np.savetxt('out.csv',data.T,delimiter=',',fmt='%.4f')
Я также решил использовать cupy,для того,чтобы программа работала на видеокарте.
import numpy as np from numpy import genfromtxt import cupy as cp OUT_CLASSES=10 HIDDEN_LEN=300 SPEED_EDICATION=0.00001 EPOCHS=1000 power1=2 power2=2 train = genfromtxt('fashion_train.csv', delimiter=',') train=train[1:,:] train_x=np.array(train[:,:-1]) train_x/=255 train_y=np.array(train[:,-1]) train_y = train_y.astype(int) out = np.zeros(OUT_CLASSES*len(train_y)) index_arr=np.reshape(train_y,(1,len(train_y))) out = np.reshape(out,(OUT_CLASSES,len(train_y))) np.put_along_axis(out,np.array(index_arr),1,axis=0) train_y=cp.array(out.T) test = genfromtxt('fashion_test.csv', delimiter=',') test=test[1:,:] test_x=np.array(test[:,:-1]) test_x/=255 test_y=np.array(test[:,-1]) test_y = np.array(test_y.astype(int)) out = np.zeros(OUT_CLASSES*len(test_y)) index_arr=np.reshape(test_y,(1,len(test_y))) out = np.reshape(out,(OUT_CLASSES,len(test_y))) np.put_along_axis(out,np.array(index_arr),1,axis=0) test_y=cp.array(out.T) weight1=cp.array(2*np.random.random((power1*int(train_x.size/len(train_x)),HIDDEN_LEN))-1) weight2=cp.array(2*np.random.random((HIDDEN_LEN*power2,OUT_CLASSES))-1) power1_arr = np.tile(np.arange(power1),train_x.size).reshape(train_x.size,power1) power2_arr = np.tile(np.arange(power2),HIDDEN_LEN*len(train_x)).reshape(HIDDEN_LEN*len(train_x),power2) power1_arr_test = np.tile(np.arange(power1),test_x.size).reshape(test_x.size,power1) power2_arr_test = cp.array(np.tile(np.arange(power2),HIDDEN_LEN*len(test_x)).reshape(HIDDEN_LEN*len(test_x),power2)) train_x2=np.reshape(train_x,(train_x.size,1)) test_x2=np.reshape(test_x,(test_x.size,1)) virtual_train_x = cp.array(np.power(train_x2,power1_arr).reshape(len(train_x),int(power1*train_x.size/len(train_x)))) virtual_test_x = cp.array(np.power(test_x2,power1_arr_test).reshape(len(test_x),int(power1*test_x.size/len(test_x)))) someones = cp.array(np.ones(power1)) persent_train = cp.array(np.ones(OUT_CLASSES).reshape(OUT_CLASSES,1)) persent_test = cp.array(np.ones(OUT_CLASSES).reshape(OUT_CLASSES,1)) max_persent = 0 error_test_list=[] error_train_list=[] error_test_list_persent=[] error_train_list_persent=[] for step in range(EPOCHS): hidden_layer = 1/(1+cp.exp(-(cp.dot(virtual_train_x,weight1)))) hidden_layer2 = cp.reshape(hidden_layer,(hidden_layer.size,1)) virtual_hidden_layer_train = cp.power(hidden_layer2,cp.array(power2_arr)).reshape(len(hidden_layer),int(power2*hidden_layer.size/len(hidden_layer))) out_with_error = 1/(1+cp.exp(-(cp.dot(virtual_hidden_layer_train,cp.array(weight2))))) error_w2 = (cp.array(train_y)-out_with_error) weight2+=SPEED_EDICATION*virtual_hidden_layer_train.T.dot(error_w2*out_with_error*(1-out_with_error)) error_w1 = error_w2.dot(weight2.T) error_w1_reshaped = cp.reshape(error_w1,(int(error_w1.size/power1),power1)) error_w1_virtual = cp.reshape(cp.dot(error_w1_reshaped,someones),(len(error_w1),int(error_w1.size/power1/len(error_w1)))) weight1+=SPEED_EDICATION*virtual_train_x.T.dot(error_w1_virtual) hidden_layer_test = 1/(1+cp.exp(-(cp.dot(virtual_test_x,weight1)))) hidden_layer2_test = cp.reshape(hidden_layer_test,(hidden_layer_test.size,1)) virtual_hidden_layer_test = cp.power(hidden_layer2_test,power2_arr_test).reshape(len(hidden_layer_test),int(power2*hidden_layer_test.size/len(hidden_layer_test))) out_with_error_test = 1/(1+np.exp(-(np.dot(virtual_hidden_layer_test,weight2)))) error_w2_test = (test_y-out_with_error_test) p_train = cp.dot(cp.abs(train_y-cp.around(out_with_error)),persent_train) p_test = cp.dot(cp.abs(test_y-cp.around(out_with_error_test)),persent_test) err_p_train = 100*(1-cp.sum(np.logical_and(p_train,True))/len(train_y)) err_p_test = 100*(1-cp.sum(np.logical_and(p_test,True))/len(test_y)) if max_persent<err_p_test: max_persent=err_p_test error_test_list.append(cp.sum(cp.square(error_w2_test))/2) error_train_list.append(cp.sum(cp.square(error_w2))/2) error_test_list_persent.append(err_p_test) error_train_list_persent.append(err_p_train) print("step =",step,"/",EPOCHS," error train = ",np.sum(np.square(error_w2))/2," error test = ",np.sum(np.square(error_w2_test)/2)) print("step =",step,"/",EPOCHS," error train = ",err_p_train,"%"," error test = ",err_p_test,"%") print("step =",step,"/",EPOCHS," max persent test = ",max_persent,"%") list_size = len(error_train_list) data = error_train_list data.extend(error_test_list) data.extend(error_train_list_persent) data.extend(error_test_list_persent) data=cp.array(data) data = cp.ndarray.get(cp.reshape(data,(4,list_size))) np.savetxt('out.csv',data.T,delimiter=',',fmt='%.4f')
Получил некоторые результаты.
Использовал power1=2,power2=2,коэффициент скорости обучения равен 0.00001,количество эпох=3000.


Получил максимальную ошибку(в процентах) тестового набора error=58.6%
Использовал power1=3,power2=3,коэффициент скорости обучения равен 0.00001,количество эпох=3000.


Получил максимальную ошибку(в процентах) тестового набора error=61,6%
Использовал power1=4,power2=4,коэффициент скорости обучения равен 0.000001,количество эпох=60000.


Получил максимальную ошибку(в процентах) тестового набора error=62.7%
Использовал power1=5,power2=5,коэффициент скорости обучения равен 0.000001,количество эпох=90000.


Получил максимальную ошибку (в процентах) тестового набора error=62.8%
Зависимость максиальной точности тестового набора от степенного ряда.

Однако среднеквадратическая ошибка вела себя странно (наверно из-за степенного ряда)

Вывод: Ошибка (в процентах) тестового обучающего набора при увеличении степенного ряда растет. Возможно, не быстро, на 0.1 или даже меньше, но с увеличением степенного ряда, количества эпох обучения и уменьшением скорости обучения можно добиться увеличения точности нейросети при работе с тестовым набором данных.
Используемая литература
Каниа Алексеевич Кан Нейронный сети. Эволюция
Тарик Рашид.Создаем нейронную сеть.
Использовалась статья Нейросеть в 11 строчек на Python
