Сегодня мы поговорим о нейронах и степенных рядах. Поехали!

Рассмотрим функцию синуса.

Как можно заметить,с увеличением степенного ряда также увеличивается и точность

Рассмотрим один нейрон с одним входом и одним выходом

Как вы считаете, сколько входов должно быть у нейрона с одним входом и одним выходом для корректной работы?

У этого нейрона должно быть два входа. Один вход - 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 или даже меньше, но с увеличением степенного ряда, количества эпох обучения и уменьшением скорости обучения можно добиться увеличения точности нейросети при работе с тестовым набором данных.

Используемая литература

  1. Каниа Алексеевич Кан Нейронный сети. Эволюция

  2. Тарик Рашид.Создаем нейронную сеть.

  3. Использовалась статья Нейросеть в 11 строчек на Python