首页 > 其他分享 >Pytorch计算机视觉实战(更新中)

Pytorch计算机视觉实战(更新中)

时间:2024-04-15 22:34:39浏览次数:29  
标签:实战 loss tensor 10 torch Pytorch np 视觉 hidden

第一章 人工神经网络基础

1.1 人工智能与传统机器学习

学习心得:

传统机器学习(ML):需要专业的主题专家人工提取特征,并通过一个编写良好的算法来破译给定的特征,从而判断这幅图像中的内容。

输入-->人工提取特征-->特征-->具有浅层结构的分类器-->输出

当存在欺骗性的图片出现时可能会失效,我们需要创建能够精细分类多种类型的人为规则数量可能是指数级的,,因此传统方法在非常受限的环境中很有效。
我们可以将同样的思路扩展到任何领域比如:文本或结构化数据,在过去如果想通过编程解决现实世界的任务,那么必须理解关于输入数据的所有内容,并且需要编写尽可能多的规则来覆盖每个场景,不仅乏味,而且不能保证所有的新场景都会遵循上述规则。

然而,通过人工神经网络,神经网络提供了特征提取和决策分类的模块,几乎不需要手工提取特征,只需要标记数据(如:哪些是人,哪些不是人)和神经网络架构,这样就消除了传统技术(如何创造规则)带来的负担

输入-->特征学习+分类器(端到端选择)-->输出

但是在这里,我们需要提供大量样本,如:大量人和不含人的图片输入给模型,以便它学习特征

1.2 人工神经网络的构建模块

可以将人工神经网络看作一个数学函数,输入一个或者多个张量(权重),输出一个或者多个张量(权重)连接这些输入和输出的运算排列称为神经网络的架构,我们可以根据手头任务定制。

输入层:自变量的输入。

隐藏(中间)层:连接输入和输出层,并对输入数据进行转换,此外隐藏层包含节点, 用于将输入值修改为更高/更低维度的值,可以通过修改中间层节点的激活函数实现更复杂的表示。

输出层:输入变量后产生期望的值,树输出层节点数量取决于手头任务,及试图预测的是连续还是分类变量,若是连续的则输出层只有一个节点,若是n个分类则输出层就有n个节点。

激活函数:

深度学习指的是具有更多隐藏层

1.3 前向传播

在开始前使用随机权重初始化

  1. 计算隐藏层的值

  2. 进行非线性激活

    sigmoid = 1/(1 + e^-x)
    ReLU = x if x > 0 else 0
    tanh = (e^x - e-x)/(ex + e^-x)

  3. 估算输出层的值

  4. 计算与期望值对应的损失值
    计算连续变量的损失一般用MSE(均方误差的平方可以保证正误差和负误差不相互抵消)
    np.mean(np.square(pred - y))

    计算分类变量的损失一般用二元交叉熵损失(当只有两个类别的时候)
    -np.mean((y*np.log(p))+(1-y)*np.log(1-p))
    一般多分类用分类交叉熵
    (图)

数据集的最终损失是所有单个损失的平均值。

补:平均绝对误差
np.mean(np.abs(pred - y))
# 在预测输出小于1的时候,使用均方误差可以大大降低损失量
np.mean(np.square(pred - y))

前向传播(Numpy)

def feed_forward(inputs, outputs, weights):       
    pre_hidden = np.dot(inputs,weights[0])+ weights[1]
    hidden = 1/(1+np.exp(-pre_hidden))
    pred_out = np.dot(hidden, weights[2]) + weights[3]
    mean_squared_error = np.mean(np.square(pred_out - outputs))
    return mean_squared_error

1.4 反向传播

通过更新权重来减小误差的过程称为梯度下降

Numpy实现每次对一个参数少量更新,实现梯度下降

from copy import deepcopy
import numpy as np
import matplotlib.pyplot as plt

 # 更新权重
def update_weights(inputs, outputs, weights, lr):
    original_weights = deepcopy(weights)
    updated_weights = deepcopy(weights)
    original_loss = feed_forward(inputs, outputs, original_weights)
    # 先计算一次损失
    for i, layer in enumerate(original_weights):
        for index, weight in np.ndenumerate(layer):
            temp_weights = deepcopy(weights)
            temp_weights[i][index] += 0.0001 
            # 每次将权重和偏置的一个增加很小的量
            _loss_plus = feed_forward(inputs, outputs, temp_weights)
            # 再计算一次损失
            grad = (_loss_plus - original_loss)/(0.0001)
            # 计算梯度(参数值改变引起的损失的改变)
            updated_weights[i][index] -= grad*lr
            # 更新参数,使用学习率慢慢建立信任
    return updated_weights, original_loss

# 输入输出
x = np.array([[1,1]])
y = np.array([[0]])

# 参数随机初始化
W = [
np.array([[-0.0053, 0.3793],
          [-0.5820, -0.5204],
          [-0.2723, 0.1896]], dtype=np.float32).T, 
np.array([-0.0140, 0.5607, -0.0628], dtype=np.float32), 
np.array([[ 0.1528, -0.1745, -0.1135]], dtype=np.float32).T, 
np.array([-0.5516], dtype=np.float32)
]

# 绘图
losses = []
for epoch in range(100):
    W, loss = update_weights(x,y,W,0.01)
    losses.append(loss)
plt.plot(losses)
plt.title('Loss over increasing number of epochs')

批大小:当有成千上万的数据的时候,如果一起输入到网络计算损失收益不是很高,因此使用批大小进行模型训练

1.5 链式法则的反向传播

利用偏导数就可以仅仅通过利用前向传播计算出的损失来更新参数。

1.6 学习率的影响

当学习率很小的时候,权值向最优值的移动比较慢。
当学习率稍大的时候,权值先是震荡,然后快速向最优值收敛。
当学习率很大的时候,权值会达到一个很大的值,无法达到最优值。
(权值小于最优值的时候梯度为负,反之梯度为正)
一般来说学习率越小越好(0.0001-0.01)

第二章 Pytorch基础

2.1 Pytorch 张量

学习心得:

标量是0维张量
向量可以表示一维张量(轴0)
形状(4,)
二维矩阵表示二维张量(上到下轴0,左到右轴1)
形状(4,3)
三维维矩阵表示三维张量(上到下轴0,左到右轴1,外到内轴2)
形状(4,3,2)

初始化张量

import torch
x = torch.tensor([[1,2]])
y = torch.tensor([[1],[2]])

print(x.shape)
# torch.Size([1,2]) # one entity of two items
print(y.shape)
# torch.Size([2,1]) # two entities of one item each

torch.zeros(3, 4)
# tensor([[0., 0., 0., 0.],
        [0., 0., 0., 0.],
        [0., 0., 0., 0.]])
torch.ones(3, 4)
# tensor([[1., 1., 1., 1.],
        [1., 1., 1., 1.],
        [1., 1., 1., 1.]])
torch.randint(low=0, high=10, size=(3,4))
# tensor([[8, 2, 5, 9],
        [6, 1, 6, 0],
        [5, 6, 9, 5]])
torch.rand(3, 4) # 0-1之间随机
# tensor([[0.3196, 0.9387, 0.9268, 0.1246],
        [0.6700, 0.7529, 0.8687, 0.3948],
        [0.2279, 0.2309, 0.0151, 0.0339]])
torch.randn(3,4) # 服从正态分布的随机
# tensor([[-0.4039, -1.8015,  0.9784, -1.5263],
        [ 0.9577, -1.2826,  0.2746, -0.2621],
        [-1.4713,  0.6437,  0.3326, -1.0703]])

x = np.array([[10,20,30],[2,3,4]])
# np.ndarrary
y = torch.tensor(x)
# 将numpy转换为张量
print(type(x), type(y))
# <class 'numpy.ndarray'> <class 'torch.Tensor'>

张量运算

x = torch.tensor([[1,2,3,4], [5,6,7,8]]) 
print(x * 10)
# tensor([[10, 20, 30, 40],
#         [50, 60, 70, 80]])

x = torch.tensor([[1,2,3,4], [5,6,7,8]]) 
y = x.add(10)
print(y)
#tensor([[11, 12, 13, 14],
#        [15, 16, 17, 18]])

重塑张量

y = torch.tensor([2, 3, 1, 0]) 
y = y.view(4,1)
y 

# tensor([[2],
    [3],
    [1],
    [0]])

#另一种重塑方法squeeze方法,只适合在某个轴上数值为1才行
x = torch.randn(10,1,10)# 三维张量轴0,轴1 轴2
z1 = torch.squeeze(x, 1) # 1表示轴为1
# z1 = x.squeeze(1)
z1.shape
# torch.Size([10, 10])

x = torch.randn(10,1,10)# 三维张量轴0,轴1 轴2
z1 = torch.unsqueeze(x, 0) # 1表示轴为1
# z1 = x.unsqueeze(0)
# torch.Size([1,10,10])

除了unsqueeze也可以用None见下

z2, z3, z4 = x[None,:,:], x[:,None,:], x[:,:,None]
# torch.Size([1, 10, 10]) 
torch.Size([10, 1, 10]) 
torch.Size([10, 10, 1])

张量的矩阵乘法

y = torch.tensor([2, 3, 1, 0])
x = torch.tensor([[1,2,3,4], [5,6,7,8]])
print(torch.matmul(x, y))
# 或者 print(x@y)

张量的连接

x = torch.randn(10,10,10)
z = torch.cat([x,x], axis=0) # np.concatenate()
print('Cat axis 0:', z.shape)
# torch.Size([20, 10, 10])

提取张量最大值

x = torch.arange(25).reshape(5,5)
print('Max:', x.shape, x.max())    
# Max: torch.Size([5, 5]) tensor(24)

x.max(dim=0)# 轴0上的最大值
# torch.return_types.max(
values=tensor([20, 21, 22, 23, 24]),
indices=tensor([4, 4, 4, 4, 4]))

x.max(dim=1)# 轴1上的最大值
# torch.return_types.max(
values=tensor([ 4,  9, 14, 19, 24]),
indices=tensor([4, 4, 4, 4, 4]))

置换张量维数(不要通过重塑张量来交换维数)

x = torch.randn(10,20,30)# (0,1,2)
z = x.permute(2,0,1) # np.permute()
print('Permute dimensions:',z.shape)
# torch.Size([30, 10, 20])

dir(torch.Tensor)

查看张量方法

help(torch.Tensor.<method>)

对某个方法查看如何使用

2.2 张量的自动梯度

x = torch.tensor([[2., -1.], [1., 1.]], requires_grad=True)
# requires_grad=True 参数指定为张量对象计算梯度
# tensor([[ 2., -1.],
    [ 1.,  1.]], requires_grad=True)
out = x.pow(2).sum()
out.backward()
# 计算out的梯度
x.grad
# 得到out 关于 x 的梯度
# tensor([[ 4., -2.],
          [ 2.,  2.]])

一般来说,在CPU上使用Torch张量运算仍然比Numpy要快
torch的GPU最快

2.3 Pytorch构建神经网络

import torch
x = [[1,2],[3,4],[5,6],[7,8]]
y = [[3],[7],[11],[15]]

# 转换为浮点对象
X = torch.tensor(x).float()
Y = torch.tensor(y).float()
print(X,Y)

# 将数据注册到GPU
device = 'cuda' if torch.cuda.is_available() else 'cpu'
X = X.to(device)
Y = Y.to(device)

# 定义网络架构
import torch.nn as nn

# 对nn.Module的继承是强制的因为是神经网络的基类
# 必须利用super().__init__()来确保继承nn.Module就可以利用事先编写好的功能
class MyNeuralNet(nn.Module):
def __init__(self):
    super().__init__()
    self.input_to_hidden_layer = nn.Linear(2,8)#等价于 nn.Parameter(torch.rand(2,8))
    # 具体为Linear(in_features = 2 , out_features = 8 , bias = True)
    self.hidden_layer_activation = nn.ReLU()
    self.hidden_to_output_layer = nn.Linear(8,1)# nn.Parameter(torch.rand(8,1))
# 必须使用forward作为方法名,因为Pytorch保留了,用其他的会报错!!!
def forward(self, x):
    x = self.input_to_hidden_layer(x)
    #若 nn.Parameter(torch.rand(2,8)),则x = x @ self.input_to_hidden_layer(x)
    x = self.hidden_layer_activation(x)
    x = self.hidden_to_output_layer(x)
    #若 nn.Parameter(torch.rand(8,1)),则x = x @ self.hidden_to_output_layer(x)
    return x

# 创建实例并注册到GPU上
mynet = MyNeuralNet().to(device)

# 获取参数权重看一下
mynet.input_to_hidden_layer.weight

# 更详细的看下参数
mynet.parameters()
for i in  mynet.parameters():
    print(i)

# 定义MSE损失
loss_func = nn.MSELoss()
# CrossEntropyLoss() # 多分类损失
# BCELoss # 二分类损失

# 计算损失
_Y = mynet(X)
loss_value = loss_func(_Y,Y)
# 在pytorch中约定先传预测,再传真实数据
print(loss_value)

# 优化器随机梯度下降
from torch.optim import SGD
opt = SGD(mynet.parameters(), lr = 0.001)   

loss_history = []
for _ in range(50):
    opt.zero_grad()# 刷新上一步计算的梯度
    loss_value = loss_func(mynet(X),Y)
    loss_value.backward()# 计算梯度
    opt.step()# 根据梯度更新权重
    loss_history.append(loss_value.item())

# 绘图
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(loss_history)
plt.title('Loss variation over increasing epochs')
plt.xlabel('epochs')
plt.ylabel('loss value')

2.4 数据集、数据加载器和批大小

批大小:用于计算损失或更新权重的数据点的数量
在有数百万数据点的情况下很有用,

class MyDataset(Dataset):
    def __init__(self,x,y):
        self.x = torch.tensor(x).float()
        self.y = torch.tensor(y).float()
    def __len__(self):
        return len(self.x)
    def __getitem__(self, ix):
        return self.x[ix], self.y[ix]
ds = MyDataset(X, Y)

# 从ds中获取两个数据点
dl = DataLoader(ds, batch_size=2, shuffle=True)

# 其余没变可套用上方代码
# 变化见下
import time
loss_history = []
start = time.time()
for _ in range(50):
    for data in dl:
        x, y = data
        opt.zero_grad()
        loss_value = loss_func(mynet(x),y)
        loss_value.backward()
        opt.step()
        loss_history.append(loss_value)
end = time.time()
print(end - start)

预测数据点

val_x = [[10,11]]
val_xf = torch.tensor(val_x).float().to('device')
mynet(val_x)

自定义损失函数

def my_mean_squared_error(_y, y):
    loss = (_y-y)**2
    loss = loss.mean()
    return loss

my_mean_squared_error(mynet(X),Y)
# 和这个效果一样 
loss_func = nn.MSELoss()
loss_value = loss_func(mynet(X),Y)
print(loss_value)

获取中间层的值(获取参数上面讲了)

# 种子
torch.random.manual_seed(10)

# 法1
input_to_hidden = mynet.input_to_hidden_layer(X)
hidden_activation = mynet.hidden_layer_activation(input_to_hidden)
x = mynet.hidden_to_output_layer(hidden_activation)
x

# 法2 改下类的forward函数
class MyNeuralNet(nn.Module):
def __init__(self):
    super().__init__()
    self.input_to_hidden_layer = nn.Linear(2,8)
    self.hidden_layer_activation = nn.ReLU()
    self.hidden_to_output_layer = nn.Linear(8,1)
def forward(self, x):
    hidden1 = self.input_to_hidden_layer(x)
    hidden2 = self.hidden_layer_activation(hidden1)
    x = self.hidden_to_output_layer(hidden2)
    return x, hidden1

# 调用
_Y, _Y_hidden = mynet(X)

2.5 使用Sequential类构建神经网络

之前是通过定义一个类来构建神经网络,

model = nn.Sequential(
nn.Linear(2, 8),
nn.ReLU(),
nn.Linear(8, 1)
).to(device)

# 这个包可以输出一个模型的摘要(总体架构)
!pip install torch_summary
from torchsummary import summary

# 输入模型和模型大小
summary(model, torch.zeros(2,2))

# 其余没变化除了模型名称
loss_func = nn.MSELoss()
from torch.optim import SGD
opt = SGD(model.parameters(), lr = 0.001)
import time
loss_history = []
start = time.time()
for _ in range(50):
    for ix, iy in dl:
        opt.zero_grad()
        loss_value = loss_func(model(ix),iy)
        loss_value.backward()
        opt.step()
        loss_history.append(loss_value)
end = time.time()
print(end - start)

# 预测新数据
val = [[8,9],[10,11],[1.5,2.5]]
val = torch.tensor(val).float().to(device)
model(val)

2.6 保存并加载Pytorch模型

保存模型

save_path = 'mymodel.pth'
torch.save(model.state_dict(), save_path)
# torch.save(model.state_dict(), 'mymodel.pth')
# state指的是模型的当前快照
# model.state_dict()返回一个字典

# 注:一个良好的保存做法是在调用torch.save()
之前将模型注册到CPU中,有助于模型加载到任何机器上(助人为乐)
# 所以可以torch.save(model.to('cpu').state_dict(), save_path)

加载模型

# 加载模型前需要事先对模型进行权重初始化
model = nn.Sequential(
        nn.Linear(2, 8),
        nn.ReLU(),
        nn.Linear(8, 1)
).to(device)

# 然后再加载参数
state_dict = torch.load('mymodel.pth')
model.load_state_dict(state_dict)

# 预测数据
val = [[8,9],[10,11],[1.5,2.5]]
val = torch.tensor(val).float().to(device)
model(val)

标签:实战,loss,tensor,10,torch,Pytorch,np,视觉,hidden
From: https://www.cnblogs.com/dxlindex/p/18137047

相关文章

  • 通义灵码×西安交通大学携手打造“云工开物-高校训练营”,解锁 AI 时代编程学习与实战
    作为大学生如何利用AI“整活儿”?欢迎各位同学关注阿里云与西安交通大学计算机学院携手打造的“云工开物-高校训练营”,带你走近AI编程助手“通义灵码”。通义灵码是阿里推出的免费AI编程工具,拥有实时代码续写与优化、自然语言生成代码、单元测试生成、代码注释生成、代码解释......
  • Pytorch DistributedDataParallel(DDP)教程二:快速入门实践篇
    一、简要回顾DDP在上一篇文章中,简单介绍了Pytorch分布式训练的一些基础原理和基本概念。简要回顾如下:1,DDP采用Ring-All-Reduce架构,其核心思想为:所有的GPU设备安排在一个逻辑环中,每个GPU应该有一个左邻和一个右邻,设备从它的左邻居接收数据,并将数据汇总后发送给右邻。通过N轮迭代......
  • Pytorch分类模型的训练框架
    Pytorch分类模型的训练框架PhotoDataset数据集是自己定义的数据集,数据集存放方式为:----image文件夹--------0文件夹--------------img1.jpg--------------img2.jpg--------1文件夹--------------img1.jpg--------------img2.jpg....如果是cpu训练的话,就把代码中的.cu......
  • Java并发编程实战读书笔记
    1.线程池模型    netty实战中讲到的线程池模型可以描述为:1.从线程池中选择一个空间的线程去执行任务,2.任务完成时,把线程归还给线程池。这个模型与连接池类似。    根据jdk源码的研究,具体的实现模型是,线程池ThreadPoolExecutor中有一个静态内部类Worker,使用装饰器模式扩......
  • 鸿蒙HarmonyOS实战-ArkUI组件(Tabs)
    ......
  • 时空图神经网络ST-GNN的概念以及Pytorch实现
    在我们周围的各个领域,从分子结构到社交网络,再到城市设计结构,到处都有相互关联的图数据。图神经网络(GNN)作为一种强大的方法,正在用于建模和学习这类数据的空间和图结构。它已经被应用于蛋白质结构和其他分子应用,例如药物发现,以及模拟系统,如社交网络。标准的GNN可以结合来自其他机器......
  • Pytorch DistributedDataParallel(DDP)教程一:快速入门理论篇
    一、写在前面随着深度学习技术的不断发展,模型的训练成本也越来越高。训练一个高效的通用模型,需要大量的训练数据和算力。在很多非大模型相关的常规任务上,往往也需要使用多卡来进行并行训练。在多卡训练中,最为常用的就是分布式数据并行(DistributedDataParallel,DDP)。但是现有的......
  • 高并发场景QPS等专业指标揭秘大全与调优实战
    高并发场景QPS等专业指标揭秘大全与调优实战最近经常有小伙伴问及高并发场景下QPS的一些问题,特意结合项目经验和网上技术贴做了一些整理和归纳,供大家参考交流。一、一直再说高并发,多少QPS才算高并发?高并发的四个角度只说并发不提高可用就是耍流氓。可以从四个角度讨论这个问......
  • Conditional AutoEncoder的Pytorch完全实现
    一个完整的深度学习流程,必须包含的部分有:参数配置、Dataset和DataLoader构建、模型与optimizer与Loss函数创建、训练、验证、保存模型,以及读取模型、测试集验证等,对于生成模型来说,还应该有重构测试、生成测试。AutoEncoder进能够重构见过的数据、VAE可以通过采样生成新数据,对于MN......
  • 面试官:实战中用过CountDownLatch吗?详细说一说,我:啊这
    写在开头在很多的面经中都看到过提问CountDownLatch的问题,正好我们最近也在梳理学习AQS(抽象队列同步器),而CountDownLatch又是其中典型的代表,我们今天就继续来学一下这个同步工具类!CountDownLatch有何作用?我们知道AQS是专属于构造锁和同步器的一个抽象工具类,基于它Java构造出了......