Я пытаюсь построить простую ИНС с нуля. Я сделал ИНС с одним слоем, он отлично работает. когда я запускаю функцию обучения
def ANN(x_train,y_train,layers,validation_data=None,epochs=1,num_iteration=1000,learning_rate=0.001,verbose=0):
"""" x_train :- shape should be (nx,nm)
layers :- list of tuple (units,activation)"""
assert(len(x_train.shape)==2)
if validation_data != None:
assert(len(validation_data[0].shape)==2)
n_layers=[]
n_layers.append(x_train.shape[0])
for unit in layers:
n_layers.append(unit[0])
parameters=initilize_weights(n_layers)
costs=[]
val_costs=[]
for epoch in range(epochs):
print('{} epoch is starting => => => :-'.format(epoch+1) )
for i in range(1,num_iteration+1):
#farward propogation
A,cache=farward_prop(x_train,layers,parameters)
#computing cost
cost=compute_cost(A,y_train)
# computing validation loss
if validation_data is not None:
y_val,_=farward_prop(validation_data[0],layers,parameters)
val_cost=compute_cost(y_val,validation_data[1])
# back propogation
parameters=back_prop(y_train, A, cache, layers, parameters, learning_rate)
if validation_data is not None:
if verbose==1 and i % 100 == 0:
val_costs.append(val_cost)
costs.append(cost)
print("\t{}--> train_loss= {} ,val_loss = {}".format(i,cost,val_cost))
if validation_data==None and verbose==1 and i % 100 == 0:
val_costs.append(val_cost)
costs.append(cost)
print("\t{}--> train_loss= {}".format(i,cost))
if validation_data is not None:
history={"parameters":parameters,"loss":costs,"val_loss":val_costs,'layers':layers}
else:
out_values={"parameters":parameters,"loss":costs,'layers':layers}
return(history)
Теперь проблемы:
стоимость очень медленно снижается даже после изменения скорости обучения
значение активации почти такой же
[[0,64890071 0,64889985 0,64889935 0,64890274 0,64890465 0,64890174 0,64890006 0,64890301 0,64889855 0,64890125 0,6488997 0,64890018 0,64890082 0,64890281 0,64890247 0,64889474 0,64889993 0,64889987 0,64890059 0,64890474 0,648899 0,64890058 0,64889982 0,64889554 0,64890257 0,64889887 0,64890185 0,64890173 0,64890024 0,64890169]]
Я пробовал нормализовать данные, а также небольшие веса, это не эффективно. Для данных проверки он предсказывает либо все, либо все нули
back_prop
def back_prop(y,A,cache,layers,parameters,learning_rate):
m=len(y)
dA= -(np.divide(y, A) - np.divide(1 - y ,1 - A))
L=len(layers)
grad={}
for l in reversed(range(1,L+1)):
dz=np.multiply(dA,back_activation(cache['Z'+str(l)],layers[l-1][1]))
dw=np.dot(dz,cache['A'+str(l-1)].T)
db=np.sum(dz,axis=1,keepdims=True)
dA=np.dot(parameters['W'+str(l)].T,dz)
grad['dW'+str(l)]=dw
grad['db'+str(l)]=db
for l in range(1,L):
parameters['W'+str(l)]=parameters['W'+str(l)]-(1/m)*learning_rate*grad['dW'+str(l)]
parameters['b'+str(l)]=parameters['b'+str(l)]-(1/m)*learning_rate*grad['db'+str(l)]
return(parameters)
forward_prop
def forward_prop(X,layers,parameters):
"""layers :- it is a list of tuple (units,activation) """
cache={}
L= len(layers)
A_prev=X
cache['A0']=A_prev
for l in range(1,L+1):
z=np.dot(parameters['W'+str(l)],A_prev)+parameters['b'+str(l)]
A_prev=activation_prop(z,layers[l-1][1])
cache['Z'+str(l)]=z
cache['A'+str(l)]=A_prev
return(A_prev,cache)
weight_initializer
def initilize_weights(n_layers):
""""n_layers :- list of integer which specifies number of units in 0,1,2,......L layers
L is last layer"""
parameters={}
for l in range(1,len(n_layers)):
parameters['W'+str(l)]=np.random.randn(n_layers[l],n_layers[l-1])*0.0001
parameters['b'+str(l)]=np.random.rand(n_layers[l],1)
return(parameters)