【问题标题】:Why does Dropout deteriorates my model accuracy?为什么 Dropout 会降低我的模型准确性?
【发布时间】:2020-11-19 20:08:10
【问题描述】:

如果我在训练中不使用 dropout,下面的代码给出了大约 95% 的准确率。 如果我使用 dropout,准确率会下降到 11%。

网络是使用 Numpy 构建的。 我使用了一个包含许多图层对象的神经网络类。 最后一层有 sigmoid 激活,其余的有 Relu。 代码是:

import numpy as np 
import idx2numpy as idx
import matplotlib.pyplot as plt

np.random.seed(0)
img = r"C:\Users\Aaditya\OneDrive\Documents\ML\train-image"
lbl = r'C:\Users\Aaditya\OneDrive\Documents\ML\train-labels-idx1-ubyte'
t_lbl = r'C:\Users\Aaditya\OneDrive\Documents\ML\t10k-labels.idx1-ubyte'
t_img = r'C:\Users\Aaditya\OneDrive\Documents\ML\t10k-images.idx3-ubyte'
image = idx.convert_from_file(img)
iput = np.reshape(image, (60000,784))/255
otput = np.eye(10)[idx.convert_from_file(lbl)]
test_image = idx.convert_from_file(t_img)
test_input = np.reshape(test_image, (10000,784))/255
test_output = idx.convert_from_file(t_lbl)

def sigmoid(x):
    sigmoid = 1/(1+ np.exp(-x)) 
    return sigmoid
    
def tanh(x):
    return np.tanh(x)
def relu(x):
    return np.where(x>0,x,0)

def reluprime(x):
    return (x>0).astype(x.dtype)

def sigmoid_prime(x):
    return sigmoid(x)*(1-sigmoid(x))
    
def tanh_prime(x):
    return 1 - tanh(x)**2
class Layer_Dense:
    def __init__(self,n_inputs,n_neurons,activation="sigmoid",keep_prob=1):
        self.n_neurons=n_neurons
        if activation == "sigmoid":
            self.activation = sigmoid
            self.a_prime = sigmoid_prime
        elif activation == "tanh":
            self.activation = tanh
            self.a_prime = tanh_prime
        else :
            self.activation = relu
            self.a_prime = reluprime
        self.keep_prob = keep_prob
        self.weights = np.random.randn(n_inputs ,n_neurons)*0.1
        self.biases = np.random.randn(1,n_neurons)*0.1 
    
    def cal_output(self,input,train=False):        
        output = np.array(np.dot(input,self.weights) + self.biases,dtype="float128")
        
        if train == True:
            D = np.random.randn(1,self.n_neurons)
            self.D = (D>self.keep_prob).astype(int)
            output = output * self.D  
        return output
    def forward(self,input):
        return self.activation(self.cal_output(input))
    def back_propagate(self,delta,ap,lr=1,keep_prob=1):
        dz =  delta
        self.weights -= 0.001*lr*(np.dot(ap.T,dz)*self.D)
        self.biases -= 0.001*lr*(np.sum(dz,axis=0,keepdims=True)*self.D)
        return np.multiply(np.dot(dz,self.weights.T),(1-ap**2))
        

class Neural_Network:
    def __init__(self,input,output):
        self.input=input
        self.output=output
        self.layers = []
    def Add_layer(self,n_neurons,activation="relu",keepprob=1):
        if len(self.layers) != 0:    
            newL = Layer_Dense(self.layers[-1].n_neurons,n_neurons,activation,keep_prob=keepprob)
        else:
            newL = Layer_Dense(self.input.shape[1],n_neurons,activation,keep_prob=keepprob)
        self.layers.append(newL)
    def predict(self,input):
        output = input
        for layer in self.layers:
            output = layer.forward(output)
        return output
    def cal_zs(self,input):
        self.activations = []
        self.activations.append(input)
        output = input
        for layer in self.layers:
            z = layer.cal_output(output,train=True)
            activation = layer.activation(z)
            self.activations.append(activation)
            output = activation
    def train(self,input=None,output=None,lr=10):
        if input is None:
            input=self.input
            output=self.output
            
        if len(input)>1000:
            indices = np.arange(input.shape[0])
            np.random.shuffle(indices)
            input = input[indices]
            output = output[indices]
            for _ in range(100):
                self.lr = lr
                for i in range(int(len(input)/100)):
                    self.lr *=0.99
                    self.train(input[i*100:i*100+100],output[i*100:i*100+100],self.lr)
            return
        self.cal_zs(input)
        for i in range(1,len(self.layers)+1):
            if i==1:
                delta = self.activations[-1] - output
                self.delta = self.layers[-1].back_propagate(delta,self.activations[-2],lr)
            else:
                self.delta = self.layers[-i].back_propagate(self.delta,self.activations[-i-1],lr)
    def MSE(self):
        predict = self.predict(self.input)
        error = (predict - self.output)**2
        mse = sum(sum(error))
        print(mse)
    def Logloss(self):
        predict = self.predict(self.input)
        error = np.multiply(self.output,np.log(predict)) + np.multiply(1-self.output,np.log(1-predict))
        logloss = -1*sum(sum(error))
        print(logloss)
    def accuracy(self):
        predict = self.predict(test_input)
        prediction = np.argmax(predict,axis=1)
        correct = np.mean(prediction == test_output)
        print(correct*100)
            
    # def train(self,input,output):
        
model = Neural_Network(iput,otput)
# model.Add_layer(4)
model.Add_layer(64)
model.Add_layer(16)
model.Add_layer(10,"sigmoid")
lrc= 6
for _ in range(10):
    model.accuracy()
    model.Logloss()
    model.train(lr=lrc)
model.accuracy()

我用过MNIST数据库,链接是THIS

【问题讨论】:

    标签: python machine-learning deep-learning neural-network artificial-intelligence


    【解决方案1】:

    这可能有多种原因。一个由@anuragal 指定。

    基本上 dropout 用于减少过拟合并帮助网络纠正错误。但是当你在最后一层之前使用 dropout 时,可能是网络无法自我纠正,从而导致精度降低

    另一个原因可能是我看到您的网络很小。通常,浅层网络不会从 dropouts 中受益

    【讨论】:

    • 感谢您的回答。我使用 randn 而不是 rand,所以我太多或太少的神经元被停用。我增加了网络规模,效果很好。感谢您的帮助
    【解决方案2】:

    其中一个原因可能是您丢失了过多的神经元。在下面的代码中

    D = np.random.randn(1,self.n_neurons)
    self.D = (D>self.keep_prob).astype(int)
    

    第一行生成的矩阵可能包含许多小于零的值。因此,在将其与 self.keep_prob(值为 1)进行比较时,很多神经元都被丢弃了

    请尝试一次更改

    self.D = (D < self.keep_prob).astype(int)
    

    【讨论】:

    • 感谢您的回复,我会尝试并让您知道
    • 我试过了,但结果是一样的。另外,我收到了类似 RuntimeWarning: overflow 在 exp sigmoid = 1/(1+ np.exp(-x)) 中遇到的警告
    猜你喜欢
    • 1970-01-01
    • 2020-03-22
    • 2020-06-22
    • 2012-01-18
    • 2021-05-04
    • 1970-01-01
    • 2018-02-08
    • 2018-10-23
    • 2018-12-24
    相关资源
    最近更新 更多