【Pytorch】学习笔记(三)

1 逻辑蒂斯回归

名为回归的分类函数,在分类问题里面输出的是一个概率

导入数据库

import torchvision
train_set = torchvision.datasets.MNIST(root='../dataset/mnist',train=True,download=True)
test_set = torchvision.datasets.MNIST(root='../dataset/mnist',train=False,download=True)

在这里插入图片描述
上图都是sigmoid函数,满足:(1)函数有极限;(2)单调增函数;(3)饱和函数(对应的导数为正态分布),其中最典型的是logistic function(逻辑蒂斯回归),因此也叫logistic functionsigmoid function
https://en.wikipedia.org/wiki/Logistic_function
∂ ( x ) = 1 1 + e − x \partial (x) = \frac {1} {1+e^{-x}} (x)=1+ex1
在深度学习中出现的 ∂ \partial 一般指代logistic函数
在这里插入图片描述
logistic函数将实数映射到0-1之间

1.1 逻辑回归模型

在这里插入图片描述

1.2 二分类交叉熵损失(BCE Loss)

比较两个分布之间的差异
其中真值Y的取值为0或1
在这里插入图片描述
公式:
l o s s = − ( y l o g y ^ + ( 1 − y ) l o g ( 1 − y ^ ) ) loss = -(ylog \hat y+(1-y)log(1-\hat y)) loss=(ylogy^+(1y)log(1y^))
在这里插入图片描述
公式:
l o s s = − 1 N ∑ n = 1 N y n l o g y ^ n + ( 1 − y n ) l o g ( 1 − y ^ n ) loss = -\frac {1}{N}\sum ^{N}_{n=1}y_nlog \hat y_n+(1-y_n)log(1-\hat y_n) loss=N1n=1Nynlogy^n+(1yn)log(1y^n)

1.3 完整代码

"""
2021.08.04
author:alian
06逻辑蒂斯回归
"""

import torch
import torch.nn.functional as F
import torchvision
train_set = torchvision.datasets.MNIST(root='../dataset/mnist',train=True,download=True)
test_set = torchvision.datasets.MNIST(root='../dataset/mnist',train=False,download=True)
# 1.准备数据集
x_data = torch.Tensor([[1.0],[2.0],[3.0]])
y_data = torch.Tensor([[0],[0],[1]])

# 2.构造函数
class LogisticRegressionModel(torch.nn.Module):
    def __init__(self):  # 初始化
        super(LogisticRegressionModel,self).__init__()
        self.linear = torch.nn.Linear(1,1)  # 构造对象,包含权重w和偏置b

    def forward(self,x):  # 前馈是要执行的计算
        y_pred = F.sigmoid(self.linear(x)) # 1.增加非线性变换
        return  y_pred

model = LogisticRegressionModel()
# 3.构造损失函数和优化器
criterion = torch.nn.BCELoss(size_average=False)  # 2. MSE损失变成BCE损失
optimizer = torch.optim.SGD(model.parameters(),lr=0.01)
# 4.训练循环
for epoch in range(100):
    y_pred = model(x_data)
    loss = criterion(y_pred,y_data)
    print(epoch,loss)

    optimizer.zero_grad()  # 梯度归零
    loss.backward()  # 损失反向传播
    optimizer.step()  # 权重更新

# 结果测试
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,10,200)
x_t = torch.Tensor(x).view((200,1))  # reshape
y_t = model(x_t)
y = y_t.data.numpy()  # 获取数值
plt.plot(x,y)
plt.plot([0,10],[0.5,0.5],c='r')
plt.xlabel('Hours')
plt.ylabel('Probability of Pass')
plt.grid()
plt.show( )

2 处理多维特征输入

2.1多维输入计算理解图(向量)

在这里插入图片描述
pytorch提供的sigmoid函数以向量的形式来计算,与numpy十分相似
在这里插入图片描述
矩阵计算的优势: 将方程运算转换成矩阵运算,向量化运算可以利用GPU的并行运算能力,提高运算速度
输入与输出在矩阵空间的变换原理(如下图):
在这里插入图片描述
将X从N维空间映射到M维空间,通过一个M*N的矩阵的线性变换即可。

但是我们常做的空间变换不一定是线性的,可能是非常复杂的非线性的,所以就想用多个线性变换层通过找到最优的权重,并加入非线性激活,把它们组合起来,来模拟这种非线性变换。所以我们使用卷积神经网络的本质就是寻找一种非线性的空间变换函数

2.2 多个线性层的链接

线性层可以实现不同维度的输入和输出之间的维度转换
在这里插入图片描述

完整代码

"""
2021.08.05
author:alian
07 处理多维特征的输入
"""
import torch
import numpy as np
# 1.准备数据集
xy = np.loadtxt('diabets.csv.gz',delimiter=',',dtype=np.float32)
x_data = torch.from_numpy(xy[:,:-1])
y_data = torch.from_numpy(xy[:,[-1]])  # []保证取出的是向量

# 2.构造函数(多层线性层)
class Model(torch.nn.Module):
    def __init__(self):  # 初始化
        super(Model,self).__init__()
        # 多层线性层
        self.linear1 = torch.nn.Linear(8, 6)  # 输入是8维度,输出是6维度
        self.linear2 = torch.nn.Linear(6, 4)
        self.linear3 = torch.nn.Linear(4, 1)
        # nn.functionl.sigmoid (函数) nn.Sigmoid()是一个模块,功能相同
        self.sigmoid = torch.nn.Sigmoid()  # 激活函数,为了给线性模型增加非线性变换

    def forward(self,x):  # 前馈是要执行的计算
        x = self.sigmoid(self.linear1(x))
        x = self.sigmoid(self.linear2(x))
        x = self.sigmoid(self.linear3(x))
        return x
model = Model()
# 3.构造损失和优化器

criterion = torch.nn.BCELoss(size_average=True)
optimizer = torch.optim.SGD(model.parameters(),lr=0.01)

# 4.训练循环
for epoch in range(100):
    y_pred = model(x_data)
    loss = criterion(y_pred,y_data)
    print(epoch,loss.item())

    optimizer.zero_grad()  # 梯度归零
    loss.backward()  # 损失反向传播
    optimizer.step()  # 权重更新

2.3 各类激活函数

http://rasbt.github.io/mlxtend/user_guide/general_concepts/activation-functions/#activation-functions-for-artificial-neural-networks
在这里插入图片描述
查看激活函数长什么样子
https://dasheeB7.github.io/data#20science/deep#20learning/visualising-activation-functions-in-neural-networks/
查看pytorch激活函数的文档信息
https://pytorch.org/docs/stable/nn.html#non-linear-activations-weighted-sum-nonlinearity

3 数据集加载

3.1 理解Epoch, Batch-Size, Iterations

  • Epoch:对所有的训练样本都进行了一次前向传播和反向传播的过程
  • Batch-Size:进行一次前馈+反向传播+更新参数所用的样本数量
  • Iterations:迭代次数=全部样本/Batch-Size

3.2 DataLoader(batch_size=2,shuffle = True(打乱))使用

DataLoader:需要知道数据集的样本的长度及其索引
shuffle:打乱数据集的顺序

"""
2021.08.05
author:alian
08加载数据集
"""
import torch
from torch.utils.data import Dataset,DataLoader
import numpy as np

# 自定义数据集
class DiabetesDataset(Dataset):
    def __init__(self,filepath):
        xy = np.loadtxt(filepath, delimiter=',', dtype=np.float32)  # 数据路径,以“,”作为分隔符,读取32位 的数列
        self.len = xy.shape[0]  # 获得数据长度
        self.x_data = torch.from_numpy(xy[:, :-1])  # 读取前8列
        self.y_data = torch.from_numpy(xy[:, [-1]])  # 读取最后一列,[]保证取出的是向量

    def __getitem__(self, index):
        return self.x_data[index],self.y_data[index]  # 获得数据索引

    def __len__(self):
        return self.len

dataset = DiabetesDataset('diabets.csv.gz')  # 传入路径
# 以一个batch_size的数据量加载数据集
train_loder = DataLoader(dataset=dataset,
                         batch_size=32,
                         shuffle=True,
                         num_workers=2)

# 2.构造函数(多层线性层)
class Model(torch.nn.Module):
    def __init__(self):  # 初始化
        super(Model,self).__init__()
        self.linear1 = torch.nn.Linear(8, 6)  # 输入是8维度,输出是1维度
        self.linear2 = torch.nn.Linear(6, 4)
        self.linear3 = torch.nn.Linear(4, 1)
        self.sigmoid = torch.nn.Sigmoid()

    def forward(self,x):  # 前馈是要执行的计算
        x = self.sigmoid(self.linear1(x))
        x = self.sigmoid(self.linear2(x))
        x = self.sigmoid(self.linear3(x))
        return x
model = Model()

# 3.构造损失和优化器

criterion = torch.nn.BCELoss(size_average=False)
optimizer = torch.optim.SGD(model.parameters(),lr=0.01)

# 4.训练循环
for epoch in range(100):
    for i, data in enumerate(train_loder,0):  # 一个iteration
        # 1. Prepare data
        input,labels = data
        # 2. Forward
        y_pred = model(input)
        loss = criterion(y_pred,labels)  # 计算损失
        print(epoch,loss.item())
        # 3.Backward
        optimizer.zero_grad()  # 梯度归零
        loss.backward()  # 损失反向传播
        # 4. Update
        optimizer.step()  # 权重更新

3.3 num_workers in Windows(多进程在Windows下的限制)

在这里插入图片描述
问题解决:将包含DataLoder的循环代码封装起来,而不是在主程序中调用
在这里插入图片描述

3.4 torchvision内置数据集(可加载的)

# 加载内置数据集
import torch
from torch.utils.data import DataLoader
from torchvision import datasets,transforms

train_dataset = datasets.MNIST(root='../dataset/mnist',  # 路径
                               train=True,
                               transform=transforms.ToTensor(),  # 图像转换为张量
                               download=True)  # 是否在线下载

test_dataset = datasets.MNIST(root='../dataset/mnist',
                               train=False,
                               transform=transforms.ToTensor(),  # 图像转换为张量
                               download=True)
# 数据加载,以batch_size的数据量进行加载(由于硬件的限制,无法一次性加载全部数据)
train_loder = DataLoader(dataset=train_dataset,
                         batch_size=32,
                         shuffle=True)
test_loder = DataLoader(dataset=train_dataset,
                         batch_size=32,
                         shuffle=False)
for batch_idx,(inputs, target) in enumerate(train_loader):

在这里插入图片描述

3.5 练习

训练目标:乘客是否存活
https://www.kaggle.com/c/titanic/data
在这里插入图片描述

4 多分类问题

4.1 Softmax Classifier 如何解决多分类问题

分布:属于每个类别的概率
多分类问题需要满足:

  1. P ( y = i ) ≥ 0 P(y=i)\geq 0 P(y=i)0
  2. ∑ i = 0 N P ( y = i ) = 1 \sum ^N_{i=0}{P(y=i)=1} i=0NP(y=i)=1

Softmax函数满足上诉要求:
在这里插入图片描述
P ( y = i ) = e Z i ∑ j = 0 K − 1 e Z j , i ∈ ( 0 , . . . , K − 1 ) P(y=i)=\frac {e^{Z_i}}{\sum ^{K-1}_{j=0}{e^{Z_j}}},i\in (0,...,K-1) P(y=i)=j=0K1eZjeZi,i(0,...,K1)

4.2 多分类的损失函数: 交叉熵损失

基于二分类的交叉熵损失进行扩展,真值Y为One-hot分布,真实类别为1,其余的类别为0

(1)基于numpy的多分类交叉熵

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()
loss = (-y*np.log(y_pred)).sum()
print(loss)

(2)pytorch实现多分类交叉熵

在这里插入图片描述

# 基于pytorch的多分类交叉熵损失
y = torch.LongTensor([0])
z = torch.Tensor([[0.2,0.1,-0.1]])
criterion = torch.nn.CrossEntropyLoss()
loss = criterion(z,y)
print(loss)

练习

https://pytorch.org/docs/stablr/nn.html#crossentropyloss
https://pytorch.org/docs/stablr/nn.html#nllloss
在这里插入图片描述

4.3 pytorch实现多分类训练

4.3.1 数据准备

import torch
from torchvision import transforms,datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim
# 1. 数据集准备
batch_size = 64
# transforms:
# (1)将图像像素值(图像张量)映射到0-1之间
# (2)H*W*C 转化成 C*H*W
# (3)Normalize,归一化(均值,标准差),使其满足0-1分布
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,),(0.3081,))
])

train_dataset = datasets.MNIST(root='../dataset/mnist',
                               train=True,
                               transform=transforms.ToTensor(),  # 图像转换为张量
                               download=True)

test_dataset = datasets.MNIST(root='../dataset/mnist',
                               train=False,
                               transform=transforms.ToTensor(),  # 图像转换为张量
                               download=True)
train_loder = DataLoader(dataset=train_dataset,
                         batch_size=32,
                         shuffle=True)
test_loder = DataLoader(dataset=train_dataset,
                         batch_size=32,
                         shuffle=False)

数据归一化:(均值,标准差)
P i x e l n o r m = P i x e l o r i g i n − m e a n s t d Pixel_{norm} = \frac {Pixel_{origin}-mean}{std} Pixelnorm=stdPixeloriginmean

4.3.2 模型设计

在这里插入图片描述

# 2. 设计模型
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()

4.3.3 构造损失和优化器

# 3. 构造损失函数和优化器
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(),lr=0.01,momentum=0.5)  # 优化器(带冲量的,0.5)

在这里插入图片描述

4.3.4 训练循环

将单轮epoch定义成函数

def train(epoch):
    running_loss = 0.0
    for batch_idx,data in enumerate(train_loder,0):
        inputs,target = data
        optimizer.zero_grad()

        # forward+backward+updata
        output = model(inputs)
        loss = criterion(output,target)
        loss.backward()
        optimizer.step()

        running_loss+=loss.item()
        if batch_idx % 300 == 299:
            print('[%d,%5d] loss: %.3f' % (epoch+1, batch_idx+1,running_loss/300))
            running_loss = 0.0

4.3.5 完整代码

"""
2021.08.05
author:alian
09多分类问题
"""
import torch
from torchvision import transforms,datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim

# 1. 数据集准备
batch_size = 64
# transforms:
# (1)将图像像素值(图像张量)映射到0-1之间
# (2)H*W*C 转化成 C*H*W
# (3)Normalize,归一化(均值,标准差),使其满足0-1分布
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,),(0.3081,))
])

train_dataset = datasets.MNIST(root='../dataset/mnist',
                               train=True,
                               transform=transforms.ToTensor(),  # 图像转换为张量
                               download=True)

test_dataset = datasets.MNIST(root='../dataset/mnist',
                               train=False,
                               transform=transforms.ToTensor(),  # 图像转换为张量
                               download=True)
train_loder = DataLoader(dataset=train_dataset,
                         batch_size=32,
                         shuffle=True)
test_loder = DataLoader(dataset=train_dataset,
                         batch_size=32,
                         shuffle=False)
# 2. 设计模型
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()

# 3. 构造损失函数和优化器
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(),lr=0.01,momentum=0.5)

# 4. 训练循环
def train(epoch):
    running_loss = 0.0
    for batch_idx,data in enumerate(train_loder,0):
        inputs,target = data
        optimizer.zero_grad()

        # forward+backward+updata
        output = model(inputs)
        loss = criterion(output,target)
        loss.backward()
        optimizer.step()

        running_loss+=loss.item()
        if batch_idx % 300 == 299:
            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_loder:
            images,labels = data
            outputs = model(images)
            _, predicted = torch.max(outputs.data, dim=1)
            total +=labels.size(0)
            correct += (predicted == labels).sum().item()
    print('Accurary on test set: %d %%' % (100 * correct/total))

if __name__ == '__mian__':
    for epoch in range(10):
        train(epoch)
        test()
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值