Использование TensorFlow2.0 для реализации мультиклассификации Softmax

машинное обучение глубокое обучение

Мы знаем, что линейная регрессия обычно используется для решения регрессионных задач, таких как прогнозирование цен на жилье, прогнозирование температуры и т. д. Фактически, с помощью таких методов, как Softmax, мы также можем использовать линейную регрессию для решения задач множественной классификации. Softmax представляет собой преобразование выходного слоя в структуру сети.Схема выглядит следующим образом:

Технические детали Софтмакс

На приведенном выше рисунке x1, x2 и x3 — это входные слои, которые проходят через две модели линейной регрессии для получения y1 и y2 соответственно:

\begin{aligned} y_1&=w_{11}x_1 + w_{12}x_2 + w_{13}x_3 + b_1\\ y_2&=w_{21}x_1 + w_{22}x_2 + w_{23}x_3 + b_2 \end{aligned}

Затем введите y1 и y2 в модуль Softmax и выведите y1 'и y2'. Результат после обработки Softmax представляет собой дискретное распределение вероятностей, то есть y1 '+ y2' = 1. Таким образом, мы можем использовать y1' и y2' для представления предсказанных вероятностей различных классов.

Конкретные детали Softmax показаны на следующем рисунке:

  1. Во-первых, выходной результат обрабатывается в степени e, чтобы получитьz_1= e^{y_1},z_2=e^{y_2}
  2. Сложите результаты шага 1: сумма = z1 + z2
  3. Наконец, разделите результат шага 1 на сумму, чтобы получитьy_1' = z_1 / sum,y_2'=z_2/sum

Поскольку результат обрабатывается в степени e, Softmax будет усиливать большие числа, что приведет к большей вероятности получения больших результатов, поэтому Softmax называется Softmax, а не max.

Функция потерь для классификации Softmax

Классификация Softmax использует функцию потерь перекрестной энтропии (Cross Entropy).Если вы внимательно посмотрите, функция потерь перекрестной энтропии на самом деле является логарифмическим правдоподобием (см.Глубокое понимание логистической регрессииarticle), их цель — максимизировать прогнозируемое значение правильной классификации.

На приведенном выше рисунке y1', y2' и y3' — прогнозируемые вероятности различных классификаций, которые являются выходными результатами Softmax; y1, y2 и y3 — реальные данные классификации. В задаче классификации только одна из этих трех числа равно 1, два других равны 0, поэтому y1, y2 и y3 также являются распределением вероятностей.

Тогда наша задача машинного обучения становится такой: предсказать распределение вероятностейy'Постоянное приближение к истинному распределению вероятностейyпроблема с оптимизацией. Мы используем перекрестную энтропию для измерения разницы между двумя распределениями вероятностей. Чем меньше перекрестная энтропия, тем ближе два распределения. Перекрестная энтропия выражается следующим образом:

H(y,y') = \sum_{j=1}^{q} -y^{(j)} \log({y'}^{(j)})

В приведенной выше формуле q указывает, что существует q категорий,y^{(j)}— вероятность для j-го класса. Сложение перекрестной энтропии всех выборок и есть функция потерь, которую мы хотим:

\begin{aligned} Loss &= \sum_{i=1}^n H(y_i,y_i')\\ &=\sum_{i=1}^{n}-y_i\log(y_i') \end{aligned}

Как я только что сказал, перекрестная энтропия эквивалентна логарифмическому правдоподобию, и вы можете понять это с точки зрения логарифмического правдоподобия. Кроме того, вы также можете понять с точки зрения теории информации:

В теории информации энтропияH=\sum_{j=1}^q -y^{(j)}\log(y^{(j)})используется для описания ожидаемого количества информации, содержащейся в системе, где-\log(y^{(j)})является самоинформацией, указывающей на то, что вероятностьy^{(j)}Количество информации, генерируемой при возникновении события, самоинформацию можно понимать как событие с небольшой вероятностью, которое будет генерировать большой объем информации, и, наоборот, событие с большой вероятностью будет генерировать небольшой объем информации.

в то время как перекрестная энтропияH(y_q,{y_q}')Описывает: усилия, необходимые для удаления информации из системы, а при ее распространении{y_q}'иy_qПри равенстве требуемое усилие минимально —H(y_q,{y_q}')Из-за этого машинное обучение, достигнув минимума, использует кросс-энтропию в качестве функции потерь.

Для более подробного объяснения см.эта статья.

Внедрение Softmax с нуля

Теперь мы используем TF2.0 для реализации Softmax с нуля, шаги следующие:

  1. Определение мультиклассовой модели Softmax
  2. Определите функцию потерь
  3. обучать, оценивать модель

Определение мультиклассовой модели Softmax

Модель линейной регрессии Softmax в основном делает две вещи:

1. Сделайте матричное умножение между матрицей входных данных и матрицей параметров.Количество строк входных данных - это количество выборок n, а содержимое каждой строки - это функция каждой выборки.Если количество функций равно d , форма входных данныхn*d, обучать несколько фрагментов данных одновременно, чтобы достичь цели пакетного расчета; размерность матрицы параметровd*q, d по-прежнему является количеством признаков, а q — количеством классификаций, поэтому результат умножения равенn*q, что означает выход каждой выборки из n выборок по разным классификациям;

Во-вторых, выполните обработку Softmax результатов первого шага, чтобы получить результаты прогнозирования каждой выборки в разных категориях.

def net(X):
    '''
    一层线性回归网络,输出 softmax 后的多分类结果
    Args:
    - X: n 条样本,每条样本有 d 个维度,即 n*d 维矩阵
    - W: 全局参数,d*q 维矩阵,q 表示分类数
    - b: bias,1*q 维向量
    Return:
    - softmax 后的多分类结果
    '''
    return softmax(tf.matmul(X, W) + b)
   
def softmax(y):
    '''
    对 n 个样本,每个样本有 q 种分类的数据做softmax 
    Args:
    - y: n*q 维的矩阵
    Return:
    - n*q 维的 softmax 后的矩阵
    Example:
    >>> y = np.array([[0.1,0.2,0.8],[0.8,0.2,0.1]])
    >>> softmax(y)
    <tf.Tensor: shape=(2, 3), dtype=float64, numpy=
    array([[0.24278187, 0.26831547, 0.48890266],
       [0.48890266, 0.26831547, 0.24278187]])>
    '''
    return tf.exp(y) / tf.reduce_sum(tf.exp(y), axis=1, keepdims=True)

Определите функцию потерь

Обратите внимание на формулу функции кросс-энтропийных потерь, чтобы реализовать ее, вы должны сначала получить прогнозируемую вероятность, соответствующую правильной классификации:

Здесь горячее кодирование используется для преобразования целевого вектора в ту же матричную форму, что и прогнозируемый результат.Например, прогнозируемый результатn*q(n означает прогнозирование n выборок за раз, q означает количество классификаций), тогда горячее кодирование также преобразует целевой вектор вn*qматрица;

Затем выполните операцию И над матрицей предсказания и целевой матрицей.boolean_maskПрогнозируемое значение, соответствующее правильной классификации, может быть извлечено;

Наконец, вычисляется прогнозируемое значение-log, а затем sum — потери этой партии образцов, код выглядит следующим образом:

def cross_entropy(y, y_hat):
    '''
    交叉熵损失函数
    Args:
    - y: n 条样本的目标值,n*1 向量
    - y_hat: n 条样本的预测分布(softmax输出结果), n*q 矩阵
    Return:
    n 个样本的 -log(y_hat) 的和
    Examples:
    >>> y = np.array([[2],[1]])
    >>> y_hat = np.array([[0.1,0.2,0.2],[0.3,0.9,0.2]])
    >>> cross_entropy(y, y_hat)
    <tf.Tensor: shape=(), dtype=float64, numpy=1.7147984280919266>
    '''
    y_obs = tf.one_hot(y, depth=y_hat.shape[-1])
    y_obs = tf.reshape(y_obs, y_hat.shape)
    y_hat = tf.boolean_mask(y_hat, y_obs)
    return tf.reduce_sum(-tf.math.log(y_hat))

Модель оценки

На этот раз мы используем показатель точности (accuracy) для оценки эффекта модели, показатель точности означает долю правильных прогнозов.

При оценке модели сначала сделайте прогноз для данных, а затем сравните результат прогноза (классификацию с наибольшим значением вероятности) с правильной классификацией, чтобы подсчитать количество правильных прогнозов. используется здесьtf.argmaxфункция, что означает, что среди нескольких категорий предсказания наибольшее значение берется в качестве результата предсказания:

def accuracy(x, y, num_inputs, batch_size):
    '''
    求数据集的准确率
    Args:
    - x: 数据集的特征
    - y: 数据集的目标值,n*1 维矩阵
    - num_inputs: 特征维度(输入层个数)
    - batch_size: 每次预测的批次
    '''
    test_iter = tf.data.Dataset.from_tensor_slices((x, y)).batch(batch_size)
    acc, n = 0, 0
    for X, y in test_iter:
        X = tf.reshape(X, (-1, num_inputs))
        y = tf.cast(y, dtype=tf.int64)
        acc += np.sum(tf.argmax(net(X), axis=1) == y)
        n += y.shape[0]
    return acc/n

тренироваться

Выше приведены общие методы, необходимые для обучения модели, прогнозирования и оценки. Далее мы можем обучить модель. На этот раз мы используем набор данных fashion_mnist, в котором каждый образец представляет собой28*28Пиксельное изображение, метка целевого значения — это номер категории, к которой принадлежит это изображение. Всего в наборе данных 10 категорий, как показано ниже:

Наша задача — прочитать такую ​​картинку и предсказать, к какой категории она относится. Входными данными для модели может быть значение каждого пикселя изображения, поскольку28*28=784пикселей, а диапазон значений каждого пикселя составляет 0-255, тогда количество узлов во входном слое нашей модели равно 784; поскольку в наборе данных всего 10 категорий, форма параметра модели W имеет вид784*10размерная матрица, форма смещения10*1, а количество узлов в выходном слое также равно 10.

После выяснения параметров, остальное - итерация модели, эта часть и предыдущаяЛинейная регрессияКод обучения примерно такой же, код выглядит следующим образом:

import tensorflow as tf
from tensorflow import keras
import numpy as np
import time
import sys
from tensorflow.keras.datasets import fashion_mnist

def train(W, b, lr, num_inputs):
    (x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()
    # 数据归一化
    x_train = tf.cast(x_train, tf.float32) / 255
    x_test = tf.cast(x_test, tf.float32) / 255
    
    batch_size = 256
    num_epochs = 5
    for i in range(num_epochs):
        # 小批量迭代
        train_iter = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(batch_size)
        train_acc_sum, loss_sum, n = 0, 0, 0
        for X, y in train_iter:
            X = tf.reshape(X, (-1, num_inputs))
            y = tf.reshape(y, (-1, 1))
            # 计算loss和梯度
            with tf.GradientTape() as tape:
                l = cross_entropy(y, net(X))
            grads = tape.gradient(l, [W, b])
            # 根据梯度调整参数
            W.assign_sub(lr * grads[0])
            b.assign_sub(lr * grads[1])

            loss_sum += l.numpy() # 累加loss
            n += y.shape[0] #累加训练样本个数

        print("epoch %s, loss %s, train accuracy %s, test accuracy %s" 
              % (i+1, loss_sum/n, 
                 accuracy(x_train, y_train, num_inputs, batch_size), 
                 accuracy(x_test, y_test, num_inputs, batch_size)))

num_inputs = 784
num_outputs = 10
lr = 0.001
# 初始化模型参数
W = tf.Variable(tf.random.normal(shape=(num_inputs, num_outputs), 
                                 mean=0, stddev=0.01, dtype=tf.float32))
b = tf.Variable(tf.zeros(num_outputs, dtype=tf.float32))
train(W, b, lr, num_inputs)

Ниже приведены результаты обучения.Видно, что использование простой модели, такой как линейная регрессия, также может обеспечить точность 0,85 для задачи классификации изображений fashion_mnist.

epoch 1, loss 0.8956155544281006, train accuracy 0.82518, test accuracy 0.8144
epoch 2, loss 0.6048591234842936, train accuracy 0.83978, test accuracy 0.8272
epoch 3, loss 0.5516327695210774, train accuracy 0.84506, test accuracy 0.8306
epoch 4, loss 0.5295544961929322, train accuracy 0.84906, test accuracy 0.8343
epoch 5, loss 0.5141636388142904, train accuracy 0.85125, test accuracy 0.8348

простая реализация

Как обычно, давайте также рассмотрим простую реализацию Softmax:

# 加载数据集
(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()
x_train = x_train / 255
x_test = x_test / 255

# 配置模型
model = keras.Sequential([
    keras.layers.Flatten(input_shape=(28, 28)),  # 输入层
    keras.layers.Dense(10, activation=tf.nn.softmax)  # 输出层,激活函数使用的是 softmax
])
# 配置交叉熵损失函数
loss = 'sparse_categorical_crossentropy'  
# 配置 SGD,学习率为 0.1
optimizer = tf.keras.optimizers.SGD(0.1)
model.compile(optimizer=optimizer,
             loss = loss,
             metrics=['accuracy'])  # 使用准确率来评估模型

model.fit(x_train, y_train, epochs=5, batch_size=256)

Его по-прежнему нужно только настроить, и вам не нужно писать строчку логического кода.

резюме

В этой статье мы научились использовать линейную регрессию и Softmax для реализации модели с несколькими классами и фактически использовали набор данных fashion_mnist для проведения экспериментов и получили хорошую точность 0,85.В этой статье есть две детали, которые необходимо быть освоенным

  1. Детали реализации Softmax
  2. Принцип функции кросс-энтропийных потерь

Ссылаться на:

Статьи по Теме: