为什么多层感知机的成本函数会变平?

我刚开始学习机器学习,正在尝试实现一个多层感知机(MLP),但成本函数似乎在达到全局最小值之前就达到了局部最小值。我绘制了成本函数随迭代次数的变化图(包括0值以避免被y轴的起点误导)。成本图 这是我在尝试中使用的代码:

import numpy as npclass NNet(object):def __init__(self, n_in, n_hidden, n_out):    self.n_in = n_in    self.n_hidden = n_hidden    self.n_out = n_out    self.W1 = np.random.randn(n_in, n_hidden)    self.W2 = np.random.randn(n_hidden, n_out)    self.b1 = np.random.randn(n_hidden,)    self.b2 = np.random.randn(n_out,)def sigmoid(self, z):    return 1/(1 + np.exp(-z))def sig_prime(self, z):    return (np.exp(-z))/((1+np.exp(-z))**2)def propagate_forward(self, X):    self.z1 = np.dot(self.W1.T, X) + self.b1    self.a1 = self.sigmoid(self.z1)    self.z2 = np.dot(self.W2.T, self.a1) + self.b2    self.a2 = self.sigmoid(self.z2)    return self.a2def cost(self, y, y_hat):    return np.mean([np.sum((y[i] - y_hat[i])**2) for i in range(y.shape[0])])/2def cost_grad(self, X, y):    y_hat = self.propagate_forward(X)    d2 = np.multiply(self.sig_prime(self.z2), -(y - y_hat))    gJ_W2 = np.matrix(np.multiply(self.a1.T, d2))    d1 = np.dot(self.W2, d2)*self.sig_prime(self.z1)    gJ_W1 = np.dot(np.matrix(X).T, np.matrix(d1))    return [gJ_W1, d1, gJ_W2, d2]m = 1000n = 1X = np.zeros((m, n))y = np.zeros((m,1))import randomimport mathi = 0for r, theta in zip(np.linspace(0, 5, num=m), np.linspace(0, 8 * math.pi, num=m)):    r += random.random()    X[i] = [r * math.cos(theta), r * math.sin(theta)]    if i < 333:        y[i] = 0    elif i < 666:        y[i] = 1    else:        y[i] = 2    i += 1nnet = NNet(n, 5, 1)learning_rate = 0.2improvement_threshold = 0.995cost = np.infxs = []ys = []iter = 0while cost > 0.2:cost = nnet.cost(y, [nnet.propagate_forward(x_train) for x_train if iter % 100 == 0:    xs.append(iter)    ys.append(cost)    print("Cost", cost)if iter >= 1000:    print("梯度下降耗时过长,放弃。")    breakcost_grads = [nnet.cost_grad(x_train, y_train) for x_train, y_train in zip(X, y)]gW1 = [grad[0] for grad in cost_grads]gb1 = [grad[1] for grad in cost_grads]gW2 = [grad[2] for grad in cost_grads]gb2 = [grad[3] for grad in cost_grads]nnet.W1 -= np.mean(gW1, axis=0)/2 * learning_ratennet.b1 -= np.mean(gb1, axis=0)/2 * learning_ratennet.W2 -= np.mean(gW2, axis=0).T/2 * learning_ratennet.b2 -= np.mean(gb2, axis=0)/2 * learning_rateiter += 1

为什么成本函数在某一点之后不再改善?也欢迎提供其他建议。

生成的玩具数据集看起来像这样数据


回答:

你的目标似乎是预测数据属于哪个类别{0,1,2}。

你的网络的输出是Sigmoid函数(sigm(x) 在 [0,1] 之间),并且你使用均方误差(MSE)进行训练,模型不可能预测出超过1的值。因此,当需要预测的类别是2时,总是错误的。

  • 成本函数可能变平是因为你的Sigmoid单元在尝试预测2时饱和,而饱和的Sigmoid的梯度为0 Sigmoid

对于分类的神经网络,通常以Softmax层结束,并使用交叉熵进行训练。

如果你想继续使用MSE和Sigmoid单元进行分类,你应该考虑一次预测两个类别,采用一对一/一对多的方式。

无论如何,如果你只进行二分类,通过将输出四舍五入到0或1,似乎是可行的。成本在下降,准确率在上升 (快速修改后的代码)

成本准确率

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注