机器学习 - softmax 回归训练流程

训练 softmax 回归循环模型与训练线性回归模型非常相似:先读取数据,再定义模型和损失函数,然后使用优化算法训练模型。

本文分为 理论介绍Python 代码实现 两部分

👉 点此直接跳转到代码实现

Softmax 回归模型

与逻辑回归一样,我们先对数据进行向量化:

$$ X = (x_0, x_1, \dots, x_n) $$

其中,$x_0$ 等于 1,且 $X$ 的形状为 $m$ 行 $n+1$ 列,$m$ 为样本个数,$n$ 为特征个数。

$$ W = (w_1, \dots, w_c) $$

$W$ 的形状为 $n+1$ 行 $c$ 列,$c$ 为总类别个数。

$$ Z = XW $$

$Z$ 的形状为 $m$ 行 $c$ 列。

$$ \hat{Y} = \text{softmax}(Z) $$

同样的,$\hat{Y}$ 的形状为 $m$ 行 $c$ 列。第 $i$ 行代表第 $i$ 个样本为每个类别的概率。

对于每个样本,我们将其判定为输出中最大值对应的类别。

Softmax 回归训练流程

Softmax 回归训练流程同逻辑回归一样,首先需要构造一个损失函数,再利用梯度下降方法最小化损失函数,从而达到更新参数的目的。具体流程如下:

Python 代码实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import numpy as np
from sklearn.preprocessing import OneHotEncoder


def softmax(x):
    '''
    input:x(ndarray):输入数据
    output:y(ndarray):经过 softmax 函数后的输出
    '''
    exp_x = np.exp(x - np.max(x))  # 防止溢出
    y = exp_x / np.sum(exp_x, axis=1, keepdims=True)
    return y


def softmax_reg(train_data, train_label, test_data, lr, max_iter):
    '''
    input:train_data(ndarray):训练数据
          train_label(ndarray):训练标签
          test_data(ndarray):测试数据
          lr(float):梯度下降中的学习率参数
          max_iter(int):训练轮数
    output:predict(ndarray):预测结果
    '''
    # 将 x0 加入训练数据
    train_data = np.c_[np.ones((train_data.shape[0], 1)), train_data]
    
    # 转换为 onehot 标签
    encoder = OneHotEncoder(sparse=False)
    train_label_onehot = encoder.fit_transform(train_label.reshape(-1, 1))
    
    # 对 w 初始化
    num_features = train_data.shape[1]
    num_classes = train_label_onehot.shape[1]
    w = np.zeros((num_features, num_classes))
    
    # 利用梯度下降对模型进行训练
    for _ in range(max_iter):
        z = np.dot(train_data, w)
        y_pred = softmax(z)
        gradient = np.dot(train_data.T, (y_pred - train_label_onehot)) / train_data.shape[0]
        w -= lr * gradient
    
    # 将 x0 加入测试数据
    test_data = np.c_[np.ones((test_data.shape[0], 1)), test_data]
    
    # 进行预测
    z_test = np.dot(test_data, w)
    y_test_pred = softmax(z_test)
    predict = np.argmax(y_test_pred, axis=1)
    return predict