我实施神经网络有什么问题?

Mys*_*Guy 24 python neural-network scikit-learn

在此输入图像描述我想绘制神经网络的学习误差曲线与训练样本的数量.这是代码:

import sklearn
import numpy as np
from sklearn.model_selection import learning_curve
import matplotlib.pyplot as plt
from sklearn import neural_network
from sklearn import cross_validation

myList=[]
myList2=[]
w=[]

dataset=np.loadtxt("data", delimiter=",")
X=dataset[:, 0:6]
Y=dataset[:,6]
clf=sklearn.neural_network.MLPClassifier(hidden_layer_sizes=(2,3),activation='tanh')

# split the data between training and testing
X_train, X_test, Y_train, Y_test = cross_validation.train_test_split(X, Y, test_size=0.25, random_state=33)

# begin with few training datas
X_eff=X_train[0:int(len(X_train)/150), : ]
Y_eff=Y_train[0:int(len(Y_train)/150)]

k=int(len(X_train)/150)-1


for m in range (140) :


    print (m)

    w.append(k)

    # train the model and store the training error
    A=clf.fit(X_eff,Y_eff)
    myList.append(1-A.score(X_eff,Y_eff))

      # compute the testing error
    myList2.append(1-A.score(X_test,Y_test))

    # add some more training datas
    X_eff=np.vstack((X_eff,X_train[k+1:k+101,:]))
    Y_eff=np.hstack((Y_eff,Y_train[k+1:k+101]))
    k=k+100

plt.figure(figsize=(8, 8))
plt.subplots_adjust()
plt.title("Erreur d'entrainement et de test")
plt.plot(w,myList,label="training error")
plt.plot(w,myList2,label="test error")
plt.legend()
plt.show()
Run Code Online (Sandbox Code Playgroud)

然而,我得到一个非常奇怪的结果,曲线波动,训练误差非常接近测试误差,这似乎不正常.哪里出错了?我无法理解为什么有这么多起伏,以及为什么训练错误不会增加,因为它会被期待.任何帮助将不胜感激!

编辑:我使用的数据集https://archive.ics.uci.edu/ml/datasets/Chess+%28King-Rook+vs.+King%29,我摆脱了小于1000个实例的类.我手动重新编码了litteral数据.

And*_*dnp 13

我认为您看到这种曲线的原因是您测量的性能指标与您正在优化的性能指标不同.

优化指标

神经网络最小化损失函数,并且在tanh激活的情况下,我假设您正在使用交叉熵损失的修改版本.如果你要绘制一段时间内的损失,你会看到一个像你期望的更单调递减的错误函数.(实际上并不是单调的,因为神经网络是非凸的,但这不是重点.)

绩效指标

您测量的性能指标是精度百分比,与损失不同.为什么这些不同?损失函数以可微分的方式告诉我们有多少错误(这对于快速优化方法很重要).准确度指标告诉我们我们如何预测,这对于神经网络的应用是有用的.

把它放在一起

由于您正在绘制相关指标的性能,因此您可以预期该图表看起来与优化指标的图表类似.但是因为它们不一样,你可能会在你的情节中引入一些未解释的差异(如你发布的情节所证明的那样).

有几种方法可以解决这个问题.

  1. 绘制损失而不是准确度.如果您确实需要精确度图,这实际上并不能解决您的问题,但它会为您提供更加平滑的曲线.
  2. 绘制多次运行的平均值.保存算法的20多次独立运行的准确度图(如在网络中训练20次),然后将它们平均并绘制出来.这将大大减少差异.

TL; DR

不要指望精确度图总是平滑且单调递减,它不会.


问题编辑后:

既然您已经添加了数据集,我还会看到一些其他可能导致您遇到问题的事情.

信息量大

数据集定义了几个棋子的等级和文件(行和列).这些是从1到6的整数输入.然而,2真的1比1好吗?6真的比4好4吗?我不认为就国际象棋的位置而言就是这种情况.

想象一下,我正在建立一个以金钱为输入的分类器.是否有一些信息被我的价值观所描绘?是的,1美元与100美元完全不同; 我们可以看出,存在一种基于幅度的关系.

对于国际象棋游戏,第1行是否意味着与第8行不同的东西?事实上,根本没有,这些尺寸是对称的!在网络中使用偏置单元可以通过"重新缩放"输入来帮助解决对称问题,使其有效地从[-3,4]开始,现在中心(ish)大约为0.

解决方案

但是,我认为,您可以通过平铺编码或单热编码获得最多的功能.不要让网络依赖于每个功能的大小中包含的信息,因为这可能导致网络进入糟糕的本地最佳状态.


zim*_*rol 7

除了之前的答案,您还应该记住,您可能需要调整网络learning rate(通过设置learning_rate = value初始化程序).如果您选择较大的速率,您将从局部最小值跳到另一个或绕这些点旋转,但实际上不会收敛(请参见下图,从此处获取).

此外,请同时绘制loss网络的准确性,而不仅仅是准确性.这将为您提供更好的见解.

另外,请记住,您必须使用大量的训练和测试数据来获得或多或少的"平滑"曲线,甚至是代表性的曲线; 如果您只使用几个(可能是几百个)数据点,那么得到的指标实际上并不是非常准确,因为它们包含许多随机事物.要解决此错误,您不应每次都使用相同的示例训练网络,而是更改训练数据的顺序,并将其拆分为不同的小批量.我非常有信心,您可以通过尝试解决这些问题并实施它们来解决甚至减少您的问题.

根据您的问题类型,您应该将激活功能更改为与功能不同的tanh功能.执行分类时,a OneHotEncoder也可能有用(如果您的数据尚未进行热编码); 该sklearn框架也提供了这方面的实现.


nbe*_*hat 5

随机化训练集并重复

如果您希望公平地比较训练样本数量对准确性的影响,我建议n_samples您从训练集中随机选择,而不是在前一批中添加100个样本.您还将重复N_repeat每个n_samples值的拟合时间.

这会给出这样的东西(未经测试):

n_samples_array = np.arange(100,len(X_train),100)
N_repeat = 10

for n_samples in n_samples_array:
    print(n_samples)

    # repeat the fit several times and take the mean
    myList_tmp, myList2_tmp = [],[]
    for repeat in range(0,N_repeat):
        # Randomly pick samples
        selection = np.random.choice(range(0,len(X_train)),n_samples,repeat=False)

        # train the model and store the training error
        A=clf.fit(X_train[selection],Y_train[selection])
        myList_tmp.append(1-A.score(X_train[selection],Y_train[selection]))

          # compute the testing error
        myList2_tmp.append(1-A.score(X_test,Y_test))

    myList.append(np.mean(myList_tmp))
    myList2.append(np.mean(myList2_tmp))
Run Code Online (Sandbox Code Playgroud)

热烈的开始

使用该fit功能时,从头开始重新启动优化.如果您希望在向同一个以前训练过的网络添加一些示例时看到优化方面的改进,则可以使用该选项warm_start=True

根据文件:

warm_start:bool,可选,默认为False

设置为True时,重用上一次调用的解决方案以适合初始化,否则,只需擦除以前的解决方案.

  • @MysteryGuy我看,所以你基本上有超过10万的免费参数,不到15k的数据点.您是否尝试过`warm_start`选项,它可能有助于平滑曲线.另外,我建议使用其他激活功能.`relu`是目前在深度学习中使用最广泛的.由于梯度消失问题,Sigmoids的学习速度很慢. (2认同)