Большая ошибка теста в простой плотной нейронной сети при тренировке с SGD, но небольшая ошибка теста при тренировке с GD - PullRequest
0 голосов
/ 23 сентября 2019

Я пытаюсь написать простую нейронную сеть с одним скрытым слоем, чтобы изучить простую задачу классификации.Нейронная сеть выглядит следующим образом: вход является реальным вектором измерения d.Полностью подключенный первый слой размером 2 * k с последующей активацией LeakyRelu с альфа = 0,1.Выходной слой имеет размер один и связан со всеми скрытыми узлами.Веса в последнем выходном слое не обучаются и фиксируются следующим образом: первые k весов (соединенных с верхними k скрытыми узлами) фиксируются на 1 / sqrt (2k), а последние k весов (соединенных с нижними k скрытыми узлами)) устанавливаются в -1 / sqrt (2k).Потери на выходе - это средняя потеря шарнира: 1 / n \ sum max (0, 1 - y_i * NN_output), где NN_output - выход нейронной сети.

Я выбираю W размера dX1 так, чтобы каждая координата представляла собой одно случайное число в диапазоне (-0,5,0,5).Затем я устанавливаю координаты в W * выше 15 равными 0. Таким образом, в векторе W только первые 15 координат имеют ненулевые значения, а остальные равны нулю.Затем я генерирую i-е обучающие данные следующим образом: для каждого вектора x_i измерения dx1 я случайным образом выбираю каждую координату, которая лежит в (-0,5,0,5).Y_i для обучающих данных устанавливается как знак (W * x).В общем, W - это настоящая гиперплоскость, которую я хочу, чтобы моя нейронная сеть выучила.

Сначала я тренируюсь с GD (путем написания явной формулы), а затем с SGD.В обоих случаях ошибка обучения может быть сведена к нулю.Тем не менее, я наблюдаю, что когда я тренируюсь с GD, потеря теста (шарнира) (для случайно выбранных тестовых векторов dx1 в (-0,5,0,5)) сводится к нулю.Тем не менее, с SGD потеря теста (шарнира) всегда велика, скажем, около 1. Может кто-нибудь помочь мне понять, почему GD работает, а SGD не работает?Когда я смотрю на вектор весов каждого скрытого узла (это вектор dx1) при обучении в GD, это, похоже, масштабированная версия W. Однако для обученной сети SGD это просто случайность.Таким образом, ясно, что ошибка теста SGD будет высокой, так как на самом деле он не узнал, что вектор весов должен фокусироваться только на первых 15 координатах.Мой вопрос: почему SGD не может учиться в отличие от GD?Изменение эпох и использование других оптимизаторов, таких как Адам и т. Д., Не меняет картину выше.Большое спасибо за то, что прочитали мой вопрос и помогли мне понять, что я делаю неправильно.

import keras
import numpy as np
# Importing the required Keras modules containing model and layers
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LeakyReLU

d = 1000                # ambient dimension
d_main = 15             
k = 200                 # number of node in hidden layer = 2k
n_train = 500          # size of training data
n_test = 100            # size of test data
m = 5
eta = 0.01              # learning rate
v = 1/np.sqrt(2*k)      # mult fact for second layer

wstar = np.random.uniform(-0.5,0.5,(d,1))
wstar[d_main:wstar.shape[0]] = 0
wstar = wstar/np.linalg.norm(wstar,ord=2)
v1 = v*np.ones((k,1))
v2 = -v*np.ones((k,1))
vf = np.concatenate((v1,v2))

X_train = np.zeros((d,n_train))

for i in range(n_train):
    tempx = np.random.uniform(-0.5,0.5,(d,1))
    while np.abs(np.dot(np.transpose(wstar),tempx)) < 1:
        tempx = np.random.uniform(-0.5,0.5,(d,1))    
    X_train[:,i] = np.reshape(tempx,d)*m*np.maximum(1.0/m,np.random.uniform(0,1))


Y_train = np.transpose(np.sign(np.matmul(np.transpose(wstar),X_train)))

x_train = X_train.reshape(X_train.shape[1],d)
y_train = Y_train

opt = keras.optimizers.SGD(lr=eta)
def create_model():
    model = Sequential()    
    model.add(Dense(2*k, activation=None,use_bias=False,input_shape=(d,)))
    model.add(LeakyReLU(alpha=0.1))
    model.add(Dense(1, activation=None,use_bias=False))
    model.compile(optimizer=opt, 
                  loss='hinge', 
                  metrics=None)
    return model

model = create_model()
model.summary()

# set the second layer to be non-trainable so that it is not updated during training
layer = model.layers[2]
# set the weights of the layer to be v*(1,1,...1,-1,-1,..,-1)
layer.set_weights([vf])
layer.trainable = False
model.compile(optimizer=opt, 
                  loss='hinge', 
                  metrics=None)

model.fit(x=x_train,y=y_train, epochs=20)

# standard test error
X_test = np.zeros((d,n_test))

for i in range(n_test):
    tempx = np.random.uniform(-0.5,0.5,(d,1))
    while np.abs(np.dot(np.transpose(wstar),tempx)) < 1:
        tempx = np.random.uniform(-0.5,0.5,(d,1))     
    X_test[:,i] = np.reshape(tempx,d)*m*np.maximum(1.0/m,np.random.uniform(0,1))

Y_test = np.transpose(np.sign(np.matmul(np.transpose(wstar),X_test)))

x_test = X_test.reshape(X_test.shape[1],d)
y_test = Y_test


model.evaluate(x_test,y_test)

Программа GD ниже:


import numpy as np

d = 1000     # ambient dimension
d_main = 15  
k = 200      # number of node in hidden layer = 2k
n = 500      # size of training data
m = 5
epoch = 20
eta = 0.01
v = 1/np.sqrt(2*k)
alpha = 0.1  # leaky ReLU with param alpha

wstar = np.random.uniform(-0.5,0.5,(d,1))
wstar[d_main-1:wstar.shape[0]-1] = 0
wstar = wstar/np.linalg.norm(wstar,ord=2)

X = np.zeros((d,n))

for i in range(n):
    tempx = np.random.uniform(-0.5,0.5,(d,1))
    while np.abs(np.dot(np.transpose(wstar),tempx)) < 1:
       tempx = np.random.uniform(-0.5,0.5,(d,1))    
    X[:,i] = np.reshape(tempx,d)*m*np.maximum(1.0/m,np.random.uniform(0,1))

Y = np.transpose(np.sign(np.matmul(np.transpose(wstar),X)))

W = np.random.uniform(-0.5,0.5,(d,k))
U = np.random.uniform(-0.5,0.5,(d,k))

def sigmaprim(y,alpha):
    z = np.zeros(len(y))
    for i in range(len(y)):
        if y[i] >= 0:
            z[i] = 1
        else:
            z[i] = alpha
    return z

for e in range(epoch):
    print('epoch:=',e)         
    W_old = W         
    grad_W = np.zeros((d,k))
    grad_U = np.zeros((d,k))         
    for i in range(n):
        x = X[:,i]
        y = Y[i]         
        if  y*((np.sum(np.dot(np.transpose(W),x) - np.dot(np.transpose(U),x)))*v) < 1:
            xmat = np.tile(np.reshape(x,(d,1)),(1,k))
            b = sigmaprim(np.dot(np.transpose(W),x),alpha)
            grad_W = grad_W - y*np.matmul(xmat,np.diag(b))
            b = sigmaprim(np.dot(np.transpose(U),x),alpha)
            grad_U = grad_U + y*np.matmul(xmat,np.diag(b))                                                                                                 
        W = W - eta*grad_W
        U = U - eta*grad_U                                                               
        convergence_error = np.linalg.norm(W/np.linalg.norm(W,ord=2)-W_old/np.linalg.norm(W_old,ord=2),ord=2)

error = 0
for i in range(100):
    x = np.random.uniform(-0.5,0.5,(d,1))
    while np.abs(np.dot(np.transpose(wstar),x)) < 1:
        x = np.random.uniform(-0.5,0.5,(d,1))

    y = np.dot(np.transpose(wstar),x)

    if y*((np.sum(np.dot(np.transpose(W),x) - np.dot(np.transpose(U),x)))*v) < 1:
        error = error + 1;

print('test error:=', error/100)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...