栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

【 Softmax 回归 + 图片分类数据集】

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【 Softmax 回归 + 图片分类数据集】

  Softmax回归虽然叫做回归,但其解决的是分类问题

回归VS分类

  • 回归估计一个连续值,输出往往只有一个
  • 分类预测一个离散类别,通常有多个输出,输出 i i i是预测为第 i i i类的置信度

从回归到多类分类-校验比例

  • 对类别进行一位有效编码
    y = [ y 1 , y 2 , . . . , y n ] T y i = θ p ( x ) = { 1 i f i = y 0 o t h e r w i s e begin{aligned}y&=[y_1,y_2,...,y_n]^T \y_i&=theta_p(x)=left{ begin{array}{rcl} 1 & & {ifquad i=y}\ 0 & & {otherwise} end{array} right.end{aligned} yyi​​=[y1​,y2​,...,yn​]T=θp​(x)={10​​ifi=yotherwise​​

  • 最大值最为预测
    y ^ = arg max ⁡ i o i hat y=argmax_io_i y^​=iargmax​oi​

同时为了转化成概率问题,我们让该模型所有输出和为1,于是就引出了softmax函数。
y ^ i = e o i ∑ k = 1 n e o k hat y_i=frac{e^{o_i}}{sumlimits_{k=1}^ne^{o_k}} y^​i​=k=1∑n​eok​eoi​​
此时每一个输出 y ^ i hat y_i y^​i​就可以看作分类为 i i i的概率,同样我们选择最大的概率作为其分类

softmax和交叉熵损失

交叉熵通常用来衡量两个概率的区别:
L = 1 n ∑ i = 1 n ( − ∑ j = 1 C y i , j log ⁡ p i , j ) L=frac1nsumlimits_{i=1}^n(-sumlimits_{j=1}^Cy_{i,j}log p_{i,j}) L=n1​i=1∑n​(−j=1∑C​yi,j​logpi,j​)
其中 n n n为bath_size,C为类的数目, y i , j y_{i,j} yi,j​表示第 i i i个样本在第 j j j个标签上的真实数值(往往一个 i i i中只有一个值为1,其余都为0), p i , j p_{i,j} pi,j​表示第 i i i个样本被预测为第 j j j个类别的概率

如果我们看单一样本:

L i = − ∑ j = 1 C y i , j log ⁡ p i , j L_i=-sumlimits_{j=1}^Cy_{i,j}log p_{i,j} Li​=−j=1∑C​yi,j​logpi,j​

前面有提过所有分类中只有一个标签值为1,其余都为0,因此我们可以得到:
L i = − log ⁡ p Y ( i ) L_i=-log p_{Y_{(i)}} Li​=−logpY(i)​​
其中 p Y ( i ) p_{Y_{(i)}} pY(i)​​表示被正确分类的概率,同时我们扩充到整个bath_size可以得到:

L = 1 n ∑ i = 1 n ( − log ⁡ p Y ( i ) ) L=frac1nsumlimits_{i=1}^n(-log p_{Y_{(i)}}) L=n1​i=1∑n​(−logpY(i)​​)

因此我们就可以使用softmax函数来求得 p Y ( i ) p_{Y_{(i)}} pY(i)​​,我们使用交叉熵函数作为损失函数

Softmax回归从零实现

  • 数据集大致介绍:此数据集一共有十个类别(不同的服装),训练集有60000张图片,测试集有10000张,
import torch
import torchvision
from matplotlib import pyplot as plt
from torchvision import datasets
from torchvision import transforms
from torch.utils import data
# 获取数据集
trans = transforms.ToTensor()

train_data = datasets.FashionMNIST(root='../data/', train=True, 
                                  transform=trans, download=True)

test_data = datasets.FashionMNIST(root='../data/', train=False, 
                                  transform=trans, download=True)

print(len(train_data))
print(len(test_data))
60000
10000
train_data[0][0].shape # 原数据集的形状是 1 * 28 * 28的
torch.Size([1, 28, 28])
# 获取所有类别
classes = train_data.classes
# 可视化几张图片
def show_imges(imgs, num_rows, num_cols, scale=1.5, titles=None):
    figsize = (num_cols * scale, num_rows * scale)
    _, axes = plt.subplots(num_rows, num_cols, figsize=figsize)
    axes = axes.flatten()
    for i, (img, axe) in enumerate(zip(imgs, axes)):
        if torch.is_tensor(img):
            axe.imshow(img.numpy())
        else: 
            axe.imshow(img)
        axe.axes.get_xaxis().set_visible(False) # 隐藏X轴和y轴
        axe.axes.get_yaxis().set_visible(False)
        if titles:
            axe.set_title(titles[i])
X, y = next(iter(data.DataLoader(train_data, batch_size=18)))
print(X.shape)
titles = [classes[i] for i in y]
show_imges(X.reshape(18, 28, 28), 3, 6, titles=titles)
torch.Size([18, 1, 28, 28])

# 获取数据采集器
def get_dataloader(batch_size, train_data, test_data):
    train_dataloader = data.DataLoader(train_data, batch_size=batch_size, shuffle=True)
    test_dataloader = data.DataLoader(test_data, batch_size=batch_size, shuffle=False)
    return train_dataloader, test_dataloader
# 定义softmax过程
def softmax(x):
    x_exp = torch.exp(x)
    sum_exp = torch.sum(x_exp, dim=-1, keepdim=True)
    return x_exp / sum_exp
# 定义训练模型
def model(X, w, b):
    return softmax(torch.matmul(X.reshape((-1, w.shape[0])), w) + b)
# 定义交叉熵损失函数
def cross_entropy(y, y_hat):
    return -torch.log(y_hat[range(len(y_hat)), y])
# 定义优化方式,仍然使用MBGD
def mbgd(params, lr, batch_size):
    with torch.no_grad():
        for param in params:
            param -= lr * param.grad / batch_size
            param.grad.zero_()
# 定义评判方法,对于分类问题,我们常使用准确率来判定
def accuracy(y, y_hat):
    padding = torch.argmax(y_hat, -1)
    right = (padding == y).sum().numpy()
    return right / y.shape[0]
# 进行训练
lr = 0.03
batch_size = 100
epochs = 10

w = torch.normal(0, 0.01, size=(28*28,10), requires_grad=True)
b = torch.zeros(10, requires_grad=True)

train_dataloader, test_dataloader = get_dataloader(batch_size, train_data, test_data)

for epoch in range(epochs):
    train_acc = 0
    test_acc = 0
    for X,y in train_dataloader:
        y_hat = model(X, w, b)
        l = cross_entropy(y, y_hat)
        l.sum().backward() # 进行反向传播计算梯度
        mbgd([w, b], lr, batch_size)
        train_acc += accuracy(y, y_hat)
    # 计算在测试集上的准确率
    with torch.no_grad():
        for x,Y in test_dataloader:
            Y_hat = model(x, w, b)
            test_acc += accuracy(Y, Y_hat)
            
    print(f'epoch is now{epoch + 1}, the accuracy on train data is {train_acc / (len(train_data) / bacth_size)}, and the accuracy on test data is {test_acc / (len(test_data) / bacth_size)}')
epoch is now1, the accuracy on train data is 0.7468833333333319, and the accuracy on test data is 0.7848999999999999
epoch is now2, the accuracy on train data is 0.8095833333333329, and the accuracy on test data is 0.8081999999999997
epoch is now3, the accuracy on train data is 0.8225000000000002, and the accuracy on test data is 0.8149
epoch is now4, the accuracy on train data is 0.8292666666666669, and the accuracy on test data is 0.8205000000000001
epoch is now5, the accuracy on train data is 0.8340500000000005, and the accuracy on test data is 0.8242999999999998
epoch is now6, the accuracy on train data is 0.8371499999999998, and the accuracy on test data is 0.8253
epoch is now7, the accuracy on train data is 0.839849999999999, and the accuracy on test data is 0.8286999999999997
epoch is now8, the accuracy on train data is 0.8423000000000006, and the accuracy on test data is 0.8280999999999996
epoch is now9, the accuracy on train data is 0.8442166666666672, and the accuracy on test data is 0.8315999999999996
epoch is now10, the accuracy on train data is 0.8458499999999998, and the accuracy on test data is 0.8337999999999997

softmax回归简洁实现

import torch
import torchvision
from matplotlib import pyplot as plt
from torchvision import datasets
from torchvision import transforms
from torch.utils import data
import torch.nn as nn
# 获取数据集
trans = transforms.ToTensor()

train_data = datasets.FashionMNIST(root='../data/', train=True, 
                                  transform=trans, download=True)

test_data = datasets.FashionMNIST(root='../data/', train=False, 
                                  transform=trans, download=True)
# 获取数据采集器
def get_dataloader(batch_size, train_data, test_data):
    train_dataloader = data.DataLoader(train_data, batch_size=batch_size, shuffle=True, d)
    test_dataloader = data.DataLoader(test_data, batch_size=batch_size, shuffle=False)
    return train_dataloader, test_dataloader
# 定义训练模型 (我们直接使用torch.nn里面集成的库即可)
model = nn.Sequential(
    nn.Flatten(),
    nn.Linear(28*28, 10)
)

# 初始化模型参数
def init_wight(net):
    if type(net) == nn.Linear:
        nn.init.normal_(net.weight, std=0.01)

model.apply(init_wight)
Sequential(
  (0): Flatten(start_dim=1, end_dim=-1)
  (1): Linear(in_features=784, out_features=10, bias=True)
)
# 定义损失函数
loss = nn.CrossEntropyLoss()
# 定义优化方式
optimizer = torch.optim.SGD(model.parameters(), lr=0.03)
# 定义评判方法,对于分类问题,我们常使用准确率来判定
def accuracy(y, y_hat):
    padding = torch.argmax(y_hat, -1)
    right = (padding == y).sum().numpy()
    return right / y.shape[0]
# 进行训练
lr = 0.03
batch_size = 100
epochs = 10

train_dataloader, test_dataloader = get_dataloader(batch_size, train_data, test_data)

for epoch in range(epochs):
    train_acc = 0
    test_acc = 0
    for X,y in train_dataloader:
        y_hat = model(X)
        l = loss(y_hat, y)
        optimizer.zero_grad()
        l.backward() # 进行反向传播计算梯度
        optimizer.step()
        train_acc += accuracy(y, y_hat)
    # 计算在测试集上的准确率
    with torch.no_grad():
        for x,Y in test_dataloader:
            Y_hat = model(x)
            test_acc += accuracy(Y, Y_hat)
            
    print(f'epoch is now{epoch + 1}, the accuracy on train data is {train_acc / (len(train_data) / batch_size)}, and the accuracy on test data is {test_acc / (len(test_data) / batch_size)}')
epoch is now1, the accuracy on train data is 0.8088666666666672, and the accuracy on test data is 0.8020000000000005
epoch is now2, the accuracy on train data is 0.8227500000000004, and the accuracy on test data is 0.8151
epoch is now3, the accuracy on train data is 0.8292666666666663, and the accuracy on test data is 0.8188000000000002
epoch is now4, the accuracy on train data is 0.83535, and the accuracy on test data is 0.8214999999999997
epoch is now5, the accuracy on train data is 0.8376166666666672, and the accuracy on test data is 0.8234999999999998
epoch is now6, the accuracy on train data is 0.840483333333333, and the accuracy on test data is 0.8277999999999995
epoch is now7, the accuracy on train data is 0.8423333333333328, and the accuracy on test data is 0.8299999999999998
epoch is now8, the accuracy on train data is 0.8441166666666657, and the accuracy on test data is 0.8317000000000003
epoch is now9, the accuracy on train data is 0.8461333333333325, and the accuracy on test data is 0.8334999999999997
epoch is now10, the accuracy on train data is 0.8475833333333337, and the accuracy on test data is 0.8334999999999998
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/977303.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号