Написано впереди: полный код можно получить, подписавшись на мою официальную учетную запись [Thumb Note] и ответив на «softmax_py» в фоновом режиме.
Эффект узнавания:
1. Регрессия Softmax
Эта часть разделена на четыре части: концепция регрессионной модели softmax, концепция набора данных классификации изображений, реализация регрессионной модели softmax и реализация регрессионной модели softmax на основе pytorch framework.
Для задач прогнозирования дискретных значений мы можем использовать модели классификации, такие как регрессия softmax. Модель регрессии softmax имеет несколько выходных единиц. В этой главе в качестве примера используется модель регрессии softmax, чтобы представить модель классификации в нейронной сети.
1.1 Проблемы классификации
Например, простая задача классификации изображений, входная графика имеет высоту и ширину 2 пикселя, а цвет — оттенки серого (значение пикселя изображения в градациях серого может быть представлено скаляром). Обозначим значения четырех пикселей изображения как x1,x2,x3,x4. Предположим, что реальными метками изображений в обучающем наборе данных являются собаки, кошки и куры, и эти метки соответствуют дискретным значениям y1, y2 и y3 соответственно.
Обычно мы используем дискретные значения для представления категорий, таких как y1=1, y2=2, y3=3. Изображение помечено одним из значений 1, 2 и 3. Для такого рода задач мы обычно используем модель, которая больше подходит для дискретного вывода, чтобы решить проблему классификации.
1.2 модель регрессии softmax
Как и в модели регрессии softmax, входные признаки и веса накладываются линейно. Основное отличие от линейной регрессии в том, что количество выходных значений регрессии softmax равно количеству категорий в метке.
В приведенном выше примере каждое изображение имеет еще четыре пикселя, соответствующие четырем собственным значениям (x) на изображение, и есть три возможных класса животных, соответствующих трем
Метки дискретных значений (o). Итак, содержит 12 весов (w) и 3 смещения (b).
Регрессия Softmax также является однослойной нейронной сетью, и расчет каждого выхода o зависит от всех входов x, поэтому выходной слой регрессии softmax также является полносвязным слоем.
Обычно выходное значение oi используется как достоверность прогнозируемого класса i, а класс, соответствующий выходу с наибольшим значением, используется как прогнозируемый выход.который
Например, o1, o2 и o3 равны соответственно 0,1, 10 и 0,1. Поскольку o2 является наибольшим, прогнозируемая категория равна 2.
Но есть две проблемы с этим подходом
-
Диапазон выходных значений выходного слоя неопределен, и трудно просто судить о значении этих значений
Например, когда три значения равны 0,1, 10 и 0,1, 10 означает «очень уверенно», а когда три значения — 1000, 10 и 1000, 10 означает «невероятно».
-
Поскольку истинные метки также являются дискретными значениями, погрешность между этими дискретными значениями и выходными значениями в диапазоне неопределенности трудно измерить.
Оператор softmax решает две вышеупомянутые проблемы. Он преобразует выходное значение в распределение вероятностей, значения которого положительны и в сумме равны 1 по следующей формуле.
в
очень легко увидеть
На основе двух приведенных выше уравнений y1, y2 и y3 являются допустимыми распределениями вероятностей. Например: y2=0,8, то неважно, какие y1 и y3, мы все знаем, что вероятность быть второй категорией составляет 80%
так как
Известно, что операция softmax не изменяет вывод прогнозируемой категории.
1.3 Выражение векторного расчета для одновыборочной классификации
Для повышения эффективности работы используется векторный расчет. Взяв в качестве примера проблему классификации изображений, приведенную выше, векторные выражения параметров веса и смещения имеют вид
Пусть характеристики образца изображения i высотой и шириной 2 пикселя соответственно равны
Выход выходного слоя
Прогнозируемое распределение вероятностей
Наконец, выражение векторного расчета для классификации выборки i с помощью регрессии softmax:
Для данного образца мини-партии существует
1.4 Функция кросс-энтропийных потерь
После использования операции softmax удобнее считать ошибку на дискретной метке. Истинная метка также может быть преобразована в допустимое распределение вероятностей, то есть: для выборки (изображения), чей истинный класс y_i, мы устанавливаем y_i равным 1, а остальные равными 0. Если изображение кошки (второе), его y = [0 1 0]. Это делает \hat{y} ближе к y.
В задаче классификации изображений, если результат предсказания верен, нет необходимости делать вероятность предсказания равной вероятности метки (кошки с разными цветами действий), нам нужно только сделать вероятность, соответствующую реальной категории, больше, чем вероятности других категорий, поэтому в регрессионных моделях нет необходимости использовать линейную квадратичную функцию потерь.
Мы используем функцию кросс-энтропии для расчета потерь.
В этой формуле y^(i) _j — элемент истинной вероятности метки, равной 1, а \hat{y}^{(i)}_j — соответствующий элемент предсказанной вероятности класса.
Поскольку в y ^ (i) есть только одна метка, в y ^ {i} все элементы, кроме y ^ (i) _j, равны 0, поэтому получается упрощенное уравнение приведенной выше формулы.
То есть функция кросс-энтропии связана только с прогнозируемой вероятностью.Пока прогнозируемое значение достаточно велико, может быть обеспечена правильность результата классификации.
Для всей выборки функция кросс-энтропийных потерь определяется как
Где \theta представляет параметры модели, если у каждого образца есть только одна метка, приведенную выше формулу можно упростить как
Минимизация функции кросс-энтропийных потерь эквивалентна максимизации совместной прогнозируемой вероятности всех классов меток в обучающем наборе данных.
2. Набор данных классификации изображений (Fashion-MNIST)
Для этой главы требуется пакет torchvision, для которого я переустановил
Этот набор данных представляет собой набор данных классификации графов, который мы будем использовать позже в нашем исследовании. Его изображение более сложное, чем набор данных для распознавания рукописных цифр MINIST, что нам удобнее для интуитивного наблюдения за различиями между алгоритмами.
В этом разделе в основном используется пакет torchvision, который в основном используется для построения моделей компьютерного зрения.
Основные компоненты пакета torchvision | Функции |
---|---|
torchvision.datasets | Некоторые функции для загрузки данных и общие интерфейсы наборов данных |
torchvision.madels | Содержит часто используемые структуры моделей (включая предварительно обученные модели) |
torchvision.transforms | Общие преобразования изображений (обрезка, поворот) |
torchvision.utils | Другие методы |
2.1 Получить набор данных
Сначала импортируйте необходимые пакеты
import torch
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import time
import sys
sys.path.append("..")
#调用库时,sys.path会自动搜索路径,为了导入d2l这个库,所以需要添加".."
#import d2lzh_pytorch as d2l 这个库找不到不用了
from IPython import display
#在这一节d2l库仅仅在绘图时被使用,因此使用这个库做替代
** Загрузите этот набор данных, вызвав torchvision.datasets в torchvision. **Первый вызов автоматически извлекает данные из Интернета.
Установив параметр train, вы можете указать получение набора данных для обучения или набора тестовых данных (набор тестов: используется для оценки производительности модели, не используется для обучения модели).
Преобразуйте все данные в тензор, установив параметр transfrom = transforms.ToTensor(), если нет, верните изображение PIL.
Функция transforms.ToTensor() преобразует изображение PIL размером (H*W*C) и данные между [0,255] или массив NumPy с типом данных np.uint8 в размер (C*H*W) и тензор данных. типа torch.float32 в [0,0,1.0]
C представляет количество каналов, а количество каналов в изображении в градациях серого равно 1.
Изображение PIL является стандартом для Python для обработки изображений.
Примечание. Функция transforms.ToTensor() по умолчанию устанавливает тип ввода uint8.
#获取训练集
mnist_train = torchvision.datasets.FashionMNIST(root='~/Datasets/FashionMNIST',train=True,download = True,transform = transforms.ToTensor())
#获取测试集
mnist_test = torchvision.datasets.FashionMNIST(root='~/Datasets/FashionMNIST',train=True,download = True,transform = transforms.ToTensor())
Среди них mnist_train и mnist_test могут использовать len() для получения размера набора данных, а также могут использовать индексы для получения конкретной выборки.
И обучающий набор, и тестовый набор имеют по 10 категорий, количество изображений в каждой категории в обучающем наборе равно 6000, а количество изображений в каждой категории в тестовом наборе равно 1000, то есть в наборе 60 000 образцов. обучающий набор и 10 000 образцов в тестовом наборе.
len(mnist_train) #输出训练集的样本数
mnist_train[0] #通过下标访问任意一个样本,返回值为两个torch,一个特征tensor和一个标签tensor
В наборе данных Fashion-MNIST имеется десять категорий, а именно: футболка (футболка), брюки (брюки), пуловер (пуловер), платье (платье), пальто (пальто), сандалии (сандалии), рубашка (рубашка ), кроссовки (кроссовки), сумка (сумка) и ботильоны (сапоги).
Необходимо преобразовать эти текстовые метки и числовые метки друг в друга, что можно сделать с помощью следующей функции.
def get_fashion_mnist_labels(labels):
text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',
'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']
return [text_labels[int(i)] for i in labels]
#labels是一个列表
#数值标签转文本标签
Ниже приведена функция, которая может рисовать несколько изображений и соответствующие метки в строке ухода.
def show_fashion_mnist(images, labels):
d2l.use_svg_display()
#绘制矢量图
_, figs = plt.subplots(1, len(images), figsize=(12, 12))
#创建子图,一行len(images)列,图片大小12*12
for f, img, lbl in zip(figs, images, labels):
#zip函数将他们压缩成由多个元组组成的列表
f.imshow(img.view((28, 28)).numpy())
#将img转形为28*28大小的张量,然后转换成numpy数组
f.set_title(lbl)
#设置每个子图的标题为标签
f.axes.get_xaxis().set_visible(False)
f.axes.get_yaxis().set_visible(False)
#关闭x轴y轴
plt.show()
Использование вышеуказанных функций
X,y = [],[]
#初始化两个列表
for i in range(10):
X.append(mnist_train[i][0])
#循环向X列表添加图像
y.append(mnist_train[i][1])
#循环向y列表添加标签
show_fashion_mnist(X,get_fashion_mnist_labels(y))
#显示图像和列表
2.2 Чтение небольших партий
Имея опыт чтения мини-пакетов в линейной регрессии, мы знаем, что чтение мини-пакетов можно реализовать с помощью функции загрузчика данных, встроенной в torch.
Загрузчик данных также поддерживает многопоточное чтение данных, устанавливая свой параметр num_workers.
batch_size = 256
#小批量数目
train_iter = torch.utils.data.DataLoader(mnist_train,batch_size=batch_size,shuffle = True,num_workers = 0)
#num_workers=0,不开启多线程读取。
test_iter = torch.utils.data.DataLoader(mnist_test,batch_size = batch_size,shuffle=False,num_workers=0)
3. Используйте pytorch для реализации модели регрессии softmax.
Использование pytorch может быть более удобным для реализации модели регрессии softmax.
3.1 Получение и чтение данных
Как читать небольшие пакеты данных:
-
Во-первых, это получение данных. pytorch может легко получить набор данных Fashion-MNIST с помощью следующего кода.
mnist_train = torchvision.datasets.FashionMNIST(root='~/Datasets/FashionMNIST',train=True,download=True,transform=transforms.ToTensor()) mnist_test = torchvision.datasets.FashionMNIST(root='~/Datasets/FashionMNIST',train=False,download=True,transform=transforms.ToTensor()) #参数 #root : processed/training.pt 和 processed/test.pt 的主目录 #train : True = 训练集, False = 测试集 #download : True = 从互联网上下载数据集,并把数据集放在root目录下. 如果数据集之前下载过,将处理过的数据(minist.py中有相关函数)放在processed文件夹下 #transform = transforms.ToTensor():使所有数据转换为Tensor
-
Затем создайте итератор для чтения данных
#生成迭代器 train_iter = torch.utils.data.DataLoader(mnist_train,batch_size=batch_size,shuffle = True,num_workers = 0) test_iter = torch.utils.data.DataLoader(mnist_test,batch_size = batch_size,shuffle=False,num_workers=0) #参数 #dataset:Dataset类型,从其中加载数据 #batch_size:int类型,每个批量加载多少个数 #shuffle:bool类型,每个学习周期都打乱顺序 #num_workers:int类型,加载数据时使用多少子进程。默认值为0. #collate_fn:定义如何取样本,可通过定义自己的函数来实现。 #pin_memory:锁页内存处理。 #drop_last:bool类型,如果有剩余的样本,True表示丢弃;Flase表示不丢弃
3.2 Определение и инициализация модели
Согласно определению регрессионной модели softmax, регрессионная модель softmax имеет только параметры веса и параметры смещения. Таким образом, можно использовать линейный модуль в подмодуле нейронной сети.
- Сначала определите сеть, регрессия softmax представляет собой двухслойную сеть, поэтому необходимо определить только входной и выходной слои.
num_inputs = 784
num_outputs = 10
class LinearNet(nn.Module):
def __init__(self,num_inputs,num_outputs):
super(LinearNet,self).__init__()
self.linear = nn.Linear(num_inputs,num_outputs)
#定义一个输入层
#定义向前传播(在这个两层网络中,它也是输出层)
def forward(self,x):
y = self.linear(x.view(x.shape[0],-1))
#将x换形为y后,再继续向前传播
return y
net = LinearNet(num_inputs,num_outputs)
- Параметры инициализации
Используйте init в torch.nn для быстрой инициализации параметров. Мы устанавливаем параметр веса как нормальное распределение со средним значением 0 и стандартным отклонением 0,01. Смещение равно 0.
init.normal_(net.linear.weight, mean=0, std=0.01)
init.constant_(net.linear.bias, val=0)
3.3 операция softmax и функция потери перекрестной энтропии
Раздельное определение операции softmax и функции кросс-энтропийных потерь может привести к численной нестабильности. Поэтому PyTorch предоставляет функцию с хорошей числовой стабильностью, включая операцию softmax и вычисление перекрестной энтропии.
loss = nn.CrossEntropyLoss()
3.4 Определение алгоритма оптимизации
Все еще использую мини-пакетный стохастический градиентный спуск в качестве алгоритма оптимизации. Определите скорость обучения как 0,1.
optimizer = torch.optim.SGD(net.parameters(),lr=0.01)
3.5 Расчет точности классификации
Принцип расчета показателя точности:
Мы берем категорию с наибольшей прогнозируемой вероятностью в качестве выходной категории, и если она согласуется с истинной категорией y, прогноз правильный. Точность классификации — это отношение количества правильных предсказаний к общему количеству предсказаний.
Сначала нам нужно получить прогнозируемый результат.
Найдите индекс, соответствующий наибольшей вероятности, из набора предсказанных вероятностей (переменная y_hat) (индекс представляет категорию)
#argmax(f(x))函数,对f(x)求最大值所对应的点x。我们令f(x)= dim=1,即可实现求所有行上的最大值对应的索引。
A = y_hat.argmax(dim=1)
#最终输出结果为一个行数与y_hat相同的列向量
Затем нам нужно сравнить категорию, соответствующую полученной максимальной вероятности, с реальной категорией (y), чтобы определить, верен ли прогноз.
B = (y_hat.argmax(dim=1)==y).float()
#由于y_hat.argmax(dim=1)==y得到的是ByteTensor型数据,所以我们通过.float()将其转换为浮点型Tensor()
Наконец, нам нужно рассчитать точность классификации
Мы знаем, что количество строк y_hat соответствует общему количеству выборок, поэтому среднее значение B является точностью классификации.
(y_hat.argmax(dim=1)==y).float().mean()
Окончательные данные, полученные на предыдущем шаге, имеют вид тензора(х), и чтобы получить итоговое число pytorch, необходимо выполнить над ним следующую операцию.
(y_hat.argmax(dim=1)==y).float().mean().item()
#pytorch number的获取统一通过.item()实现
Разберитесь и получите рассчитанную функцию точности классификации
def accuracy(y_hat,y):
return (y_hat.argmax(dim=1).float().mean().item())
В качестве расширения эта функция также может оценивать точность сети модели в наборе данных data_iter.
def net_accurary(data_iter,net):
right_sum,n = 0.0,0
for X,y in data_iter:
#从迭代器data_iter中获取X和y
right_sum += (net(X).argmax(dim=1)==y).float().sum().item()
#计算准确判断的数量
n +=y.shape[0]
#通过shape[0]获取y的零维度(列)的元素数量
return right_sum/n
3.6 Обучение модели
num_epochs = 5
#一共进行五个学习周期
def train_softmax(net,train_iter,test_iter,loss,num_epochs,batch_size,optimizer,net_accurary):
for epoch in range(num_epochs):
#损失值、正确数量、总数 初始化。
train_l_sum,train_right_sum,n= 0.0,0.0,0
for X,y in train_iter:
y_hat = net(X)
l = loss(y_hat,y).sum()
#数据集损失函数的值=每个样本的损失函数值的和。
optimizer.zero_grad() #对优化函数梯度清零
l.backward() #对损失函数求梯度
optimizer(params,lr,batch_size)
train_l_sum += l.item()
train_right_sum += (y_hat.argmax(dim=1) == y).sum().item()
n += y.shape[0]
test_acc = net_accurary(test_iter, net) #测试集的准确率
print('epoch %d, loss %.4f, train right %.3f, test acc %.3f' % (epoch + 1, train_l_sum / n, train_right_sum / n, test_acc))
train_softmax(net,train_iter,test_iter,cross_entropy,num_epochs,batch_size,optimizernet_accurary,net_accurary)
тренировочный эффект
3.7 Классификация изображений
Используйте обученную модель, чтобы делать прогнозы на тестовом наборе
Конечной целью создания модели является, конечно, не обучение, поэтому попробуем спрогнозировать.
#将样本的类别数字转换成文本
def get_Fashion_MNIST_labels(labels):
text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',
'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']
return [text_labels[int(i)] for i in labels]
#labels是一个列表,所以有了for循环获取这个列表对应的文本列表
#显示图像
def show_fashion_mnist(images,labels):
display.set_matplotlib_formats('svg')
#绘制矢量图
_,figs = plt.subplots(1,len(images),figsize=(12,12))
#设置添加子图的数量、大小
for f,img,lbl in zip(figs,images,labels):
f.imshow(img.view(28,28).numpy())
f.set_title(lbl)
f.axes.get_xaxis().set_visible(False)
f.axes.get_yaxis().set_visible(False)
plt.show()
#从测试集中获得样本和标签
X, y = iter(test_iter).next()
true_labels = get_Fashion_MNIST_labels(y.numpy())
pred_labels = get_Fashion_MNIST_labels(net(X).argmax(dim=1).numpy())
#将真实标签和预测得到的标签加入到图像上
titles = [true + '\n' + pred for true, pred in zip(true_labels, pred_labels)]
show_fashion_mnist(X[0:9], titles[0:9])
добиться эффекта
Первая строка — это метка истинности, а вторая — идентификационная метка.