PyTorch深度学习

0.引言

1.pyhton 开发环境安装

2.创建python虚拟环境以及pip国内源设置

目前 python3.8 是一个兼容性比较好的版本:

conda create -n py38 python=3.8

新建的 conda 环境在电脑中的位置为: /home/q/anaconda3/envs/py38
相关的命令行:

#显示所有的虚拟环境
conda env list 或 conda info --envs

#创建python3.5的xxxx虚拟环境
conda create -n [your_env_name] python=3.5
#复制虚拟环境(必须在base环境下进行以上操作)
conda create -n [new_env_name] --clone [env_name]
#删除虚拟环境(必须在base环境下进行以上操作)
conda remove -n [your_env_name] --all
#重命名虚拟环境
#直接修改环境所在路径的文件夹名即可

#切换虚拟环境
conda activate xxxx
#关闭当前虚拟环境
conda deactivate

在这里插入图片描述

全局修改,需要修改配置文件。
Linux/Mac os 环境中,配置文件位置在 ~/.pip/pip.conf(如果不存在创建该目录和文件):

mkdir ~/.pip

打开配置文件 ~/.pip/pip.conf,修改如下:

[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
[install]
trusted-host = https://pypi.tuna.tsinghua.edu.cn

查看 镜像地址:

$ pip3 config list   
global.index-url='https://pypi.tuna.tsinghua.edu.cn/simple'
install.trusted-host='https://pypi.tuna.tsinghua.edu.cn'

可以看到已经成功修改了镜像。Windows下,你需要在当前对用户目录下(C:\Users\xx\pip,xx 表示当前使用对用户,比如张三)创建一个 pip.ini在pip.ini文件中输入以下内容:

[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
[install]
trusted-host = pypi.tuna.tsinghua.edu.cn

3.PyCharm基本用法及设置解释器

第一次打开的时候需要创建一个工程,工程的名字和位置自己定义,把 Create a main.py 取消勾选。选择解释器的时候可以选择anaconda3的解释器:

在这里插入图片描述

在setting->Editor->font 将字体改大一点:18号。

也可以选择我们创建的虚拟环境解释器:
在这里插入图片描述

PyCharm右下角可以快速切换解释器:

在这里插入图片描述

4.第一个深度学习实例手写字符识别

  • 代码地址:https://github.com/mivlab/AI_course
  • 打开PyCharm新建工程位置为代码根目录
  • 解释器选择虚拟环境解释器
  • 点击从已有源代码进行创建

在这里插入图片描述

下一弹窗单击左边三个按钮任意一个都行。

在这里插入图片描述

  • 1.安装pytorch: https://pytorch.org/get-started/locally/

安装时一定要在你使用的虚拟环境中进行安装: conda install pytorch torchvision torchaudio cpuonly -c pytorch
GPU版本:conda install pytorch torchvision torchaudio pytorch-cuda=11.1 -c pytorch -c nvidia
GPU版本:pip install torch==1.9.1+cu111 torchvision==0.10.1+cu111 torchaudio==0.9.1 -f https://download.pytorch.org/whl/torch_stable.html

err:

>>> import torchvision
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/CN/bo.feng/anaconda3/envs/mmlab-learn/lib/python3.8/site-packages/torchvision/__init__.py", line 7, in <module>
    from torchvision import datasets
  File "/home/CN/bo.feng/anaconda3/envs/mmlab-learn/lib/python3.8/site-packages/torchvision/datasets/__init__.py", line 1, in <module>
    from .lsun import LSUN, LSUNClass
  File "/home/CN/bo.feng/anaconda3/envs/mmlab-learn/lib/python3.8/site-packages/torchvision/datasets/lsun.py", line 2, in <module>
    from PIL import Image
ModuleNotFoundError: No module named 'PIL'

solved:

pip uninstall Pillow
pip uninstall PIL
pip install Pillow

在这里插入图片描述

  • 2.继续在虚拟环境中安装 opencv: pip install opencv-python
  • 3.下载数据集:
    1)下载数据集:链接:https://pan.baidu.com/s/18Fz9Cpj0Lf9BC7As8frZrw 提取码:xhgk
    2)训练:train_mnist.py
    需要加一个参数,–datapath=数据集所在的目录。
    train_mnist.py --datapath=/home/q/dataset/mnist
    3)测试:tes_mnist.py 可以识别一张新的图片的类别。

MNIST数据库一共有四个文件:
‒ 1. train-images-idx3-ubyte.gz:训练集图片(9912422字节),55000张训练集,5000张验证集
‒ 2. train-labels-idx1-ubyte.gz:训练集图片对应的标签(28881字节),
‒ 3. t10k-images-idx3-ubyte .gz:测试集图片(1648877字节),10000张图片
‒ 4. t10k-labels-idx1-ubyte.gz:测试集图片对应的标签(4542字节)

将参数填进去:--datapath=/home/q/dataset/mnist/train_images

在这里插入图片描述

  • 4.安装torchsummary:pip install torchsummary

  • 5.开始训练:
    在这里插入图片描述

  • 6.测试: 运行 test_mnist.py 文件

在这里插入图片描述

5.第一个深度学习实例–手写字符识别代码解析

在这里插入图片描述

Module 代码:

import torch.nn as nn
import torch
#    # 在pytorch中,自己定义的网络必须继承自 nn.Module
class Net(nn.Module):
    def __init__(self, c):
        super(Net, self).__init__()
        self.conv1 = nn.Sequential(
            nn.Conv2d(3, 32, 3, 1, 1),  # 32x28x28
            nn.ReLU(),
            nn.MaxPool2d(2)
        )  # 32x14x14
        self.conv2 = nn.Sequential(
            nn.Conv2d(32, 64, 3, 1, 1),  # 64x14x14
            nn.ReLU(),
            nn.MaxPool2d(2)  # 64x7x7
        )
        self.conv3 = nn.Sequential(
            nn.Conv2d(64, 64, 3, 1, 1),  # 64x7x7
            nn.ReLU(),
            nn.MaxPool2d(2)  # 64x3x3
        )
        self.dense = nn.Sequential(
            nn.Linear(64 * 3 * 3, 128),  # fc4 64*3*3 -> 128
            nn.ReLU(),
            nn.Linear(128, c)  # fc5 128->10
        )
    def forward(self, x):
        conv1_out = self.conv1(x)
        conv2_out = self.conv2(conv1_out)
        conv3_out = self.conv3(conv2_out)  # 64x3x3
        res = conv3_out.view(conv3_out.size(0), -1)  # batch x (64*3*3)
        #res = torch.reshape(conv3_out, (conv3_out.size(0), 64*3*3))
        out = self.dense(res) #dense 表示做全连接
        return out

训练代码:

import torch
import math
import torch.nn as nn
from torch.autograd import Variable
from torchvision import transforms, models
import argparse
import os
from torch.utils.data import DataLoader

from dataloader import mnist_loader as ml
from models.cnn import Net
from toonnx import to_onnx


parser = argparse.ArgumentParser(description='PyTorch MNIST Example')
parser.add_argument('--datapath', required=True, help='data path')
parser.add_argument('--batch_size', type=int, default=256, help='training batch size')
parser.add_argument('--epochs', type=int, default=300, help='number of epochs to train')
parser.add_argument('--use_cuda', default=False, help='using CUDA for training')

args = parser.parse_args()
args.cuda = args.use_cuda and torch.cuda.is_available()
if args.cuda:
    torch.backends.cudnn.benchmark = True


def train():
    os.makedirs('./output', exist_ok=True)
    if True: #not os.path.exists('output/total.txt'):
        ml.image_list(args.datapath, 'output/total.txt')  #将图像列表的文件分成训练集和验证集两部分  输出的文件在output文件夹下面
        ml.shuffle_split('output/total.txt', 'output/train.txt', 'output/val.txt') # 80% 作为训练集  20作为验证集

    train_data = ml.MyDataset(txt='output/train.txt', transform=transforms.ToTensor()) # 像素值0~255归一化到0~1之间
    val_data = ml.MyDataset(txt='output/val.txt', transform=transforms.ToTensor())
    train_loader = DataLoader(dataset=train_data, batch_size=args.batch_size, shuffle=True) #将训练集进行分批次加载训练,一次加载batch_size大小的数据
    val_loader = DataLoader(dataset=val_data, batch_size=args.batch_size)

    model = Net(10)
    #model = models.vgg16(num_classes=10)
    #model = models.resnet18(num_classes=10)  # 调用内置模型
    #model.load_state_dict(torch.load('./output/params_10.pth'))
    from torchsummary import summary
    summary(model, (3, 28, 28))

    if args.cuda:
        print('training with cuda')
        model.cuda()
    optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=1e-3) #优化器采用 Adam,初始学习率为0.01,权重衰减系数为 1*10^-4
    scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer, [20, 30], 0.1) #按照阶梯调整学习速率的方式:达到第20个 epoch的时候,学习率*0.1,达到第30个 epoch的时候,学习率再*0.1,
    loss_func = nn.CrossEntropyLoss()#定义损失函数:交叉熵损失函数

    for epoch in range(args.epochs): #开始训练
        # training-----------------------------------
        model.train() #进入训练模式
        train_loss = 0
        train_acc = 0
        for batch, (batch_x, batch_y) in enumerate(train_loader):#第二层循环对每一个批次做训练,使用训练加载器train_loader加载batch
            if args.cuda:
                batch_x, batch_y = Variable(batch_x.cuda()), Variable(batch_y.cuda())
            else:
                batch_x, batch_y = Variable(batch_x), Variable(batch_y)
            # 256x3x28x28  256:一个批次有256张图,3:rgb 3通道,28*28:图像的宽高。
            # out 256x10 ,256:一个批次有256个样本,10:表示每张图要输出10个值,
            # 这10个值就代表了这个样本属于这10个类别的概率值(和为1),注意:要经过softmax才会变成概率值,这一步是在CrossEntropyLoss里面做的。
            out = model(batch_x)
            loss = loss_func(out, batch_y) #计算损失函数
            train_loss += loss.item()
            pred = torch.max(out, 1)[1] #取最大的那一类的标签
            train_correct = (pred == batch_y).sum() #统计正确的个数
            train_acc += train_correct.item()
            print('epoch: %2d/%d batch %3d/%d  Train Loss: %.3f, Acc: %.3f'
                  % (epoch + 1, args.epochs, batch, math.ceil(len(train_data) / args.batch_size),
                     loss.item(), train_correct.item() / len(batch_x)))

            optimizer.zero_grad()
            loss.backward() #误差反向传播?
            optimizer.step()
        scheduler.step()  # 更新learning rate
        print('Train Loss: %.6f, Acc: %.3f' % (train_loss / (math.ceil(len(train_data)/args.batch_size)),
                                               train_acc / (len(train_data))))
        # 在完成一个epoch后对模型进行一次评估
        # evaluation--------------------------------
        model.eval()
        eval_loss = 0
        eval_acc = 0
        for batch_x, batch_y in val_loader:
            if args.cuda:
                batch_x, batch_y = Variable(batch_x.cuda()), Variable(batch_y.cuda())
            else:
                batch_x, batch_y = Variable(batch_x), Variable(batch_y)

            out = model(batch_x)
            loss = loss_func(out, batch_y)
            eval_loss += loss.item()
            pred = torch.max(out, 1)[1]
            num_correct = (pred == batch_y).sum()
            eval_acc += num_correct.item()
        print('Val Loss: %.6f, Acc: %.3f' % (eval_loss / (math.ceil(len(val_data)/args.batch_size)),
                                             eval_acc / (len(val_data))))
        # 保存模型。每隔多少帧存模型,此处可修改------------
        if (epoch + 1) % 1 == 0:
            # torch.save(model, 'output/model_' + str(epoch+1) + '.pth')
            torch.save(model.state_dict(), 'output/params_' + str(epoch + 1) + '.pth')
            #to_onnx(model, 3, 28, 28, 'params.onnx')

if __name__ == '__main__':
    train()

保存模型:

        # 保存模型。每隔多少帧存模型,此处可修改------------
        if (epoch + 1) % 1 == 0:
            # torch.save(model, 'output/model_' + str(epoch+1) + '.pth')
            torch.save(model.state_dict(), 'output/params_' + str(epoch + 1) + '.pth')
            #to_onnx(model, 3, 28, 28, 'params.onnx')

使用模型:

import torch
import cv2
from torch.autograd import Variable
from torchvision import transforms
from models.cnn import Net
from toonnx import to_onnx

use_cuda = False
model = Net(10)
# 注意:此处应把pth文件改为你训练出来的params_x.pth,x为epoch编号,
# 一般来讲,编号越大,且训练集(train)和验证集(val)上准确率差别越小的(避免过拟合),效果越好。
model.load_state_dict(torch.load('output/params_yl.pth'))
# model = torch.load('output/model.pth')
model.eval()
if use_cuda and torch.cuda.is_available():
    model.cuda()

to_onnx(model, 3, 28, 28, 'output/params.onnx')

img = cv2.imread('4_00440.jpg')
img = cv2.resize(img, (28, 28))
img_tensor = transforms.ToTensor()(img)
img_tensor = img_tensor.unsqueeze(0)
if use_cuda and torch.cuda.is_available():
    prediction = model(Variable(img_tensor.cuda()))
else:
    prediction = model(Variable(img_tensor))
pred = torch.max(prediction, 1)[1]
print(prediction)
print(pred)
cv2.imshow("image", img)
cv2.waitKey(0)

6.性别识别-最简单的神经网络-逻辑回归

根据一个人的身高体重,预测其性别:

在这里插入图片描述

import torch
import math
import torch.nn as nn
from torch.autograd import Variable
from torchvision import transforms, models
import argparse
import os
from torch.utils.data import DataLoader
from torch.utils.data import Dataset

class SexDataset(Dataset):
    def __init__(self, txt, transform=None, target_transform=None):
        fh = open(txt, 'r')
        data = []
        for line in fh:
            line = line.strip('\n')
            words = line.split()
            data.append((float(words[0]) / 2.0, float(words[1]) / 80.0, int(words[2])))
        self.data = data

    def __getitem__(self, index):
        return torch.FloatTensor([self.data[index][0], self.data[index][1]]), self.data[index][2]

    def __len__(self):
        return len(self.data)

class SexNet(nn.Module):
    def __init__(self):
        super(SexNet, self).__init__()
        self.dense = nn.Sequential(
            nn.Linear(2, 2)
        )

    def forward(self, x):
        out = self.dense(x)
        return out

def train():
    os.makedirs('./output', exist_ok=True)
    train_data = SexDataset(txt='sex_train.txt')
    val_data = SexDataset(txt='sex_val.txt')
    batchsize = 10
    train_loader = DataLoader(dataset=train_data, batch_size=batchsize, shuffle=True)
    val_loader = DataLoader(dataset=val_data, batch_size=batchsize)

    model = SexNet()

    optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=1e-3)
    scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer, [100, 200], 0.1)
    loss_func = nn.CrossEntropyLoss()

    epochs = 100
    for epoch in range(epochs):
        # training-----------------------------------
        model.train()
        train_loss = 0
        train_acc = 0
        for batch, (batch_x, batch_y) in enumerate(train_loader):
            batch_x, batch_y = Variable(batch_x), Variable(batch_y)
            out = model(batch_x)
            loss = loss_func(out, batch_y)
            train_loss += loss.item()
            pred = torch.max(out, 1)[1]
            train_correct = (pred == batch_y).sum()
            train_acc += train_correct.item()
            print('epoch: %2d/%d batch %3d/%d  Train Loss: %.3f, Acc: %.3f'
                  % (epoch + 1, epochs, batch, math.ceil(len(train_data) / batchsize),
                     loss.item(), train_correct.item() / len(batch_x)))

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        scheduler.step()  # 更新learning rate
        print('Train Loss: %.6f, Acc: %.3f' % (train_loss / (math.ceil(len(train_data)/batchsize)),
                                               train_acc / (len(train_data))))

        # evaluation--------------------------------
        model.eval()
        eval_loss = 0
        eval_acc = 0
        for batch_x, batch_y in val_loader:
            batch_x, batch_y = Variable(batch_x), Variable(batch_y)

            out = model(batch_x)
            loss = loss_func(out, batch_y)
            eval_loss += loss.item()
            pred = torch.max(out, 1)[1]
            num_correct = (pred == batch_y).sum()
            eval_acc += num_correct.item()
        print('Val Loss: %.6f, Acc: %.3f' % (eval_loss / (math.ceil(len(val_data)/batchsize)),
                                             eval_acc / (len(val_data))))
        # save model --------------------------------
        if (epoch + 1) % 1 == 0:
            # torch.save(model, 'output/model_' + str(epoch+1) + '.pth')
            torch.save(model.state_dict(), 'output/params_' + str(epoch + 1) + '.pth')
            #to_onnx(model, 3, 28, 28, 'params.onnx')

if __name__ == '__main__':
    train()

总结一下,如果需要实现一个简单的图像分类:
‒ 自定义一个 **Dataset 类,它是继承自 pytorch的Dataset这个类,这个类主要实现两个功能:一个是根据样本编号index来获取样本特征,如身高体重,以及获取它的类别;第二个作用是获得样本的个数。
‒ 自定义一个网络模型类,它是继承自 pytorch的nn.Module这个类,在里面定义网络结构。
‒ 自定义训练过程。

7.深度学习网络结构可视化

在这里插入图片描述

以第四节的手写字符识别为例,其模型代码为:

class Net(nn.Module):
    def __init__(self, c):
        super(Net, self).__init__()
        self.conv1 = nn.Sequential(
            nn.Conv2d(3, 32, 3, 1, 1),  # 32x28x28
            nn.ReLU(),
            nn.MaxPool2d(2)
        )  # 32x14x14
        self.conv2 = nn.Sequential(
            nn.Conv2d(32, 64, 3, 1, 1),  # 64x14x14
            nn.ReLU(),
            nn.MaxPool2d(2)  # 64x7x7
        )
        self.conv3 = nn.Sequential(
            nn.Conv2d(64, 64, 3, 1, 1),  # 64x7x7
            nn.ReLU(),
            nn.MaxPool2d(2)  # 64x3x3
        )
        self.dense = nn.Sequential(
            nn.Linear(64 * 3 * 3, 128),  # fc4 64*3*3 -> 128
            nn.ReLU(),
            nn.Linear(128, c)  # fc5 128->10
        )
    def forward(self, x):
        conv1_out = self.conv1(x)
        conv2_out = self.conv2(conv1_out)
        conv3_out = self.conv3(conv2_out)  # 64x3x3
        res = conv3_out.view(conv3_out.size(0), -1)  # batch x (64*3*3)
        #res = torch.reshape(conv3_out, (conv3_out.size(0), 64*3*3))
        out = self.dense(res) #dense 表示做全连接
        return out

使用了一个工具: https://github.com/lutzroeder/netron

step1:生成 params.onnx文件:

def to_onnx(model, c, w, h, onnx_name):
    dummy_input = torch.randn(1, c, w, h, device='cpu')
    torch.onnx.export(model, dummy_input, onnx_name, verbose=True)
from toonnx import to_onnx
to_onnx(model, 3, 28, 28, 'params.onnx')

Q: to_onnx函数怎么写的?

step 2 :L将生成的 param.onnx文件拖入Netron 中:
在这里插入图片描述

可视化结果如下所示:
在这里插入图片描述

另一种可视化方法为 torchsummary:
在这里插入图片描述

    from torchsummary import summary
    summary(model, (3, 28, 28))

在开始训练之前会输出一些简要信息:

----------------------------------------------------------------
        Layer (type)               Output Shape         Param #
================================================================
            Conv2d-1           [-1, 32, 28, 28]             896
              ReLU-2           [-1, 32, 28, 28]               0
         MaxPool2d-3           [-1, 32, 14, 14]               0
            Conv2d-4           [-1, 64, 14, 14]          18,496
              ReLU-5           [-1, 64, 14, 14]               0
         MaxPool2d-6             [-1, 64, 7, 7]               0
            Conv2d-7             [-1, 64, 7, 7]          36,928
              ReLU-8             [-1, 64, 7, 7]               0
         MaxPool2d-9             [-1, 64, 3, 3]               0
           Linear-10                  [-1, 128]          73,856
             ReLU-11                  [-1, 128]               0
           Linear-12                   [-1, 10]           1,290
================================================================
Total params: 131,466
Trainable params: 131,466
Non-trainable params: 0
----------------------------------------------------------------

8.深度学习实例-图像分割1

在这里插入图片描述

参考代码:https://github.com/Tramac/awesome-semantic-segmentation-pytorch

在这里插入图片描述

在这里插入图片描述

‒ 1.下载代码,更改train参数
‒ 2. 安装缺少的依赖项: pip install tqdm、pip install scipy 注意实在当前虚拟环境进行安装。

PyCharm快捷键:这个地方是啥快捷键啊查找这个函数的: ctrl+shift+F

‒ 原視頻:https://www.bilibili.com/video/BV1Gi4y1m77E/?spm_id_from=pageDriver&vd_source=6d96ad3d63238e8488f65de89e674efa

9.图像语义分割2-用最简单的代码实现语义分割

在这里插入图片描述

Q:为什么是21通道?
A:因为VOC2012数据集一共有21个类别,然后将特征图插值放大到和原图一样大小,然后再和mask进行像素区域识别

和手写字符识别的最大的不同就是数据的标签方面。语义分割对每个像素都要赋予一个标签。

‒ 原视频链接: https://www.bilibili.com/video/BV1Y44y1g7LS/?spm_id_from=333.788

数据集展示没下载下来。

10.以基于人体姿态估计的仰卧起坐计数为例

在这里插入图片描述

在这里插入图片描述

epoch 和 batch的关系就好比我们背一本英语单词,有1000个单词,分10个单元,每个单词相当于一个训练样本,把整本书背一遍称为一个epoch,一个单元的单词称为一个batch即是一个批次。

11.理解卷积神经网络运算过程

在这里插入图片描述

'''
习题:打开一张纯色的彩色图,对它做3x3卷积,卷积系数全为0.1,偏置项也为0.1。
要求对比手工计算和程序实现的结果。
'''

import torch
import torch.nn as nn
import numpy as np
import cv2
img = cv2.imread('2.jpg', cv2.IMREAD_COLOR) #读图像,读出来格式为ndarray
img = img.transpose((2, 0, 1)) # 把HWC转换为CHW,即把第2维提前面,第0、1维放后面
conv = nn.Conv2d(3, 1, 3) #卷积参数:输入3通道,输出1通道,3x3卷积
conv.weight.requires_grad_(False) #不需要计算梯度
conv.bias.requires_grad_(False)
conv.weight[0, :, :, :] = 0.1 #设置所有权重
conv.bias[:] = 0.1 #设置所有偏置
#卷积要求的输入数据格式是NCHW,tensor浮点类型,因此需要转浮点、转tensor、由CHW变为NCHW
out = conv(torch.tensor(img.astype(np.float32)).unsqueeze(0)) #转换为tensor,并增加一维,做卷积,得到结果
print(out)
print(26*0.1*9+132*0.1*9+239*0.1*9+0.1)  #9个格子的系数均为0.1

b:
在这里插入图片描述

g:
在这里插入图片描述
r:
在这里插入图片描述

运行结果:
在这里插入图片描述


在这里插入图片描述

在这里插入图片描述

'''
习题:生成一个向量,对它做ReLU,演示其运行结果。
要求对比手工计算和程序实现的结果。
'''

import torch
import torch.nn as nn
m = nn.ReLU()
input = torch.randn(2)
output = m(input)
print(input)
print(output)
#tensor([-0.5912, -0.7376])
#tensor([0., 0.])

在这里插入图片描述

'''
习题:生成一个4x4矩阵,对它做kernel_size为2的最大池化,演示其运行结果。
'''

import torch
import torch.nn as nn
x = torch.arange(1.,17.,1.0).reshape(4, 4)
x = x.unsqueeze(0).unsqueeze(0)
pl = nn.MaxPool2d(2)
y = pl(x)
print(x)
print(y)
tensor([[[[ 1.,  2.,  3.,  4.],
          [ 5.,  6.,  7.,  8.],
          [ 9., 10., 11., 12.],
          [13., 14., 15., 16.]]]])
tensor([[[[ 6.,  8.],
          [14., 16.]]]])

在这里插入图片描述

'''
习题:定义一个全连接层,其权重和偏置都是0.1,对比手工计算和pytorch运算的结果
'''

import torch
import torch.nn as nn

input = torch.FloatTensor([1, 2, 3])
li = nn.Linear(3, 2)
li.weight.requires_grad = False
li.bias.requires_grad = False
li.weight[:] = 0.1
li.bias[:] = 0.1
output = li(input)
print(input)
print(output)
print(1*0.1 + 2*0.1 + 3*0.1 + 0.1)
tensor([1., 2., 3.])
tensor([0.7000, 0.7000])
0.7000000000000001
  • 绘制Sigmoid函数:
import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
#请修改代码,完成调用nn.Sigmoid()画出sigmoid曲线
m = nn.Sigmoid()
x = torch.arange(-10, 10, 0.1)
y = m(x)
xplot = x.numpy()
yplot = y.numpy()
plt.plot(xplot, yplot, color='#58b970', label='Regression Line')
plt.axis([-10, 10, 0, 1])
plt.show()

在这里插入图片描述

  • 创建Tensor
import torch
import numpy as np

# 这个例子程序是展示创建Tensor的各种方法

data = [[1, 2],[3, 4]]
x_data = torch.tensor(data, dtype=torch.uint8) # 把list转换为Tensor
np_array = np.array(data)
x_np = torch.from_numpy(np_array) # 把ndarray转换为Tensor
shape = (2,3)
rand_tensor = torch.rand(shape) # 根据形状创建随机数Tensor
ones_tensor = torch.ones(shape, dtype=torch.uint8) # 根据形状创建全1 的Tensor
zeros_tensor = torch.zeros(shape) # 根据形状创建全0的Tensor

print(x_data)
print(x_np)
print(rand_tensor)
print(ones_tensor)
print(zeros_tensor)
tensor([[1, 2],
        [3, 4]], dtype=torch.uint8)
tensor([[1, 2],
        [3, 4]])
tensor([[0.6191, 0.5835, 0.5323],
        [0.4516, 0.8843, 0.4424]])
tensor([[1, 1, 1],
        [1, 1, 1]], dtype=torch.uint8)
tensor([[0., 0., 0.],
        [0., 0., 0.]])
  • 张量拼接
import numpy as np
import torch
a = torch.Tensor(np.arange(1, 65, 1).reshape(8, 8))
print(a)
# 使用 PyTorch 库中的 stack 函数将两个张量沿一个新的维度拼接在一起,
# 其中第一个张量是从矩阵 a 中取出的第 1 到 2 行,第 1 到 3 列,
# 第二个张量是从矩阵 a 中取出的第 1 到 2 行,最后 3 列。
print(torch.stack([a[0:2, 0:3], a[0:2, -3:]]))
tensor([[ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.],
        [ 9., 10., 11., 12., 13., 14., 15., 16.],
        [17., 18., 19., 20., 21., 22., 23., 24.],
        [25., 26., 27., 28., 29., 30., 31., 32.],
        [33., 34., 35., 36., 37., 38., 39., 40.],
        [41., 42., 43., 44., 45., 46., 47., 48.],
        [49., 50., 51., 52., 53., 54., 55., 56.],
        [57., 58., 59., 60., 61., 62., 63., 64.]])
tensor([[[ 1.,  2.,  3.],
         [ 9., 10., 11.]],

        [[ 6.,  7.,  8.],
         [14., 15., 16.]]])
  • nn.Linear全连接层
import torch
import math
import torch.nn as nn

dense = nn.Linear(2, 1)
dense.weight.requires_grad_(False)
dense.bias.requires_grad_(False)
dense.weight[0, 0] = 0.1
dense.weight[0, 1] = 0.2
dense.bias[0] = 0.1
x = torch.Tensor([0.6, 0.8])
y = dense(x)
print(0.6 * 0.1 + 0.8 * 0.2 + 0.1)
print(y)
0.32000000000000006
tensor([0.3200])
  • BN:批量归一化
import torch
import math
import torch.nn as nn
m = nn.BatchNorm2d(2, eps=0, affine=False)

input = torch.randn(2, 2, 2, 2)
output = m(input)
print(input)
print(output)
tensor([[[[ 0.2719, -0.4281],
          [-0.9898, -1.0042]],

         [[ 0.2434,  1.2318],
          [-0.5240,  0.3968]]],


        [[[-0.2524, -0.0591],
          [ 1.2908,  0.5640]],

         [[ 0.8303, -2.1681],
          [ 2.7166, -0.1668]]]])
tensor([[[[ 0.4771, -0.4833],
          [-1.2538, -1.2736]],

         [[-0.0579,  0.6896],
          [-0.6383,  0.0581]]],


        [[[-0.2421,  0.0230],
          [ 1.8749,  0.8778]],

         [[ 0.3859, -1.8817],
          [ 1.8125, -0.3682]]]])

BatchNorm2d 函数在 PyTorch 中用于实现二维批量归一化,通常是在卷积神经网络(Convolutional Neural Network, CNN)中使用。

具体使用方法如下:

  • 1.实例化 BatchNorm2d 层:首先在代码中实例化 BatchNorm2d 层,如 m = nn.BatchNorm2d(2, eps=0, affine=False)。其中 2 为输入通道数。

  • 2.在模型中使用:将 BatchNorm2d 层加入到模型中,如:

import torch.nn as nn

class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.conv = nn.Conv2d(3, 2, 3, stride=1, padding=1)
        self.bn = nn.BatchNorm2d(2, eps=0, affine=False)
        
    def forward(self, x):
        x = self.conv(x)
        x = self.bn(x)
        return x
  • 3.训练模型:使用数据进行模型训练。

  • 4.推理:使用训练好的模型进行推理(预测)。

在使用 BatchNorm2d 层的过程中,需要注意的是:

  • BatchNorm2d 层的输入通道数需要与你的模型输入的通道数相匹配。

  • 如果设置了 affine=True,那么模型将自动学习参数权重和偏差,否则不学习。

BatchNorm2d的计算公式:

y = x − E [ x ] Var ⁡ [ x ] + ϵ ∗ γ + β y=\frac{x-\mathrm{E}[x]}{\sqrt{\operatorname{Var}[x]+\epsilon}} * \gamma+\beta y=Var[x]+ϵ xE[x]γ+β

BatchNorm2d 计算的过程包括如下步骤:

  • 1.计算均值:对每一个批量中的每一通道数据计算其均值。

  • 2.计算方差:对每一个批量中的每一通道数据计算其方差。

  • 3.归一化:对每一个批量中的每一通道数据使用如下公式归一化:

x_norm = (x - mean) / sqrt(var + eps)

其中 mean 为每一个通道的均值,var 为每一个通道的方差,eps 为防止除以 0 的小常数。

  • 4.拉伸和平移(可选):如果设置了 affine=True,那么模型会学习两个参数,一个是拉伸参数 gamma,一个是平移参数 beta,归一化数据通过如下公式拉伸和平移:
x_norm = gamma * x_norm + beta

完成以上步骤后,BatchNorm2d 就会对每一个批量的数据进行归一化处理。

  • pytorch的全连接写法
# 创建一个简单的神经网络,它包含一个线性层(nn.Linear(3, 2)),
# 用于预测给定3个输入值时的2个输出值。
# 神经网络是使用nn.Sequential容器构建的,该容器将多个模块合并为一个。
#
# 然后,代码将线性层的权重和偏差设置为不需要进行梯度优化(requires_grad_设置为False),
# 并将其填充为0.1。最后,代码创建一个Numpy数组并将其转换为PyTorch张量,
# 然后将其作为输入传递给神经网络,并输出结果。

import torch
import torch.nn as nn
from torchvision import transforms
import  numpy  as np
import cv2

li = nn.Linear(3, 2)
net = nn.Sequential(li)
li.weight.requires_grad_(False)
li.bias.requires_grad_(False)
li.weight.fill_(0.1)
li.bias.fill_(0.1)
#li.weight[0][0] = 0.5
#li.weight[0][1] = 0.5
#li.bias[0] = 1

data = np.array([20, 20, 10], dtype=np.float32)
data1 = torch.tensor(data)
out = net(data1)
print(out)
print([20*0.1 + 20*0.1 + 10*0.1 + 0.1, 20*0.1 + 20*0.1 + 10*0.1 + 0.1])

for idx, m in enumerate(net.modules()):
   print(m)
for param in net.parameters():
   print(param)
tensor([5.1000, 5.1000])
[5.1, 5.1]
Sequential(
  (0): Linear(in_features=3, out_features=2, bias=True)
)
Linear(in_features=3, out_features=2, bias=True)
Parameter containing:
tensor([[0.1000, 0.1000, 0.1000],
        [0.1000, 0.1000, 0.1000]])
Parameter containing:
tensor([0.1000, 0.1000])
  • pytorch交叉熵损失函数
import torch
import torch.nn as nn
# import numpy_tes as np

data = torch.tensor([1.0, -1.0, -1.0]).unsqueeze(0)
y = torch.tensor([2])
w=torch.Tensor([1.0, 2.0, 3.0])
loss_func = nn.CrossEntropyLoss(weight=w)
loss = loss_func(data, y)
print(loss)

在这里插入图片描述

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值