目录
三、Pytorch里的交叉熵损失Torch.nn.CrossEntropyLoss()
SoftMAX分类器
一、使用Sigmoid实现多分类
计算P(y=1)、P(y=2)...的概率可以变成多个二分类问题:属于x或者不属于x;
缺点:之间的概率会互相抑制,当P(y=1)<P(y=2)时,不管P(y=1)多大,都会被忽略掉。
因此,多分类问题中,要求最终的概率满足某些分布:①各概率均不小于零;②概率之和为1;
输出应当是一个分布(distribution).
二、Softmax Layer使得输出满足分布的条件
Softmax Layer 对之前神经网络的输出做一个处理:
分子令所有值的大小转变为正数,分母使得概率归一化。
损失函数如何做?
损失函数不应当为0,否则没有意义。
二分类的交叉熵/损失函数:
多分类的损失函数/交叉熵定义为:
没有其他项,是因为其他项的y都严格等于0;
NLLLoss(Negative Log Likehood Loss):外输入标签,内输入为计算出的概率求对数之后的结果,这个函数计算相应的损失。
import numpy as np
y = np.array([1, 0, 0]) #输入的标签,放在一个向量中
z = np.array([0.2, 0.1, -0.1]) #神经网络的输出值
y_pred = np.exp(z) / np.exp(z).sum() #SoftMax函数
loss = (- y * np.log(y_pred)).sum() #损失函数的计算
print(loss)
三、Pytorch里的交叉熵损失Torch.nn.CrossEntropyLoss()
Pytorch内提供的交叉熵损失函数,将上述过程合并,不需要对神经网络做额外的激活。
import torch
y = torch.LongTensor([0]) #y需要是一个长整型的张量
z = torch.Tensor([[0.2, 0.1, -0.1]]) #设定为第0个分类
criterion = torch.nn.CrossEntropyLoss() #交叉熵损失函数
loss = criterion(z, y)
print(loss)
一个代码示例:
import torch
criterion = torch.nn.CrossEntropyLoss()
Y = torch.LongTensor([2, 0, 1]) #第一个分类是2,第二个是0,第三个是1
Y_pred1 = torch.Tensor([[0.1, 0.2, 0.9], #样本一第2个分类最大
[1.1, 0.1, 0.2], #样本二分类0概率最大
[0.2, 2.1, 0.1]]) #样本三分类1概率最大
Y_pred2 = torch.Tensor([[0.8, 0.2, 0.3], #预测2的差距与实际相差很大,因此损失也应当更大
[0.2, 0.3, 0.5],
[0.2, 0.2, 0.5]])
l1 = criterion(Y_pred1, Y)
l2 = criterion(Y_pred2, Y)
print("Batch Loss1 = ", l1.data, "\nBatch Loss2=", l2.data)
四、图像分类(简单)
图像可以转化为相应像素的矩阵,不同的颜色表示从0-1不同的大小(若图像只有黑白的话)。
- Prepare dataset //Dataset and Dataloader
- Design model using Class //inherit from nn.Module
- Construct loss and optimizer //using PyTorch API
- Training cycle +Test //forward, backward, update
1.数据处理
import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F #将激活函数改为relu函数,以替代sigmoid
import torch.optim as optim #优化器的包
batch_size = 64
transform = transforms.Compose([
transforms.ToTensor(),
#图像数据转变为张量
transforms.Normalize((0.1307, ), (0.3081, ))
#数据标准化,第一个数字是均值,第二个是标准差,Mini这个数据集是这样的参数
])
#Python读入图像的时候使用的是PIL(Pillow),期望将图像的像素n*n个[0,255]的数据转变为正态分布
#在[0,1]之间的数据结构(一个张量)
train_dataset = datasets.MNIST(root='../dataset/mnist/',
train=True,
download=True,
transform=transform)
train_loader = DataLoader(train_dataset,
shuffle=True,
batch_size=batch_size)
test_dataset = datasets.MNIST(root='../dataset/mnist/',
train=False,
download=True,
transform=transform)
test_loader = DataLoader(test_dataset,
shuffle=False,
batch_size=batch_size)
在图像处理领域,灰度图并非是一个简单的矩阵,灰度图是单通道;彩色图像是通道(Channel),由多层构成;数据一般是由的数据构成,分别表示图像的宽度、高度、通道数构成,我们在Pytorch处理的过程中应当将其映射为大小的张量数据,以提高处理的效率。
网络结构:
class Net(torch.nn.Module):
def __init__(self):
super(Net, self).__init__()
self.l1 = torch.nn.Linear(784, 512)
self.l2 = torch.nn.Linear(512, 256)
self.l3 = torch.nn.Linear(256, 128)
self.l4 = torch.nn.Linear(128, 64)
self.l5 = torch.nn.Linear(64, 10)
def forward(self, x):
x = x.view(-1, 784)
x = F.relu(self.l1(x))
x = F.relu(self.l2(x))
x = F.relu(self.l3(x))
x = F.relu(self.l4(x))
return self.l5(x)
model = Net()
损失函数:
criterion = torch.nn.CrossEntropyLoss() #交叉熵损失
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
#梯度下降法,学习率0.01,更换了momentum优化算法,带冲量的
训练过程:
def train(epoch):
running_loss = 0.0
for batch_idx, data in enumerate(train_loader, 0):
#enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时
#列出数据和数据下标,一般用在 for 循环当中。参数0是指从0开始;
inputs, target = data
optimizer.zero_grad() #优化器清零
# forward + backward + update
outputs = model(inputs)
loss = criterion(outputs, target)
loss.backward()
optimizer.step()
running_loss += loss.item() #计算累计的loss
if batch_idx % 300 == 299: #每300轮输出一次
print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 300))
running_loss = 0.0
测试函数:
def test():
correct = 0
total = 0
with torch.no_grad(): #测试的时候不用计算梯度
for data in test_loader: #从测试集中拿数据
images, labels = data
outputs = model(images) #做预测
_, predicted = torch.max(outputs.data, dim=1) #拿到最大值的下标,只需要下标;
total += labels.size(0) #total是计算样本的总数
correct += (predicted == labels).sum().item()
print('Accuracy on test set: %d %%' % (100 * correct / total))
主函数:
if __name__ == '__main__':
for epoch in range(10):
train(epoch)
test()
在图像处理的时候,使用全连接的神经网络,会导致权重数量少,只关注于原始特征,忽略了局部特征,正确率无法达到很高的水平。
人工特征提取:傅里叶变换/小波进行特征提取
自动特征提取:CNN等