龙良曲PyTorch入门到实战 深度学习

文章目录

  • 笔记
    • 激活函数与Loss的梯度
    • lesson5 手写数字识别问题
    • lesson6 基本数据类型
    • lesson7 创建tensor
    • lesson8 索引和切片
    • lesson9 维度变换
    • lesson10 broadcasting
    • lesson11 分割和合并
    • lesson12 数学运算
    • lesson13 Tensor统计
    • lesson14 Tensor高阶
    • lesson16 什么是梯度
    • lesson17 常见函数的梯度
    • lesson18 激活函数与Loss的梯度
    • lesson19 感知机的梯度推导
      • 单一输出感知机
      • 多输出感知机
    • MLP反向传播推导过程
    • lesson22 优化小实例
      • 2D函数优化实例
    • lesson24 logistic regression
    • lesson25 交叉熵
    • lesson26 LR多分类问题实战
    • lesson28 激活函数与GPU加速
    • lesson29 MNIST
    • lesson30 Visdom可视化
    • lesson32 Train-Val-Test-交叉验证
    • lesson32 正则化
    • lesson34 动量和学习率衰减
      • 学习率
    • lesson35 early-stopping & dropout
      • Stochastic Gradient Descent
    • lesson38 卷积神经网络
    • Batch Normalization
    • nn.Moudle
    • 数据增强
    • 经典神经网络
    • RNN
    • LSTM
    • 如何理解Embeding
    • KL散度

笔记

  • 分类Classification适用于离散的数据,回归Regression适用于连续的数据
  • 一个epoch是对一个数据集迭代一次,一个step是对一个batch迭代一次
  • 类型判断:
a = torch.tensor(2.2)
# 判断类型的两种方法:
# 1
a.type()
type(a)		# 这是调用的python自带的方法,返回 torch.Tensor
# 2
isinstance(a, torch.FloatTensor)	# 判断a的类型是否为torch.FloatTensor
  • 一个标量的维度只有0维。表示它是一个标量。
  • 一维向量在数学中叫vector向量,在pytorch中叫tensor张量

深度学习中norm表示什么意思

在深度学习中,"norm"通常表示范数(norm)的概念。范数是一种衡量向量或矩阵大小的方法,它可以用来度量向量的长度或矩阵的大小。
在深度学习中,常见的范数有以下几种:
L1范数(L1 Norm):也称为曼哈顿范数(Manhattan Norm),它计算向量中各个元素绝对值之和。对于向量x=(x₁, x₂, …, xn),L1范数定义为||x||₁ = |x₁| + |x₂| + … + |xn|。
L2范数(L2 Norm):也称为欧几里德范数(Euclidean Norm),它计算向量各个元素平方和的平方根。对于向量x=(x₁, x₂, …, xn),L2范数定义为||x||₂ = √(x₁² + x₂² + … + xn²)。
无穷范数(Infinity Norm):它计算向量中各个元素绝对值的最大值。对于向量x=(x₁, x₂, …, xn),无穷范数定义为||x||∞ = max(|x₁|, |x₂|, …, |xn|)。
这些范数在深度学习中经常用于正则化、损失函数的定义、优化算法等方面。例如,L1范数正则化可以用于稀疏性推断,L2范数正则化可以用于权重衰减(weight decay),无穷范数可以用于约束梯度的大小。
在深度学习中,范数的概念还可以扩展到矩阵或张量上,用于度量它们的大小或复杂度。例如,矩阵的Frobenius范数用于度量矩阵的大小,核范数(Nuclear Norm)用于度量矩阵的低秩性质。

使用 iter() 函数可以将可迭代对象转换为迭代器。例如:

my_list = [1, 2, 3, 4, 5]
my_iter = iter(my_list)

print(next(my_iter))  # 输出:1
print(next(my_iter))  # 输出:2
print(next(my_iter))  # 输出:3

enumerate()函数
enumerate返回索引值和对应的元素

fruits = ['apple', 'banana', 'orange']

for index, fruit in enumerate(fruits):
    print(index, fruit)
"""
0 apple
1 banana
2 orange
"""

如何用pytorch表示String

1. one-hot编码:
one-hot编码是一种常用的数据编码方式,它将离散的类别型特征转化为一组二进制向量,用于机器学习等任务中。
eg,如果有男,女,中性,则分别用[1, 0, 0], [0, 1, 0], [0, 0, 1]表示。这样表示称为one-hot编码
2. Embedding

  • Word2vec
  • glove
# 随机正态分布
torch.randn()
# 随机均匀分布,[0, 1]
 

Resnet:最大的特点使用了残差连接。

optimizer.zero_grad()  :参数梯度的清零
loss.backward()			:反向传播,计算梯度
        optimizer.step(): 根据梯度更新模型参数
这三行代码分别代表什么意思

在这里插入图片描述


上面是基础


激活函数与Loss的梯度

为什么要计算梯度w.requires_grad_(requires_grad=True), 有什么用?
梯度是一个向量,它指示了函数在给定点的变化率最大的方向。通过计算梯度,可以实现反向传播(Backpropagation),参数优化,特征选择等。

p[1].backward(retain_graph=True)
计算p[1]对张量a的梯度,并将该梯度存在a.grad中

mse = F.mse_loss(torch.ones(1), x*w)
F.mse_loss() 函数的输入参数是两个张量,分别表示预测值和目标值。它将计算这两个张量之间的均方误差,并返回一个标量张量作为结果。

torch.autograd.grad(mse, [w])
torch.autograd.grad() 函数用于计算给定标量张量 mse 相对于指定参数张量 w 的梯度。
retain_graph=True 表示保留中间的计算图,以便在第二调用backward时不会引发错误

import torch
from torch.nn import functional as F

# autograd.grad    自动求导
x = torch.ones(1)
print(x)
w = torch.full([1], 2)      # 创建了一个包含一个元素且值为2的PyTorch Tensor
print(w)
w = w.type(torch.float32)
w.requires_grad_(requires_grad=True)    # w初始化时设置需要求导信息
mse = F.mse_loss(torch.ones(1), x*w)
# torch.autograd.grad(y,w) 表示y对w求导。
torch.autograd.grad(mse, [w], retain_graph=True)    # retain_graph=True 表示保留中间的计算图,以便在第二调用backward时不会引发错误
# mse = F.mse_loss(torch.ones(1), x*w)
print(torch.autograd.grad(mse, [w]))


# F.softmax    放缩到0-1且和为1
a = torch.rand(3)   # 生成3个0-1的随机数
print(a)
a.requires_grad_()
p = F.softmax(a, dim=0)         # 将给定的数据转化为0-1范围内,且和为1
print(p)
p[1].backward(retain_graph=True)        # 计算p[1]对张量a的梯度,并将该梯度存在a.grad中
print(p[1])
p1 = torch.autograd.grad(p[1], [a], retain_graph=True)      # 计算p1对张量a的梯度,返回梯度值
print(p1)
print(a.grad)
p[2].backward(retain_graph=True)
print(p[2])
p2 = torch.autograd.grad(p[2], [a], retain_graph=True)      # 计算p2对张量a的梯度,返回梯度值
print(p2)
print(a.grad)


"""
tensor([1.])
tensor([2])
(tensor([2.]),)
tensor([0.9741, 0.7026, 0.0407])
tensor([0.4639, 0.3536, 0.1824], grad_fn=<SoftmaxBackward0>)
tensor(0.3536, grad_fn=<SelectBackward0>)
(tensor([-0.1641,  0.2286, -0.0645]),)
tensor([-0.1641,  0.2286, -0.0645])
tensor(0.1824, grad_fn=<SelectBackward0>)
(tensor([-0.0846, -0.0645,  0.1491]),)
tensor([-0.2487,  0.1641,  0.0846])
"""

lesson5 手写数字识别问题

# mnist_train.py
import  torch
from    torch import nn
from    torch.nn import functional as F     # 常用函数
from    torch import optim      # 优化数据包

import torchvision
from matplotlib import pyplot as plt

from utils import plot_image, plot_curve, one_hot   # image是图片,curve是曲线


batch_size = 512  # 一次可以处理的图片数

# step1. load dataset    非重点
train_loader = torch.utils.data.DataLoader(
    torchvision.datasets.MNIST('mnist_data', train=True, download=True,     # train=True表示采用的训练集
                               transform=torchvision.transforms.Compose([
                                   torchvision.transforms.ToTensor(),
                                   torchvision.transforms.Normalize(
                                       (0.1307,), (0.3081,))
                               ])),
    batch_size=batch_size, shuffle=True)

test_loader = torch.utils.data.DataLoader(
    torchvision.datasets.MNIST('mnist_data/', train=False, download=True,   # train=False表示采用的测试集
                               transform=torchvision.transforms.Compose([
                                   torchvision.transforms.ToTensor(),       # 下载下的为numpy格式,转为tensor格式
                                   torchvision.transforms.Normalize(        # 使数据从0-1之间转为0附近均匀分布,使性能更好
                                       (0.1307,), (0.3081,))
                               ])),
    batch_size=batch_size, shuffle=False)

x, y = next(iter(train_loader))
print(x.shape, y.shape, x.min(), x.max())
plot_image(x, y, 'image sample')



# 创建网络
class Net(nn.Module):

    def __init__(self):
        super(Net, self).__init__()

        # xw+b
        self.fc1 = nn.Linear(28*28, 256)    # 线性层 256是随机决定的 28*28是图片尺寸
        self.fc2 = nn.Linear(256, 64)       # 256是fc2的输入,应为fc1的输出。
        self.fc3 = nn.Linear(64, 10)        # 64是fc3的输入,应为fc2的输出。10是0-9十个数字。

    def forward(self, x):
        # x: [b, 1, 28, 28]
        # h1 = relu(xw1+b1)
        x = F.relu(self.fc1(x))
        # h2 = relu(h1w2+b2)
        x = F.relu(self.fc2(x))
        # h3 = h2w3+b3
        x = self.fc3(x)
        return x



net = Net()
# [w1, b1, w2, b2, w3, b3]
optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.9)


train_loss = []

for epoch in range(3):      # 对整个数据集迭代3次

    for batch_idx, (x, y) in enumerate(train_loader):   # 对一个batch迭代一次

        # x: [batch_size, 1, 28, 28], y: [batch_size]    x是图像输入,y是输出结果0-9
        # [batch_size, 1, 28, 28] => [batch_size, 784]
        x = x.view(x.size(0), 28*28)
        # => [b, 10]
        out = net(x)       # net是个全连接层,只能接受dimension=2的输入,即[b, feature]的特征(b=batch_size)。因此要view成新的shape。
        # [b, 10]
        y_onehot = one_hot(y)
        # loss = mse(out, y_onehot)
        loss = F.mse_loss(out, y_onehot)

        optimizer.zero_grad()
        loss.backward()
        # w' = w - lr*grad
        optimizer.step()		# 更新参数信息

        train_loss.append(loss.item())

        if batch_idx % 10==0:
            print(epoch, batch_idx, loss.item())

plot_curve(train_loss)
# we get optimal [w1, b1, w2, b2, w3, b3]


total_correct = 0
for x,y in test_loader:
    x  = x.view(x.size(0), 28*28)
    out = net(x)
    # out: [b, 10] => pred: [b]
    pred = out.argmax(dim=1)
    correct = pred.eq(y).sum().float().item()
    total_correct += correct

total_num = len(test_loader.dataset)
acc = total_correct / total_num
print('test acc:', acc)

x, y = next(iter(test_loader))
out = net(x.view(x.size(0), 28*28))
pred = out.argmax(dim=1)
plot_image(x, pred, 'test')


# utils.py
# 封装了一些函数
import  torch
from    matplotlib import pyplot as plt


def plot_curve(data):
    fig = plt.figure()
    plt.plot(range(len(data)), data, color='blue')
    plt.legend(['value'], loc='upper right')
    plt.xlabel('step')
    plt.ylabel('value')
    plt.show()



def plot_image(img, label, name):

    fig = plt.figure()
    for i in range(6):
        plt.subplot(2, 3, i + 1)
        plt.tight_layout()
        plt.imshow(img[i][0]*0.3081+0.1307, cmap='gray', interpolation='none')
        plt.title("{}: {}".format(name, label[i].item()))
        plt.xticks([])
        plt.yticks([])
    plt.show()



def one_hot(label, depth=10):
    # convert label to one-hot encoding
    out = torch.zeros(label.size(0), depth)
    idx = torch.LongTensor(label).view(-1, 1)
    out.scatter_(dim=1, index=idx, value=1)
    return out



lesson6 基本数据类型

# 判断数据类型方法
a.type()		//
type(a)			# python自带的
isinstance(a, torch.FloatTensor)	# 判断是否为某种类型的


# dimension为0的标量表示方法: (dimension为0的标量常用于表示loss)
a = torch.tensor(1.)	# tensor(1.)


# dimension为1的张量表示方法,常用于表示bias偏置
torch.tensor([1.1])		# tensor([1.1000])
torch.tensor([1.1, 2.2])	# tensor([1.1000, 2.2000])
# FloatTensor的参数为张量的长度,而内容为随机初始化的。
torch.FloatTensor(1)	# tensor([3.2239e-25])
torch.FloatTensor(2)	# tensor([3.2239e-25, 4.59e-41])

# 从numpy转为tensor
data = np.ones(2)	# array([1., 1.])
torch.from_numpy(data)	# tensor([1., 1.], dtype=torch.float64)

# dimension为2的张量常用于表示多张图片的时候。比如有100张图片,每张图片是28*28=784的,所以可以用[100, 784]表示多张图片 


# 求size,shape
a = torch.tensor(2.2)
a.shape		# torch.Size([])
len(a.shape)	# 0
a.size()		# torch.Size([])

# dimension为3适用于RNN,自然语言处理

# dimension为4适用于图片,卷积神经网络。
[b, c, h, w] => [图片数, 通道数, 高度, 宽度]

# 其他
a.numel()	#tensor占用的内存的数量
a.dim()		# 返回维度dimension

lesson7 创建tensor

import numpy as np
import torch

# import from numpy
a = np.array([2, 3.3])
a = torch.from_numpy(a)
print(a)
# 全1矩阵,[a, b]表示创建a行b列的矩阵
a = np.ones([2, 3])
a = torch.from_numpy(a)
print(a)


# torch.tensor 使用现成的数据, tensor.Tensor接收数据的shape维度
# import from list
a = torch.tensor([2., 3.2])     # a就是tensor类型的[2, 3.2]
print(a)
a = torch.Tensor(2, 3)      # 生成2行3列的数据
print(a)
# 如果出现torch.nan 或者torch.inf可能是没有初始化


# 随机初始化
a = torch.rand(3, 3)    # 生成一个3行3列的,均匀采样于[0, 1]之间的数
print(a)

# 生成相同shape的tensor
a = torch .rand_like(a)
print(a)
# int的随机初始化
a = torch.randint(1, 10, [3, 3])    # [1, 9] shape:(3,3)
print(a)


# 正态分布 N(0, 1) 作为bias的初始化
a = torch.randn(3, 3)   # 生成(3, 3)的,均值为0 方差为1的tensor
print(a)


# full: 全部赋值为1个元素
a = torch.full([2, 3], 7)   # 2*3, 用7来填充
print(a)
# [] 表示生成标量 用7来填充
a = torch.full([], 7)
print(a)    # tensor(7)
# [1] 表示生成dimension为1的tensor
a = torch.full([1], 7)
print(a)    # tensor([7])


# arange
a = torch.arange(0, 10)     # 生成0-9的数字,默认步长是1
print(a)
a = torch.arange(0, 10, 2)  # 步长是2
print(a)


# linespace /logspace
a = torch.linspace(0, 10, steps=4)  # 0,10分别表示第一个和最后一个元素   steps表示元素数量
print(a)
a = torch.linspace(0, 10, steps=11)
print(a)
a = torch.logspace(0, -1, steps=10)     # 这个是logspace, 0表示10的0次方,-1表示10的-1次方
print(a)                        # a的第一个数是1,最后一个数是0


# ones zeros eye
a = torch.ones(3, 3)    # 生成3*3的全1矩阵
a = torch.zeros(3, 3)   # 生成3*3的全0矩阵
a = torch.eye(3, 4)     # 生成主对角全1的矩阵


# randperm随机打散 重新排序  ★★
a = torch.randperm(10)  # 0-9之间的所有数随机打散

a = torch.rand(2, 3)
b = torch.rand(2, 2)
idx = torch.randperm(2)
print(idx)
print("a=\n", a)
a = a[idx]      # 将a的行按照idx重新排序 (整个行重新换)
print("new_a=\n",a)
print("b=\n", b)
b = b[idx]
print("new_b=\n", b)        # 将b的行按照idx重新排序

lesson8 索引和切片

import numpy
import torch


# index: dim 0 first
a = torch.rand(4, 3, 28, 30)
print(a[0].shape)       # torch.Size([3, 28, 30])
print(a[0, 0].shape)    # torch.Size([28, 30])
print(a[0, 0, 2, 4])    # 用下标索引元素值


# 隔行采样:
print(a[:, :, 0:28:2, 0:30:2].shape)    # torch.Size([4, 3, 14, 14])
# ::2 等价于start:end:2

# index_select
"""
a.index_select(idx, torch.arange(k))
将第idx个维度变为k
"""
print(a.index_select(0, torch.arange(2)).shape)
print(a.index_select(2, torch.arange(13)).shape)

lesson9 维度变换

import numpy as np
import torch


# view / reshape
# view能干的reshape都能干。reshape更强大
a = torch.rand(4, 1, 28, 28)
print(a.shape)      # torch.Size([4, 1, 28, 28])
b = a.view(4,  28*28)
print(b.shape)      # torch.Size([4, 784])
c = a.reshape(4*28, 28)
print(c.shape)


# squeeze / unsqueeze
# unsqueeze(idx) 将shape在idx维度多插上一维。
# 指定压缩第n位,如果它的维数为1,则压缩,反之不对该维度操作。
# unsqueeze(-1) 使shape从[2] => [2, 1], 再unsqueeze变成[2,1,1]  -1表示插到最后面
# unsqueeze(1)  使shape从[4,2] => [4, 1,2]
a = torch.tensor([1.2, 2.3])
print(a.unsqueeze(-1))      # shape变成[2,1]
"""
tensor([[1.2000],
        [2.3000]])
"""
print(a.unsqueeze(0))   # 变成[1, 2]    tensor([[1.2000, 2.3000]])
# 实在案例
b = torch.rand(32)      # b是在channel上的bias。
f = torch.rand(4, 32, 14, 14)
b = b.unsqueeze(0).unsqueeze(2).unsqueeze(3)
print(b.shape)      # torch.Size([1, 32, 1, 1])


# squeeze(n)用法
# 指定压缩第n位,如果它的维数为1,则压缩,反之不对该维度操作。
b = torch.Tensor(1, 32, 1, 1)
print(b.shape)
print(b.squeeze().shape)       # torch.Size([32])    b.squeeze表示默认将所有维度为1的全部squeeze
print(b.squeeze(0).shape)      # torch.Size([32, 1, 1])  将第0维挤压


# 维度扩展expand / repeat
# expand: boradcasting  不主动复制数据,推荐使用。
a = torch.rand(4, 32, 14, 14)
b = torch.Tensor(1, 32, 1, 1)
print(b.expand(4, 32, 14, 14).shape)    # torch.Size([4, 32, 14, 14])    expand从1到n可行,从n到m不太好

# repeat
# repeat: memory copied
# repeat的参数表示倍数,在原来的基础上乘
b = torch.Tensor(1, 32, 1, 1)
print(b.repeat(4, 32, 1, 1).shape)  # torch.Size([4, 1024, 1, 1])


# .t 转置
a = torch.randn(3, 4)   # 生成3行4列的矩阵
print(a.t().shape, a.t())   # torch.Size([4, 3])


# permute
# 按照参数的顺序交换维度。
b = torch.rand(4, 3, 28, 32)
print(b.permute(0, 2, 3, 1).shape)  # torch.Size([4, 28, 32, 3])

lesson10 broadcasting

在这里插入图片描述
关于是否可以用广播机制:
如果当前维度dim=1,则可直接expand到相同dim
如果没有dim,就插入一个dim,然后expand到相同dim
否则不能broadcasting:
在这里插入图片描述

lesson11 分割和合并

import numpy as np
import torch


# cat concat  要求除了拼接外的维度之外都不一样
a1 = torch.rand(4, 3, 32, 32)
a2 = torch.rand(5, 3, 32, 32)
print(torch.cat([a1, a2], dim=0).shape)     # torch.Size([9, 3, 32, 32])

a2 = torch.rand(4, 1, 32, 32)
print(torch.cat([a1, a2], dim=1).shape)      # torch.Size([4, 4, 32, 32])

a1 = torch.rand(4, 3, 16, 32)
a2 = torch.rand(4, 3, 20, 32)
print(torch.cat([a1, a2], dim=2).shape)     # torch.Size([4, 3, 36, 32])


# stack: create new dim 要求a和b的shape完全一样。
a1 = torch.rand(4, 3, 16, 32)
a2 = torch.rand(4, 3, 16, 32)
print(torch.stack([a1, a2], dim=2).shape)       # torch.Size([4, 3, 2, 16, 32]) 在dim=2处插一个维度

b = torch.randn(32, 8)
a = torch.randn(32, 8)
c = torch.stack([a, b], dim=0)
print(c.shape)          # torch.Size([2, 32, 8])


# split: by len
a = torch.rand([5, 6])
print(a)
aa, bb = torch.split(a, [2, 3], dim=0)  # 按行去split,本来是[5,6], split成[2,6]和[3,6]
print(aa.shape, bb.shape)               # torch.Size([2, 6]) torch.Size([3, 6])

lesson12 数学运算

import  numpy as np
import torch

a = torch.rand(3,4)
b = torch.rand(4)
torch.all(torch.eq(a-b, torch.sub(a,b)))
print(a + b)
print(torch.add(a, b))  # 等价于a+b

# 同理,torch.sub(a,b) 等价于a-b

# 矩阵的乘法
# matmul:
#   torch.mm  : 只适用于2d
#   torch.matmul
#   @
a = torch.full([2, 2], 3)
b = torch.ones(2, 2)
# 矩阵乘法的三种表示方法
torch.mm(a, b)      # 等价于
torch.matmul(a, b)  # 等价于
print(a@b)

a = torch.rand(4, 784)
x = torch.rand(4, 784)
w = torch.rand(512, 784)    # w:(channel.out, channel.in)
print(torch.matmul(x, w.t()).shape)     # torch.Size([4, 512])

# >>> a = torch.rand(4,3, 28, 64)
# >>> b = torch.rand(4,1,64,32)
# >>> torch.matmul(a,b).shape
# torch.Size([4, 3, 28, 32])

# 次方
# a.pow(k) : a的k次方
# a**k
# a.sqrt(): 开根号
# a.rsqrt(): 取倒数再开方


# e的几次方 & ln
a = torch.exp(torch.ones(2, 2))
print(torch.log(a))     # 对a的所有元素再取ln


# 近似值
a = torch.tensor(3.14)
a.floor()       # 取地板
a.ceil()        # 取天花板
a.trunc()       # 取整数
a.frac()        # 取小数


# clamp
# 将值限制在给定参数的范围内
# a.clamp(min, max) : 将a的值限定在min-max之间。a中的值小于min的变成min,大于max的变成max,介于二者之间的不变。
grad = torch.rand(2, 3) * 15

lesson13 Tensor统计

import torch

"""
tensor统计:
norm: 求范数
mean : 平均值   sum : 求和
prod : 连乘
max, min, argmin, argmax : 最大最小值,最大最小值的idx(默认先打平,再求第几个数)
kthvalue, topk : 第k大的数的位置及其值
"""

# 1范数表示 |x|求和。 2范数表示平方和再开根号。
a = torch.tensor([1,2,3,4,5,6,7,8], dtype=float)
b = a.view(2, 4)
c = a.view(2, 2, 2)
print(c)
print(c.norm(1, dim=0))     # 参数1表示1范数。 2表示2范数
print(c.norm(1, dim=1))
print(c.norm(1, dim=2))
print(c.norm(2, dim=0))
"""
c: tensor([[[1., 2.],
         [3., 4.]],
        [[5., 6.],
         [7., 8.]]], dtype=torch.float64)
         
c.norm(1, dim=0):
tensor([[ 6.,  8.],
        [10., 12.]], dtype=torch.float64)
        
c.norm(1, dim=1):
tensor([[ 4.,  6.],
        [12., 14.]], dtype=torch.float64)
        
c.norm(1, dim=2):
tensor([[ 3.,  7.],
        [11., 15.]], dtype=torch.float64)
"""

a = torch.randn(4, 10)
print(a.argmax())           #    tensor(28)
print(a.argmax(dim=1))      # tensor([1, 0, 8, 2])  每行10个数,求10个数中的最大值的idx,即按照dim=1求最大值


# dim, keepdim
a = torch.rand(4, 10)
b = a.max(dim=1)    # b[0]是value的max, b[1]是value对应的idx
c = a.max(dim=1, keepdim=True)
print(b[0].shape)   # torch.Size([4])
print(c[0].shape)   # torch.Size([4, 1]) 保持竖着的


a = torch.rand(4, 10)
print(a)
print(a.topk(3, dim=1))     # 共4行,返回每一行前3大的元素及下标
print(a.topk(3, dim=1, largest=False))      # largest=False表示求最小的。
print(a.kthvalue(8, dim=1))     # 默认是第8小的元素

"""
tensor([[0.7841, 0.5202, 0.5160, 0.4788, 0.6427, 0.1049, 0.5161, 0.3836, 0.1677, 0.4653],
        [0.4838, 0.4054, 0.4336, 0.1541, 0.4228, 0.4602, 0.5819, 0.3031, 0.0749, 0.7695],
        [0.2420, 0.7969, 0.7428, 0.4675, 0.3132, 0.7516, 0.6356, 0.4277, 0.7945, 0.1089],
        [0.0475, 0.6876, 0.4313, 0.2479, 0.8423, 0.2280, 0.3918, 0.2062, 0.9654, 0.9479]])
torch.return_types.topk(
values=tensor([[0.7841, 0.6427, 0.5202],
                [0.7695, 0.5819, 0.4838],
                [0.7969, 0.7945, 0.7516],
                [0.9654, 0.9479, 0.8423]]),
indices=tensor([[0, 4, 1],
        [9, 6, 0],
        [1, 8, 5],
        [8, 9, 4]]))
torch.return_types.topk(
values=tensor([[0.1049, 0.1677, 0.3836],
        [0.0749, 0.1541, 0.3031],
        [0.1089, 0.2420, 0.3132],
        [0.0475, 0.2062, 0.2280]]),
indices=tensor([[5, 8, 7],
        [8, 3, 7],
        [9, 0, 4],
        [0, 7, 5]]))

torch.return_types.kthvalue(
values=tensor([0.5202, 0.4838, 0.7516, 0.8423]),
indices=tensor([1, 0, 5, 4]))
"""


# torch.equal() 用的更多一些
# torch.eq(a,b)   返回相同类型的矩阵,相等的位置为1,不等的位置为0
# torch.equal(a,b) 返回True或False

lesson14 Tensor高阶

where
gather

import torch

# where
# torch.where(cond>0.5, a, b) 大于0.5选a,小于0.5选b的值
cond = torch.rand(2, 2)
print(cond)
a = torch.zeros(2, 2)
print(a)
b = torch.ones(2, 2)
print(b)
c = torch.where(cond>0.5, a, b)
print(c)
"""
#### where
tensor([[0.4118, 0.6295],
        [0.1647, 0.2860]])
tensor([[0., 0.],
        [0., 0.]])
tensor([[1., 1.],
        [1., 1.]])
c = torch.where(cond>0.5, a, b) 大于0.5选a,小于0.5选b的值
tensor([[1., 0.],
        [1., 1.]])

进程已结束,退出代码0
"""


# gather
prob = torch.randn(4, 10)
topk = prob.topk(dim=1, k=3)
print("idx=\n", topk)
idx = topk[1]       # 取到下标。 topk[1]表示
print("idx=\n", idx)
label = torch.arange(10) + 100
# 根据idx索引,在label张量中收集对应  位置的值。
res = torch.gather(label.expand(4, 10), dim=1, index=idx.long())    # idx.long()表示转为长整型
print("res=\n", res)
"""
idx=
 torch.return_types.topk(
values=tensor([[1.1974, 0.6872, 0.6593],
        [1.5346, 0.4412, 0.4348],
        [1.8746, 1.3127, 0.5541],
        [1.9470, 0.8821, 0.5151]]),
indices=tensor([[1, 3, 4],
        [9, 6, 5],
        [0, 9, 2],
        [9, 7, 8]]))
idx=
 tensor([[1, 3, 4],
        [9, 6, 5],
        [0, 9, 2],
        [9, 7, 8]])
res=
 tensor([[101, 103, 104],
        [109, 106, 105],
        [100, 109, 102],
        [109, 107, 108]])
"""

lesson16 什么是梯度

梯度的长度反应趋势
梯度的方向反应增长的方向。

在这里插入图片描述

哪些因素会影响搜索过程?

  • 初始状态
  • 学习率
  • 动量(如何逃离局部极小值):可以理解为惯性。

lesson17 常见函数的梯度

导数偏导数都是在一个方向上的求导。梯度是所有方向上的导数。
在这里插入图片描述

lesson18 激活函数与Loss的梯度

Sigmoid激活函数
在这里插入图片描述
对于Sigmoid函数,f' = f * (1-f)
当x趋于正无穷或负无穷时,其导数值变为0,梯度无法更新。

Tanh激活函数
适用于RNN
在这里插入图片描述

ReLU激活函数
在这里插入图片描述

** Gradient API **

求损失函数对参数的梯度信息
在这里插入图片描述

- torch.autograd.grad(loss, [w1, w2…])
-

(插入图片且居中)
- loss.backward()
w1 grad
w2 grad~

Softmax
让数据转化为概率,使用softmax可以将所有的数据转为0-1内且数据求和为1
还可以使大的更大 小的更小。
在这里插入图片描述
softmax 求导
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

import torch
from torch.nn import functional as F


# 常见激活函数
a = torch.randn(10)
print(a)
print(torch.sigmoid(a))
print(torch.tanh(a))
print(torch.relu(a))


# autograd.grad    自动求导
x = torch.ones(1)
print(x)
w = torch.full([1], 2,)      # 创建了一个包含一个元素且值为2的PyTorch Tensor
print(w)
w = w.type(torch.float32)    # 更改w的类型
w.requires_grad_(requires_grad=True)    # w初始化时设置需要求导信息
mse = F.mse_loss(torch.ones(1), x*w)    # 求平均绝对误差。 torch.ones()是真实值,x*w是预测值
# torch.autograd.grad(y,[w]) 表示y对w求导。
torch.autograd.grad(mse, [w], retain_graph=True)    # retain_graph=True 表示保留中间的计算图,以便在第二调用backward时不会引发错误
print(torch.autograd.grad(mse, [w]))


# loss.backward    ?
x = torch.ones(1)
w = torch.full([1], 2)
w = w.type(torch.float32)      # 下一行的需要梯度信息需要浮点类型数据才能有梯度信息,所以将w改为浮点类型。
w.requires_grad_()
mse = F.mse_loss(torch.ones(1), x*w)
print(mse)
mse.backward()      # 对loss向后传播,把梯度信息存在.grad中。每个参数的梯度信息存储在.grad中
print(w.grad)


# softmax 求导
# F.softmax    放缩到0-1且和为10
a = torch.rand(3)   # 生成3个0-1的随机数
print(a)
a.requires_grad_()
p = F.softmax(a, dim=0)         # 将给定的数据转化为0-1范围内,且和为1
print(p)
p[1].backward(retain_graph=True)        # 计算p[1]对张量a的梯度,并将该梯度存在a.grad中
print(p[1])
p1 = torch.autograd.grad(p[1], [a], retain_graph=True)      # 计算p[1]对张量a的梯度,返回梯度值
print(p1)           # (tensor([-0.1025,  0.2275, -0.1249]),)     只有p[1]的下标为正
print(a.grad)       # tensor([-0.1025,  0.2275, -0.1249])
p[2].backward(retain_graph=True)
print(p[2])         # tensor(0.3571, grad_fn=<SelectBackward0>)
p2 = torch.autograd.grad(p[2], [a], retain_graph=True)      # 计算p2对张量a的梯度,返回梯度值    只有p[2]的下标为正
print(p2)           # (tensor([-0.1046, -0.1249,  0.2296]),)
print(a.grad)       # tensor([-0.2072,  0.1025,  0.1046])  这里的梯度累加了p[1]的和p[2]的梯度

lesson19 感知机的梯度推导

单一输出感知机

在这里插入图片描述
上标1表示第1层
下标i表示上一层结点是为i,j表示当前层的结点是j

在这里插入图片描述
O应该表示输出预测值,t表示true真实值。
在这里插入图片描述

多输出感知机

P 42
在这里插入图片描述

import torch
from torch.nn import functional as F

# 单一输出感知机推导
x = torch.randn(1, 10)
w = torch.randn(1, 10, requires_grad=True)      # 设置w需要保存梯度信息
o = torch.sigmoid(x@w.t())  # 得到1*1的输出结果
print(o.shape)              # torch.Size([1, 1])
loss = F.mse_loss(torch.ones(1, 1), o)      # 计算平均绝对误差。 真实值是(1, 1),预测值是o
print(loss.shape)               # loss是个标量,所以shape是torch.Size([])
loss.backward()                 # 计算损失函数对参数的梯度信息
print(w.grad)                   # 输出损失函数对w的梯度。w是[1, 10]的tensor,所以w的梯度信息也是[1, 10]的。


# 多输出感知机
x = torch.randn(1, 10)
w = torch.randn(2, 10, requires_grad=True)
o = torch.sigmoid(x@w.t())      # 得到[1, 2]的输出
print(o.shape)
loss = F.mse_loss(torch.ones(1, 2), o)
print(loss.shape)
loss.backward()             # 可以得到损失函数对所有需要梯度信息的参数的梯度信息
print(w.grad)

MLP反向传播推导过程

这是在求每个参数的反向传播的误差来更新参数。
在这里插入图片描述

在这里插入图片描述

lesson22 优化小实例

2D函数优化实例

view_init() 用于设置三维坐标轴的视角	
x.tolist() 将numpy转为list列表    pred.item返回值而不是tensor
tensor.item() 返回一维张量的数值而非tensor类型。
eg: a = torch.tensor(1.234)    a.item()是个数值。a是张量。
# 2D函数优化实例
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import pyplot as plt
import torch


def himmelblau(x):
    # f = (x^2 + y - 11)^2 + (x + y^2 - 7)^2
    return (x[0] ** 2 + x[1] - 11) ** 2 + (x[0] + x[1] ** 2  - 7) ** 2      # x[0]是x,x[1]是y


# Plot
x = np.arange(-6, 6, 0.1)
y = np.arange(-6, 6, 0.1)
print("x,y range:", x.shape, y.shape)
X, Y = np.meshgrid(x, y)
Z = himmelblau([X, Y])

fig = plt.figure('himmelblau')
ax = fig.add_subplot(projection='3d')
ax.plot_surface(X, Y, Z)
ax.view_init(60, -30)       # view_init() 用于设置三维坐标轴的视角
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.show()


# 梯度下降法求
x = torch.tensor([-4., 0.], requires_grad=True)
optimizer = torch.optim.Adam([x], lr=1e-3)      # Adam优化器,学习率1e-3
for step in range(20000):
    pred = himmelblau(x)
    optimizer.zero_grad()       # 梯度清零
    pred.backward()             # 生成x[0], x[1]的梯度信息
    optimizer.step()            # 更新参数信息
    if step % 2000 == 0:
        print(f"step={step}, x = {x.tolist()}, f(x) = {pred.item()} ")     # x.tolist() 将numpy转为list列表    pred.item返回值而不是tensor

lesson24 logistic regression

逻辑回归,之前的叫法。现在是叫classification.
逻辑回归和分类的区别在于逻辑回归不能直接用accuracy当作Error。
如果使用MSE,做真实值和预测值之间的差使二者之间的值越来越小,则解读为regression问题
如果使用Cross Entropy, 则解读为classification。

lesson25 交叉熵

是用于衡量两个之间间隔的Loss。间隔的越小,交叉熵越小。间隔的越大,交叉熵越大。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

# practise
import torch
from torch.nn import functional as F


# Cross Entropy = softmax + log + nll_loss
x = torch.randn(1, 784)
w = torch.randn(10, 784)
logits = x@w.t()

pred = F.softmax(logits, dim=1)
pred_log = torch.log(pred)

print(F.cross_entropy(logits, torch.tensor([3])))

print(F.nll_loss(pred_log, torch.tensor([3])))  # 之前的softmax和log都做了,所以只需要nll_loss即可得到与上面一样的结果

lesson26 LR多分类问题实战

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms


batch_size = 200
learning_rate = 0.01
epochs = 10


# 加载数据集
train_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=True, download=True,
                   transform=transforms.Compose([
                       transforms.ToTensor(),
                       transforms.Normalize((0.1307,), (0.3081,))
                   ])),
    batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=False, transform=transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.1307,), (0.3081,))
    ])),
    batch_size=batch_size, shuffle=True)


# 参数信息
                    # 784是输入,200是输出 前后相反
w1, b1 = torch.randn(200, 784, requires_grad=True),\
         torch.zeros(200, requires_grad=True)
w2, b2 = torch.randn(200, 200, requires_grad=True),\
    torch.zeros(200, requires_grad=True)
w3, b3 = torch.randn(10, 200, requires_grad=True),\
    torch.zeros(10, requires_grad=True)

torch.nn.init.kaiming_normal_(w1)           # 用于对张量进行Kaiming正态分布初始化
torch.nn.init.kaiming_normal_(w2)
torch.nn.init.kaiming_normal_(w3)


# 向前传播
def forward(x):
    x = x@w1.t() + b1
    x = F.relu(x)
    x = x@w2.t() + b2
    x = F.relu(x)
    x = x@w3.t() + b3
    x = F.relu(x)
    return x


optimizer = optim.SGD([w1, b1, w2, b2, w3, b3], lr=learning_rate)       # SGD: 随机梯度下降
criteon = nn.CrossEntropyLoss()         # 交叉熵做loss

for eopch in range(epochs):

    for batch_idx, (data, target) in enumerate(train_loader):
        data = data.view(-1, 28*28)
        logits = forward(data)      # 模型得到的预测值logits
        loss = criteon(logits, target)     # 真实值target和预测值logits之间的交叉熵损失函数
        optimizer.zero_grad()       # 清零梯度  每次计算前都要清零梯度,不让梯度累计
        loss.backward()             # 计算交叉熵损失函数对参数的梯度信息 (参数有w1 b1 w2 b2 w3 b3)
        optimizer.step()            # 更新参数梯度信息

        if batch_idx % 100 == 0:
            print("Train Epoch:{} [{}/{} ({:.0f}%)]\tLoss:{:.6f}".format(
                eopch, batch_idx*len(data), len(train_loader.dataset),
                100. * batch_idx / len(train_loader), loss.item()))
    test_loss = 0
    correct = 0
    for data, target in test_loader:
        data = data.view(-1, 28*28)
        logits = forward(data)      # # 模型得到的预测值logits
        test_loss += criteon(logits, target).item()     # 测试误差累加交叉熵损失函数值
        pred = logits.data.max(1)[1]    # logits.data 是获取 logits 张量的数据部分,即去除梯度信息,得到一个新的张量。
                                        # .max(1) 是对 logits.data 进行操作,这个操作会返回两个值:最大值和最大值所在的索引。[1] 表示选择返回最大值所在的索引。
        correct += pred.eq(target.data).sum()   # 判断pred和target.data是否相等(eq),将相等的求和得到预测正确的数量。

    test_loss /= len(test_loader.dataset)
    print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
        test_loss, correct, len(test_loader.dataset),
        100. * correct / len(test_loader.dataset)))

lesson28 激活函数与GPU加速

# 使用GPU的code
import  torch
import  torch.nn as nn
import  torch.nn.functional as F
import  torch.optim as optim
from    torchvision import datasets, transforms


batch_size=200
learning_rate=0.01
epochs=10

train_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=True, download=True,
                   transform=transforms.Compose([
                       transforms.ToTensor(),
                       transforms.Normalize((0.1307,), (0.3081,))
                   ])),
    batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=False, transform=transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.1307,), (0.3081,))
    ])),
    batch_size=batch_size, shuffle=True)






class MLP(nn.Module):

    def __init__(self):
        super(MLP, self).__init__()

        self.model = nn.Sequential(
            nn.Linear(784, 200),
            nn.LeakyReLU(inplace=True),
            nn.Linear(200, 200),
            nn.LeakyReLU(inplace=True),
            nn.Linear(200, 10),
            nn.LeakyReLU(inplace=True),
        )

    def forward(self, x):
        x = self.model(x)

        return x

device = torch.device('cuda:0')
net = MLP().to(device)
optimizer = optim.SGD(net.parameters(), lr=learning_rate)
criteon = nn.CrossEntropyLoss().to(device)

for epoch in range(epochs):

    for batch_idx, (data, target) in enumerate(train_loader):
        data = data.view(-1, 28*28)
        data, target = data.to(device), target.cuda()

        logits = net(data)
        loss = criteon(logits, target)

        optimizer.zero_grad()
        loss.backward()
        # print(w1.grad.norm(), w2.grad.norm())
        optimizer.step()

        if batch_idx % 100 == 0:
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                epoch, batch_idx * len(data), len(train_loader.dataset),
                       100. * batch_idx / len(train_loader), loss.item()))


    test_loss = 0
    correct = 0
    for data, target in test_loader:
        data = data.view(-1, 28 * 28)
        data, target = data.to(device), target.cuda()
        logits = net(data)
        test_loss += criteon(logits, target).item()
		"""
            logits是模型的输出,通常是一个包含每个类别的得分张量,通常是[batch_size, num_classes], 分别表示批量大小、类别数量
            logits.data是去除梯度信息只保留张量的数值数据。
            .max(1)用于在张量的指定维度上找到最大值。多分类问题的得分分布在第二个维度上。 为什么找最大值? 找最大值是每个预测结果都有个值,取最可能的就是取得分值最大的。
            [1]用于获取最大值的索引,即得分最高的类别的索引。
        """
        pred = logits.data.max(1)[1]
        correct += pred.eq(target.data).sum()

    test_loss /= len(test_loader.dataset)
    print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
        test_loss, correct, len(test_loader.dataset),
        100. * correct / len(test_loader.dataset)))

lesson29 MNIST

import torch
import torch.nn.functional as F


# 计算Accuracy的流程
logits = torch.rand(4, 10)
print(logits)
pred = F.softmax(logits, dim=1)
pred_label = pred.argmax(dim=1)
print(pred_label)
print(logits.argmax(dim=1))
label = torch.tensor([9, 3, 2, 4])      # 真实值
correct = torch.eq(pred_label, label)   # 这是一个类型为byte的tensor
print("Accuracy: {}".format(correct.sum().float().item() / 4))  # 先求和,再将byte转为float,再取值,再/4

# MNIST测试集
import  torch
import  torch.nn as nn
import  torch.nn.functional as F
import  torch.optim as optim
from    torchvision import datasets, transforms


batch_size=200
learning_rate=0.01
epochs=10

train_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=True, download=True,
                   transform=transforms.Compose([
                       transforms.ToTensor(),
                       transforms.Normalize((0.1307,), (0.3081,))
                   ])),
    batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=False, transform=transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.1307,), (0.3081,))
    ])),
    batch_size=batch_size, shuffle=True)



class MLP(nn.Module):

    def __init__(self):
        super(MLP, self).__init__()

        self.model = nn.Sequential(
            nn.Linear(784, 200),
            nn.LeakyReLU(inplace=True),
            nn.Linear(200, 200),
            nn.LeakyReLU(inplace=True),
            nn.Linear(200, 10),
            nn.LeakyReLU(inplace=True),
        )

    def forward(self, x):
        x = self.model(x)

        return x


device = torch.device('cuda:0')
net = MLP().to(device)
optimizer = optim.SGD(net.parameters(), lr=learning_rate)
criteon = nn.CrossEntropyLoss().to(device)

for epoch in range(epochs):

    for batch_idx, (data, target) in enumerate(train_loader):
        data = data.view(-1, 28*28)
        data, target = data.to(device), target.cuda()

        logits = net(data)
        loss = criteon(logits, target)

        optimizer.zero_grad()
        loss.backward()
        # print(w1.grad.norm(), w2.grad.norm())
        optimizer.step()

        if batch_idx % 100 == 0:
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                epoch, batch_idx * len(data), len(train_loader.dataset),
                       100. * batch_idx / len(train_loader), loss.item()))


    test_loss = 0
    correct = 0
    for data, target in test_loader:
        data = data.view(-1, 28 * 28)
        data, target = data.to(device), target.cuda()
        logits = net(data)
        test_loss += criteon(logits, target).item()

        pred = logits.argmax(dim=1)
        correct += pred.eq(target).float().sum().item()

    test_loss /= len(test_loader.dataset)
    print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
        test_loss, correct, len(test_loader.dataset),
        100. * correct / len(test_loader.dataset)))

lesson30 Visdom可视化

我真哭了 破代码!!!

import  torch
import  torch.nn as nn
import  torch.nn.functional as F
import  torch.optim as optim
from    torchvision import datasets, transforms
from visdom import Visdom

batch_size = 200
learning_rate = 0.01
epochs = 10


# 导入数据
train_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=True, download=True,
                   transform=transforms.Compose([
                       transforms.ToTensor(),
                       # transforms.Normalize((0.1307,), (0.3081,))
                   ])),
    batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=False, transform=transforms.Compose([
        transforms.ToTensor(),
        # transforms.Normalize((0.1307,), (0.3081,))
    ])),
    batch_size=batch_size, shuffle=True)

# print(len(train_loader))          # 返回的是批次数,即总样本数/batch_size
# print(len(train_loader.dataset))  # 返回总样本数


# 创建多层感知机模型
class MLP(nn.Module):
    def __init__(self):
        super(MLP, self).__init__()

        self.model = nn.Sequential(
            nn.Linear(784, 200),
            nn.LeakyReLU(inplace=True),     # inplace=True表示就地操作
            nn.Linear(200, 200),
            nn.LeakyReLU(inplace=True),
            nn.Linear(200, 10),
            nn.LeakyReLU(inplace=True),
        )

    # 重写了父类的方法
    def forward(self, x):
        x = self.model(x)
        return x


device = torch.device('cuda:0')     # 使用索引为0的设备
net = MLP().to(device)              # 将MLP导入device上计算。
optimizer = optim.SGD(net.parameters(), lr=learning_rate)
criteon = nn.CrossEntropyLoss().to(device)      # 将交叉熵Loss导入device上计算。

# 创建visdom可视化
"""
viz.line: 创建一个折线图窗口
[0.] 指定初始x y轴的数据点
win='train_loss':指定窗口名称为train_loss。
opts 用于指定折线图选项。这里设置了标题为train loss

"""
viz = Visdom()
viz.line([0.], [0.], win='train_loss', opts=dict(title='train loss'))
viz.line([[0.0, 0.0]], [0.], win='test', opts=dict(title='test loss&acc.',
                                                  legend=['loss', 'acc.']))
global_step = 0     # 步长


# 开始训练
for epoch in range(epochs):
    for batch_idx, (data, target) in enumerate(train_loader):
        data = data.view(-1, 28*28)
        data, target = data.to(device), target.cuda()           # 将图片数据和真实值挪到GPU(device)上进行运算

        logits = net(data)      # 预测值 结果
        loss = criteon(logits, target)      # 损失

        optimizer.zero_grad()       # 清零梯度
        loss.backward()              # 保留参数的梯度信息
        optimizer.step()            # 根据参数的梯度信息以更新参数
        global_step += 1
        # 画折线。 纵坐标是loss的值。横坐标是步长
        viz.line([loss.item()], [global_step], win='train_loss', update='append')       # 更新方式为在后面append

        # 输出
        if batch_idx % 100 == 0:
            print("Train Epoch:{} [{}/{} ({:.0f}%)]\tLoss:{:.6f}".format(
                epoch, batch_idx*len(data), len(train_loader.dataset),
                100. * batch_idx / len(train_loader), loss.item()))

    # 测试集上的数据
    test_loss = 0       # 测试集上的Loss
    correct = 0         # 预测正确的个数
    for data, target in test_loader:
        data = data.view(-1, 28*28)
        data, target = data.to(device), target.cuda()
        logits = net(data)
        test_loss += criteon(logits, target).item()         # 取item取值

        pred = logits.argmax(dim=1)         # 0-9每个都可能预测到。取概率最大的就是取得分最高的。得到其下标就是该值。dim=1表示求第一个维度。
        correct += pred.eq(target).float().sum().item()

    viz.line([[test_loss, correct / len(test_loader.dataset)]],
             [global_step], win='test', update='append')
    viz.images(data.view(-1, 1, 28, 28), win='x')  # images是可视化函数 用于显示图像诗句
    # detach是将张量从计算图中分离出来。.cpu是转到cpu上。.numpy是转为numpy格式。
    viz.text(str(pred.detach().cpu().numpy()), win='pred',
             opts=dict(title='pred'))

    test_loss /= len(test_loader.dataset)
    print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
        test_loss, correct, len(test_loader.dataset),
        100. * correct / len(test_loader.dataset)))

lesson32 Train-Val-Test-交叉验证

在训练集上训练更新参数θ。在验证集上看哪个时间戳是最好的,在哪个时间戳结束。测试集是测试模型效果的好坏
验证集是在原来的训练集中划分出来的。

pred = logits.data.max(1)[1]    # max(1) 表示在第一个维度上找到最大值。[1]用于返回最大值的索引,[0]用于返回最大值的数值。

lesson32 正则化

在这里插入图片描述
在这里插入图片描述
正则化是强制让权重weights变为0或趋近于0,降低模型的复杂度。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

lesson34 动量和学习率衰减

动量理解为惯性。
没有动量,梯度变化很大,loss也变化的很大。
在这里插入图片描述
有动量,梯度变化会很小。
在这里插入图片描述
在这里插入图片描述

学习率

在这里插入图片描述
如果一段步骤内学习率没变,则设置学习率减半(ReduceLROnPlateau).
在这里插入图片描述
按照规定每走几步就让学习率变成多少。

lesson35 early-stopping & dropout

在这里插入图片描述
在这里插入图片描述

dropout

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

net_dropped.eval() 是 PyTorch 中用于将神经网络模型切换到评估模式的方法。在评估模式下,模型的行为会发生一些变化,通常用于在不训练模型的情况下进行推断或测试。

当你调用 net_dropped.eval() 时,它会做以下事情:

批归一化层(Batch Normalization):在训练模式下,批归一化层会根据每个批次的统计信息进行批次归一化。但在评估模式下,它会使用固定的统计信息,通常是在训练集上计算的统计信息。这确保了评估模式下的一致性,不受输入数据的影响。

Dropout:如果在模型中使用了 Dropout 层,评估模式下 Dropout 不会丢弃任何神经元的输出。这是因为在测试或推断时,你通常不需要进行随机丢弃。
tensorflow的参数是保留结点的概率,Torch是删掉结点的概率!

梯度计算:评估模式下,PyTorch 不会计算梯度,因为你通常不会在评估模式下进行反向传播(即不会进行训练)。

通常,在训练完模型后,你会调用 model.eval() 来确保在执行推断或测试时模型处于一致的状态。这有助于确保模型在不同模式下的一致性行为。如果你希望恢复到训练模式,可以调用 model.train()。


Stochastic Gradient Descent

Stochastic Gradient Descent 是在一个batch中对参数进行求导。一般都是在一整个数据集上对参数进行求导。
随机梯度下降(Stochastic Gradient Descent,简称 SGD) 是机器学习和深度学习中最常用的优化算法之一,用于训练模型的权重以最小化损失函数。与传统的梯度下降算法不同,SGD 在每一步更新权重时都使用一小部分训练数据,而不是整个数据集。这使得它特别适用于大规模数据集和深度神经网络。

以下是 SGD 的主要特点和工作原理:

随机性:SGD 是随机的,因为它每次迭代都从训练数据中随机选择一小批样本来计算梯度。这种随机性有助于避免陷入局部极小值,并且使算法能够在训练过程中跳出局部最优解。

计算效率:由于 SGD 仅使用一小批数据进行梯度计算,因此它通常比使用整个数据集的批量梯度下降更快。这对于大规模数据集尤其重要。

学习率:SGD 使用一个称为学习率的超参数来控制每次权重更新的步长。较小的学习率会导致收敛较慢,但更稳定,而较大的学习率可能导致不稳定的训练。

随机梯度计算:在每次迭代中,SGD 计算损失函数相对于一小批数据的梯度,并使用该梯度来更新模型的权重。这个梯度计算是通过反向传播算法来完成的。

Mini-Batch:SGD 中的小批量数据通常被称为 mini-batch。mini-batch 的大小是一个重要的超参数,它影响到算法的性能和收敛速度。较小的 mini-batch 可能导致更多的随机性,但也会增加计算开销。

收敛性:SGD 不保证全局最优解,但通常能够收敛到一个合理的解决方案,特别是在使用适当的学习率调度策略时。

学习率调度:为了提高 SGD 的性能,可以使用学习率调度策略,即在训练过程中逐渐降低学习率的大小。

lesson38 卷积神经网络

在这里插入图片描述

在这里插入图片描述

import torch
from torch import nn    
layer = nn.Conv2d(1, 3, kernel_size=3, stride=1, padding=1) # 1表示通道数,3表示卷积核数量
x = torch.rand(1, 1, 28, 28)
out = layer.forward(x)       # 完成一次前向传播,即计算一次卷积结果
out = layer(x)       # 推荐使用这个方法 完成一次前向传播,同时做pytorch自带的一些工作。
print(out)

layer.weight		# 权重,需要梯度信息
layer.weight.shape	# 权重的shape

池化层和采样
在这里插入图片描述
采样
在这里插入图片描述

Batch Normalization

为什么要使用批量归一化?

使用浅层模型时,随着模型训练的进行,当每层中参数更新时,靠近输出层的输出较难出现剧烈变化。对深层神经网络来说,随着网络训练的进行,前一层参数的调整使得后一层输入数据的分布发生变化,各层在训练的过程中就需要不断的改变以适应学习这种新的数据分布。所以即使输入数据已做标准化,训练中模型参数的更新依然很容易导致后面层输入数据分布的变化,只要网络的前面几层发生微小的改变,那么后面几层就会被累积放大下去。最终造成靠近输出层输出的剧烈变化。这种计算数值的不稳定性通常令我们难以训练出有效的深度模型。如果训练过程中,训练数据的分布一直在发生变化,那么将不仅会增大训练的复杂度,影响网络的训练速度而且增加了过拟合的风险。

nn.Moudle

# 常用的flatten操作
class Flatten(nn.Module):
    def __init__(self):
        super(Flatten, self).__init__()

    def forward(self, input):
        return input.view(input.size(0), -1)
    

数据增强

train_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=True, download=True,
                   transform=transforms.Compose([
                       transforms.RandomHorizontalFlip(),       # 水平翻转
                       transforms.RandomVerticalFlip(),         # 垂直反转
                       transforms.RandomRotation(15),           # 旋转,-15°~ 15°
                       transforms.RandomRotation([90, 180, 270]),   # 旋转
                       transforms.Resize([32, 32]),             # 裁切,变成大小为32*32
                       transforms.RandomCrop([28, 28]),         # 裁剪部分
                       transforms.ToTensor(),                   # 转为tensor类型
                       # transforms.Normalize((0.1307,), (0.3081,))
                   ])),
    batch_size=batch_size, shuffle=True)

# 转到一个transform的list中,会对数据进行上面的操作。但是操作是随机的,并不一定会进行该操作。

经典神经网络

LeNet-5
AlexNet

RNN

RNN 跟传统神经网络最大的区别在于每次都会将前一次的输出结果,带到下一次的隐藏层中,一起训练。
在这里插入图片描述

在这里插入图片描述

LSTM

在这里插入图片描述

如何理解Embeding

KL散度

相对熵可以衡量两个随机分布之间的距离,当两个随机分布相同时,它们的相对熵为零,当两个随机分布的差别增大

KL divergence和JSdivergence区别
其中,KL是非对称的度量,JS是对称的,W是对称的。另外,我们假设两个分布的“差异”是变量x(x>0),那么:

x越大,KL越大,且大到一定程度的时候,例如不交叉时,恒无意义(或理解恒为无穷大)。
x越大,JS越大,且大到一定程度的时候,例如不交叉时,不变,恒为log2。
x越大,w越大。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/235645.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

初识Ceph --组件、存储类型、存储原理

目录 ceph组件存储类型块存储文件存储对象存储 存储过程 ceph Ceph&#xff08;分布式存储系统&#xff09;是一个开源的分布式存储系统&#xff0c;设计用于提供高性能、高可靠性和可扩展性的存储服务&#xff0c;可以避免单点故障&#xff0c;支持块存储、对象存储以及文件系…

Java项目-瑞吉外卖Day2

完善登录功能&#xff1a; 完善未登录不能访问/backend/index.html。使用拦截器或过滤器。 创建过滤器。 重写doFilter方法。 查看是否过滤成功。 处理流程如下&#xff1a; 添加员工功能&#xff1a; 点击保存&#xff0c;可以看到请求信息。 再看前端代码&a…

使用React 18、Echarts和MUI实现温度计

关键词 React 18 Echarts和MUI 前言 在本文中&#xff0c;我们将结合使用React 18、Echarts和MUI&#xff08;Material-UI&#xff09;库&#xff0c;展示如何实现一个交互性的温度计。我们将使用Echarts绘制温度计的外观&#xff0c;并使用MUI创建一个漂亮的用户界面。 本文…

MySQL - InnoDB 和 MyISAM 的索引实现的区别

InnoDB 和 MyISAM 底层都是 B 树的实现&#xff0c;但是二者却完全不同 。 主键索引文件存储不同 MyISAM 引擎的索引文件和数据文件是分离的&#xff0c;而 InnoDB 引擎的索引文件和数据文件是不分离的。 MyISAM 引擎的叶子节点存储的是数据文件的地址&#xff0c;而 InnoDB 的…

textarea文本框回车enter的时候自动提交表单,根据内容自动高度

切图网近期一个bootstrap5仿chatgpt页面的项目遇到的&#xff0c;textarea文本框回车enter的时候自动提交表单&#xff0c;根据内容自动高度&#xff0c;代码如下&#xff0c;亲测可用。 <textarea placeholder"Message ChatGPT…" name"" rows"&q…

Qt之Ui样式表不影响子类的配置

Qt之Ui样式表不影响子类的配置 问题 在ui界面上布局时&#xff0c;当对容器进行样试设计时&#xff0c;会对容器内其它成员对象也进行了修改 分析 对应*.ui文件内容 从这个写法来看&#xff0c;它的样式属性会影响其成员对象样式属性。 解决方法 在容器的样式表中写时适…

离散型随机变量的分布律(也称概率质量函数:probability mass function, PMF)

设是一个离散型随机变量&#xff0c;可能的取值为&#xff0c;取各个值的概率记为&#xff1a; &#xff08;1&#xff09; 其中 并且&#xff0c; 公式&#xff08;1&#xff09;就称为离散型随机变量的分布律&#xff0c;也称概率质量函数&#xff1a;probability ma…

前端怎么调用node接口---小白

1.基于node搭建express后端脚手架&#xff1a;基于node搭建express后端脚手架 2.在node里边写一个接口 // 引入express const express require(express) // 创建实例 const app express() // 创建监听端口 const port 3000 // 定义接口 app.get(/api/getData,(req,res) &g…

java 获取泛型T的class对象

问题描述 最近在封装es方法的时候遇到一个问题,就是泛型T怎么获取对应的class对象,代码如下: /*** Author: hrd* CreateTime: 2023/11/27 15:08* Description:*/ public interface IESIndex<R, P extends BaseModel> {/**** param p* param id 唯一ID* return*/IndexResp…

C#结合JavaScript实现多文件上传

目录 需求 引入 关键代码 操作界面 ​JavaScript包程序 服务端 ashx 程序 服务端上传后处理程序 小结 需求 在许多应用场景里&#xff0c;多文件上传是一项比较实用的功能。实际应用中&#xff0c;多文件上传可以考虑如下需求&#xff1a; 1、对上传文件的类型、大小…

风险评估是什么,为什么被称为保护网络安全的重要一环!

随着互联网的普及和信息技术的快速发展&#xff0c;网络已经成为人们生活和工作中不可或缺的一部分。然而&#xff0c;网络在为我们带来便利的同时&#xff0c;也存在着各种安全风险。因此&#xff0c;进行网络风险评估是保护网络安全的重要一环。而为什么说风险评估是保护网络…

2.2 C语言之常量

2.2 C语言之常量 一、常量 一、常量 类似于1234的整数常量属于int类型。 printf("%d\n", 1234);long类型的常量以l或L结尾 printf("%d\n", 123456789l);printf("%d\n", 123456789L);如果一个整数太大&#xff0c;以至于无法用int类型表示时&…

LINUX-ROS集成安装MQTT库步骤注意事项

环境信息 roottitan-ubuntu1:/home/mogo/data/jp/paho.mqtt.cpp# lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 18.04.5 LTS Release: 18.04 Codename: bionic 步骤 安装doxygen sudo apt install doxygen 构…

Tomcat从认识安装到详细使用

文章目录 一.什么是Tomact?二.Tomcat的安装1.下载安装包2.一键下载3.打开Tomcat进行测试4.解决Tomcat中文服务器乱码 三.Tomcat基本使用1.启动与关闭Tomcat2.Tomcat部署项目与浏览器访问项目 四.Tomcat操作中的常见问题1.启动Tomcat后&#xff0c;启动窗口一闪而过&#xff1f…

Day15——File类与IO流

1.java.io.File类的使用 1.1 File类的理解 File 类及本章下的各种流&#xff0c;都定义在 java.io 包下。一个 File 对象代表硬盘或网络中可能存在的一个文件或者文件目录&#xff08;俗称文件夹&#xff09;&#xff0c;与平台无关。&#xff08;体会万事万物皆对象&#xf…

金山终端安全系统V9.0 update_software_info_v2.php处SQL注入漏洞分析

文章目录 金山终端安全系统V9.0 update_software_info_v2.php处SQL注入漏洞分析前言一、漏洞描述二、影响版本三、POC四、漏洞原理分析参考链接&#xff1a; 金山终端安全系统V9.0 update_software_info_v2.php处SQL注入漏洞分析 前言 免责声明&#xff1a;请勿利用文章内的相…

idea 本身快捷键ctrl+d复制 无法像eclipse快捷键ctrl+alt+上下键,自动换行格式问题解决

问题 例如我使用ctrld 想复制如下内容 复制效果如下&#xff0c;没有自动换行&#xff0c;还需要自己在进行调整 解决 让如下快捷键第一个删除 修改成如下&#xff0c;将第二个添加ctrld 提示&#xff1a;对应想要修改的item&#xff0c;直接右键&#xff0c;remove是删…

Nginx反向代理跳过国内备案(以宝塔面板为例)

需要两台服务器&#xff0c;一台已备案或者免备案&#xff0c;一台国内主力服务器放你的项目。 先把域名解析到A服务器 然后在A服务器里配置 server {listen 80;server_name 你的域名;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_…

(3)kylin系统部署weblogic项目

一、jdk迁移 1、拷贝成功后要配置环境变量 vi /etc/profile 将jdk的目录添加进去 2、将jdk安装目录拷贝后权限会发生变化&#xff0c; 要对jdk下bin目录中的所有文件修改权限&#xff1a; chmod x ./* 回车即可 ----------------------------- 环境变量 export …