Хороший обмен книгами: книги для знакомства с машинным обучением
0. Определите результаты
Если у вас есть друг, который хочет попробовать это сам, вы можете зайти в мой официальный аккаунт [Thumb Note] и ответить «MLP» в фоновом режиме, чтобы забрать его~
1. Многослойный персептрон (MLP)
В этом разделе в качестве примера будет взят многослойный персептрон, чтобы представить концепцию многослойной нейронной сети.
1.1 Скрытый слой
На рисунке ниже показана схема нейронной сети многослойного персептрона.
Многослойные персептроны вводят один или несколько скрытых слоев на основе однослойной нейронной сети. Скрытый слой, как показано на рисунке, имеет в общей сложности 5 скрытых единиц. Поскольку входной слой не требует вычислений, количество слоев в этом многослойном персептроне равно 2. И скрытый слой, и выходной слой в многослойном персептроне, показанном на рисунке, являются полносвязными слоями.
Для многослойного персептрона только с одним скрытым слоем и числом скрытых единиц h обозначим его выход как H. Поскольку скрытый слой и выходной слой в этом многослойном персептроне являются полностью связанными слоями, его можно установить: параметр веса и параметр смещения скрытого слоя равны W_h и b_h соответственно, а параметр веса и параметр смещения выходного слоя являются W_o и b_o соответственно
Отсюда мы можем получить взаимосвязь между входом нейронной сети одного скрытого слоя, выходом и выходом скрытого слоя.
Объедините два уравнения, чтобы получить связь между входом и выходом.
Из уравнения (2) нетрудно увидеть, что хотя такая нейронная сеть вводит (один или несколько) скрытых слоев, она все же эквивалентна однослойной нейронной сети. Основной причиной этой проблемы является полносвязный слой, который выполняет только аффинное преобразование данных, а наложение нескольких аффинных преобразований по-прежнему является аффинным преобразованием. Для решения таких задач вводятся нелинейные преобразования, а именно функции активации.
Студенты, которые не понимают функции активации,кликните сюда
2. Реализовать многослойный персептрон
В этом разделе будет использоваться многослойный персептрон для реализации чтения набора данных Fashion-MNIST.
Сначала импортируйте необходимые библиотеки.
import torch
from torch import nn
import numpy as np
import sys
sys.path.append("..")
import torchvision
from IPython import display
from time import time
import matplotlib.pyplot as plt
import torchvision.transforms as transforms
from time import time
2.1 Получение и чтение данных
В этой части по-прежнему используется предыдущий набор данных Fashion-MNIST.
batch_size = 256
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())
#获取测试集
#生成迭代器
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)
2.2 Определение и инициализация параметров модели
Изображения в наборе данных Fashion-MNIST имеют размер 28*28 пикселей, то есть состоят из 784 значений признаков. В наборе данных Fashion-MNIST есть десять категорий. Таким образом, модели требуется 784 входа и 10 выходов. Предположим, скрытая единица измерения — 256 (гиперпараметр, регулируемый).
num_inputs,num_outputs,num_hiddens = 784,10,256
#隐藏层权重参数、隐藏层偏差参数、输出层权重参数和输出层偏差参数初始化。
w1 = torch.tensor(np.random.normal(0,0.01,(num_inputs,num_hiddens)),dtype = torch.float)
b1 = torch.zeros(num_hiddens,dtype = torch.float)
w2 = torch.tensor(np.random.normal(0,0.01,(num_hiddens,num_outputs)),dtype = torch.float)
b2 = torch.zeros(num_outputs,dtype = torch.float)
params = [w1,b1,w2,b2]
#对w1,w2,b1,b2开启自动求导
for param in params:
param.requirers_grad_(requires_grad = True)
2.3 Определение функции активации
def relu(X):
return torch.max(input=X,other = torch.tensor(0.0))
2.4 Определение модели
def net(X):
X = X.view((-1,num_inputs))
#将输入换形为列向量的形式
H = relu(torch.matmul(X,W1)+b1)
#计算出隐藏层的输出
O = torch.matmul(H,W2)+b2
#计算输出
return O
2.5 Определение функции потерь
Здесь расчетная операция softmax и численная стабильность кросс-энтропии лучше..
loss = torch.nn.CrossEntropyLoss()
2.6 Функция оптимизации
Используйте мини-пакетный алгоритм стохастического градиентного спуска.
def sgd(params,lr,batch_size):
#lr:学习率,params:权重参数和偏差参数
for param in params:
param.data -= lr*param.grad/batch_size
#.data是对数据备份进行操作,不改变数据本身。
2.7 Расчет точности классификации
Принцип расчета показателя точности:
我们把预测概率最大的类别作为输出类别,如果它与真实类别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
2.8 Обучение модели
При обучении модели количество итераций num_epochs, количество нейронных единиц скрытого слоя num_hiddens и скорость обучения lr являются регулируемыми гиперпараметрами. Путем настройки значения гиперпараметров можно получить более точную модель классификации.
num_epochs,lr = 5,100
def train_MLP(net,train_iter,test_iter,loss,num_epochs,batch_size,params,lr ,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() #对优化函数梯度清零
for param in params:
param.grad.data.zero_()
l.backward() #对损失函数求梯度
optimzer(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_accuracy(test_iter, net) #测试集的准确率
print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f' % (epoch + 1, train_l_sum / n, train_acc_sum / n, test_acc))
train_MLP(net,train_iter,test_iter,loss,num_epochs,batch_size,params,lr,sgd,net_accurary)
2.9 Результаты обучения
Видно, что после использования многослойного персептрона точность распознавания нейронной сети улучшилась. И время работы было увеличено (5 циклов обучения выполняются по 80 секунд).
2.10 Определите тестовый набор
Используйте обученную модель, чтобы делать прогнозы на тестовом наборе
Конечной целью создания модели является, конечно, не обучение, поэтому давайте попробуем идентифицировать набор данных.
#将样本的类别数字转换成文本
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])
Результат распознавания
Писать нелегко, если вы сочтете это полезным, добавьте подписку, мой публичный аккаунт [Thumb Note], обновляйте мои учебные заметки каждый день~