Форум программистов, компьютерный форум, киберфорум
Наши страницы
Konst2016
Войти
Регистрация
Восстановить пароль
Оценить эту запись

Крутой код.Самодельная нейросеть работает с mnist

Запись от Konst2016 размещена 10.10.2019 в 16:51
Обновил(-а) Konst2016 10.10.2019 в 16:55 (орфогр.)

Здравствуйте!Показываю код как нейросеть с 784 входами и 40 нейронами скрытого слоя и 10 нейронами выхода обучается на наборе mnist-черно-белых картинок рукописных цифр.
В коде происходит нормализация неактивированного состояния нейрона и после его активации(так на двух слоях),без этого в системе накапливались больше числа,и MSE выдавала как nan.Соответственно подправлен backprop(градиенты).
Код
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
"""
   Трехслойный перпецетрон
"""
 
import numpy as np
import matplotlib.pyplot as plt
 
from math import sqrt
from keras.datasets import mnist
 
from keras.utils import np_utils
 
import hashlib as hsh
 
#np.set_printoptions(threshold=np.inf) для вывода матриц полностью
 
 
 
# Зерно для генератора
np.random.seed(42)
 
bias_val=1
class NN:
 
  def nonlin(self,sygnals,deriv=False):
    
     if deriv:
           return (sygnals*(1.0-sygnals))
 
     return (1.0 / (1+np.exp(-sygnals)))
   
  def __init__(self):
 
     self.e1=None # Взвешенная сумма сигналов на первой прослойке
     self.e2=None # Взвешенная сумма сигналов на второй прослойке 
   
     self.hidden1=None # активированное состояние нейронов на первой прослойке
     self.hidden2=None # активированное состояние нейронов на второй прослойке
 
     self.learning_rate=0.001   
  
     self.init_net()
  
  def  init_net(self):
    
   
     self.in_layer1=np.random.normal(0,2**-0.5,(40,784)) 
     self.in_layer2=np.random.normal(0,2**-0.5,(10,40))
     # Говорят так лучше инициализировать веса,под дробью параметр-количество
     # дендритов-сигналов
     #self.in_layer1=np.random.randn(40,784)\
       #*sqrt(2.0/784)
     #self.in_layer2=np.random.randn(10,40)\
       #*sqrt(2.0/10)
     print("lay1 %s \n lay2 %s"%(self.show_matrix_hash(self.in_layer1,self.in_layer2)[0],self.show_matrix_hash(self.in_layer1,self.in_layer2)[1]))
     
    
  def direct_motion(self,_vector):
 
      
     self.e1=np.dot(self.in_layer1,_vector.T)
     self.e1/=784
    
     self.hidden1=self.nonlin(self.e1
                              +bias_val
                              )
     self.hidden1/=784 # Здесь все нормализовал что бы не было больших чисел
                       # ведь идет сумма произведений,которые близки к единицы
                       # а их 784
     self.e2=np.dot(self.in_layer2,self.hidden1)
     self.e2/=40      # нормализовал
     self.hidden2=self.nonlin(self.e2
                              +bias_val
                              )
     self.hidden2/=40
     return self.hidden2
 
   # for debug
  def show_matrix_hash(self,*matr):
                hash_obj=hsh.sha256()
                matr_list=['']*len(matr)
                j=0
                #:matrix<R> 
                for i  \
                    in matr:   
                         hash_obj.update(str(matr).encode('ascii'))
                         matr_list[j]=hash_obj.hexdigest()
                         j+=1
                return matr_list      
 
  
  def calculate_minimal_square_error(self,val):
 
     return np.mean(np.square(val))
   
 
  def back_propagate(self,vector, target):
  
      """
         Прямой проход
      """
      out_NN=self.direct_motion(vector)
      #print("out %s",self.show_matrix_hash(out_NN)[0])
 
      """
           Расчет ошибки 
      """
      delta_out=abs(target.T-out_NN)
      grads_out_nn=delta_out*self.nonlin(self.e2,deriv=True)
     
 
      grads_on_lay2=np.dot(grads_out_nn.T,self.in_layer2)*self.nonlin(self.e1.T,deriv=True)*1/40 # Подправлям дифференциалы
      grads_on_lay1=np.dot(grads_on_lay2,self.in_layer1)*1/784  # Подправлям дифференциалы
 
      """
         Коррекция ошибки
      """
     
      self.in_layer1+=(vector*grads_on_lay1*self.learning_rate)
     
      self.in_layer2+=(self.e1.T*grads_on_lay2*self.learning_rate)
 
      return self.calculate_minimal_square_error(delta_out)
    
  def plot_graphic_by_x_and_y(self,x,y):
      plt.plot(x,y)
      plt.show()    
 
  def learn(self,epocha:int,l_r:float,train_set,target_set):
    
     error=0.0
     self.learning_rate=l_r
     iteration:int=0
     n_epochs=[]
     n_mse=[]
     while(iteration< epocha):
       
       for i in range(train_set.shape[0]):
           
            single_2D_array_train=np.array([train_set[i]])
            single_2D_array_target=np.array([target_set[i]])
            error=self.back_propagate(single_2D_array_train,single_2D_array_target)
       if iteration % 1==0:
 
          print(error)
          n_epochs.append(iteration)
          n_mse.append(error)
           
 
       iteration+=1
     self.plot_graphic_by_x_and_y(n_epochs,n_mse)
     
 
def create_nn()->NN:
 
  return NN()     
def test():
   (X_train,y_train),(X_test,y_test)=mnist.load_data()
   
   X_train=X_train.astype('float32')
    
  
   X_train=X_train.reshape(60000,784)
  
   # Нормализация всей обучающей выборки
   X_train=X_train/255.0
   print('X_train',X_train[0])
   
   y_train=np_utils.to_categorical(y_train)    
 
   NN=create_nn()  
 
   NN.learn(100,0.7,X_train,y_train)  
#===========================
if __name__=='__main__':
   test()
#===========================
График
Нажмите на изображение для увеличения
Название: right_mse_mnist.png
Просмотров: 85
Размер:	19.1 Кб
ID:	5612
Спасибо!До свидания!
Размещено в Без категории
Просмотров 119 Комментарии 2
Всего комментариев 2
Комментарии
  1. Старый комментарий
    100…7
    График чего? Где легенда на графике( подписи к осям). Для мнист указана там на сайте выборка и процент ошибки. Там спец кусок данных берут.
    Запись от Excalibur921 размещена 10.10.2019 в 18:59 Excalibur921 вне форума
  2. Старый комментарий
    Вообще то да,графики я пока неважно освоил,все думал над backprop,C,Java коды изучал.
    Запись от Konst2016 размещена 10.10.2019 в 19:28 Konst2016 вне форума
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.