神经网络算法在许多机器学习应用中展现出了巨大的潜力,尤其是深度学习。然而,由于深度学习算法通常需要经过精细调优才能在特定应用场景中表现良好,目前我们暂时只讨论一些更为基础的方法。具体来说,我们将探讨一种基本的神经网络结构——多层感知机(MLP),它也被称作前馈神经网络或神经网络。这种模型可以作为进一步研究复杂深度学习技术的基础。
MLP可以被看作是一种广义的线性模型。在经过多层处理后,MLP得出结论。线性模型的预测公式如下:
[ y = w[0] cdot x[0] + w[1] cdot x[1] + ldots + w[p] cdot x[p] + b ]
其中,( y ) 是输入特征 ( x[0] ) 到 ( x[p] ) 的加权求和,权重为学到的系数 ( w[0] ) 到 ( w[p] )。这一公式可以通过图表直观展示:
图中,左侧的每个节点代表一个输入特征,连接线表示学到的系数。左侧的节点表示输入,它们的加权求和构成下一步处理的基础。在MLP中,这个过程会被重复执行,先计算隐藏单元的加权求和,然后用这些隐藏单元的加权求和结果得到最终输出。单隐层的多层感知机可以用下图说明:
这个模型需要学习更多的系数(也称为权重)。在每个输入与每个隐藏单元之间,以及每个隐藏单元与输出之间,都存在相应的权重。
从数学角度讲,无论计算多少次加权求和,其本质都是相同的。为了使模型比线性模型更强大,我们需要在每次计算完隐藏单元的加权求和后,使用一个非线性函数(例如ReLU或tanh)来处理结果。这可以通过下面的例子来说明:
python
import matplotlib.pyplot as plt
line = np.linspace(-4, 4, 100)
plt.plot(line, np.tanh(line), label="tanh")
plt.plot(line, np.maximum(line, 0), label="relu")
plt.legend(loc="best")
plt.xlabel("x value")
plt.ylabel("relu(x) value, tanh(x) value")
运行上述代码后,可以看到双曲正切激活函数(tanh)与校正线性激活函数(ReLU)的对比图:
ReLU函数会截断所有负值,而tanh函数在输入值较小时接近-1,在输入值较大时接近+1。这两种非线性函数使得神经网络能够学习到比线性模型更复杂的函数。
计算回归问题的完整公式如下(使用tanh非线性函数):
[ h[0] = text{tanh}(w[0,0] cdot x[0] + w[1,0] cdot x[1] + ldots + w[4,0] cdot x[4] + b[0]) ] [ h[1] = text{tanh}(w[0,1] cdot x[0] + w[1,1] cdot x[1] + ldots + w[4,1] cdot x[4] + b[1]) ] [ vdots ] [ y = v[0] cdot h[0] + v[1] cdot h[1] + ldots + b ]
其中,( w ) 是输入 ( x ) 与隐藏层 ( h ) 之间的权重,( v ) 是隐藏层 ( h ) 与输出 ( y ) 之间的权重。这些权重需要通过训练数据学习得到。用户需要设置的重要参数之一是隐藏层中的节点数量。对于较小或较简单的数据集,节点数量可以设置得较少(例如10个节点),而对于复杂的数据集,节点数量可以增加到数千个。还可以添加多个隐藏层。
接下来,我们将使用MLPClassifier来演示神经网络的工作原理。具体来说,我们将在two_moons数据集上训练一个神经网络,并观察不同配置下的决策边界变化。
```python from sklearn.neuralnetwork import MLPClassifier from sklearn.datasets import makemoons from sklearn.modelselection import traintest_split
x, y = makemoons(nsamples=100, noise=0.25, randomstate=3) xtrain, xtest, ytrain, ytest = traintestsplit(x, y, stratify=y, randomstate=42)
mlp = MLPClassifier(solver='lbfgs', randomstate=0).fit(xtrain, y_train) ```
运行上述代码后,可以看到默认情况下,MLP使用100个隐藏节点。这已经足够应对这个小型数据集。如果减少隐藏节点数量,效果会如何呢?
python
mlp = MLPClassifier(solver='lbfgs', random_state=0, hidden_layer_sizes=[15]).fit(x_train, y_train)
运行结果表明,当隐藏节点数量减少到15个时,决策边界变得更加粗糙,但仍能很好地拟合数据。此外,如果增加隐藏层的数量,效果会更好。例如,使用两个隐藏层,每个隐藏层有15个节点:
python
mlp = MLPClassifier(solver='lbfgs', random_state=0, hidden_layer_sizes=[15, 15]).fit(x_train, y_train)
运行结果表明,使用两个隐藏层的决策边界更加平滑,效果更佳。如果激活函数改为tanh,同样能得到类似的平滑边界。
通过以上分析可以看出,增加隐藏节点数量或隐藏层数量可以使模型更加复杂,从而获得更平滑的决策边界。这为我们提供了更多调整模型以适应不同数据集的方法。
希望这些内容对你有所帮助。如果有任何疑问或建议,欢迎留言讨论!