我们的训练集由 m = 750 个样本组成。因此,我们的矩阵维度如下:
-
训练集维度: X = (750,2)
-
目标维度: Y = (750,1)
-
维度:(m,nhidden) = (2,6)
-
维度:(bias vector):(1,nhidden) = (1,6)
-
维度: (nhidden,noutput)= (6,1)
-
维度:(bias vector):(1,noutput) = (1,1)
损失函数
我们使用与 Logistic 回归算法相同的损失函数:
对于多类别的分类任务,我们将使用这个函数的通用形式作为损失函数,称之为分类交叉熵函数。
训练
我们将用梯度下降法来训练我们的神经网络,并通过反向传播法来计算所需的偏导数。训练过程主要有以下几个步骤:
1. 初始化参数(即权重量和偏差量)
2. 重复以下过程,直到收敛:
-
通过网络传播当前输入的批次大小,并计算所有隐藏和输出单元的激活值和输出值。
-
针对每个参数计算其对损失函数的偏导数
-
更新参数
前向传播过程
首先,我们计算网络中每个单元的激活值和输出值。为了加速这个过程的实现,我们不会单独为每个输入样本执行此操作,而是通过矢量化对所有样本一次性进行处理。其中:
-
表示对所有训练样本激活隐层单元的矩阵
-
表示对所有训练样本输出隐层单位的矩阵
隐层神经元将使用 tanh 函数作为其激活函数:
输出层神经元将使用 sigmoid 函数作为激活函数:
激活值和输出值计算如下(·表示点乘):
反向传播过程
为了计算权重向量的更新值,我们需要计算每个神经元对损失函数的偏导数。这里不会给出这些公式的推导,你会在其他网站上找到很多更好的解释(https://mattmazur.com/2015/03/17/a-step-by-step-backpropagation-example/)。
对于输出神经元,梯度计算如下(矩阵符号):
对于输入和隐层的权重矩阵,梯度计算如下:
权重更新
In [3]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import make_circles
from sklearn.model_selection import train_test_split
np.random.seed(123)
% matplotlib inline
数据集
In [4]:
X, y = make_circles(n_samples=1000, factor=0.5, noise=.1)
fig = plt.figure(figsize=(8,6))
plt.scatter(X[:,0], X[:,1], c=y)
plt.xlim([-1.5, 1.5])
plt.ylim([-1.5, 1.5])
plt.title("Dataset")
plt.xlabel("First feature")
plt.ylabel("Second feature")
plt.show()
In [5]:
# reshape targets to get column vector with shape (n_samples, 1)
y_true = y[:, np.newaxis]
# Split the data into a training and test set
X_train, X_test, y_train, y_test = train_test_split(X, y_true)
print(f'Shape X_train: {X_train.shape}')
print(f'Shape y_train: {y_train.shape}')
print(f'Shape X_test: {X_test.shape}')
print(f'Shape y_test: {y_test.shape}')
Shape X_train: (750, 2)
Shape y_train: (750, 1)
Shape X_test: (250, 2)
Shape y_test: (250, 1)