安装
在PyTorch官网上选择对应的版本,然后下面会出现对应的安装命令 一般安装命令如下:
bash
复制代码
pip3 install torch torchvision torchaudio
查看版本
python
复制代码
import torch
print(torch.__version__)
print("cuda:",torch.cuda.is_available())
vbnet
复制代码
2.0.0
cuda: False
python
复制代码
import torch
x = torch.rand(5, 3)
print(x)
css
复制代码
tensor([[0.5553, 0.0181, 0.7441],
[0.4689, 0.3908, 0.6449],
[0.9274, 0.1054, 0.7166],
[0.3487, 0.2997, 0.3689],
[0.3598, 0.7262, 0.9564]])
基础知识
张量(Tensors)
声明和定义
- torch.empty(): 声明一个未初始化的矩阵。创建张量时,它将创建一个具有指定形状的未初始化张量。这意味着张量中的元素可能包含任意值,取决于分配内存时内存中已有的数据。
python
复制代码
x = torch.empty(5,3)
print(x)
css
复制代码
tensor([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
- torch.rand():随机初始化一个矩阵
python
复制代码
rand_x = torch.rand(5,3)
print(rand_x)
css
复制代码
tensor([[0.5710, 0.4795, 0.3452],
[0.4638, 0.3674, 0.7197],
[0.7879, 0.7133, 0.5328],
[0.3456, 0.7724, 0.8772],
[0.5487, 0.5881, 0.9586]])
- torch.zeros():创建数值皆为 0 的矩阵,也可以创建都是1的矩阵。torch.ones
python
复制代码
# 创建一个数值皆是 0,类型为 long 的矩阵
zero_x = torch.zeros(5, 3, dtype=torch.long)
print(zero_x.shape,zero_x)
css
复制代码
torch.Size([5, 3]) tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
- torch.tensor():直接传递 tensor 数值来创建
python
复制代码
# tensor 数值是 [5.5, 3]
tensor1 = torch.tensor([5.5, 3])
print(tensor1.shape,tensor1)
scss
复制代码
torch.Size([2]) tensor([5.5000, 3.0000])
- tensor.new_ones():new_*() 方法需要输入尺寸大小
python
复制代码
# 显示定义新的尺寸是 5*3,数值类型是 torch.double
tensor2 = tensor1.new_ones(5, 3, dtype=torch.double) # new_* 方法需要输入 tensor 大小
print(tensor2)
ini
复制代码
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]], dtype=torch.float64)
- torch.randn_like(old_tensor):保留相同的尺寸大小
python
复制代码
# 修改数值类型
tensor3 = torch.randn_like(tensor2, dtype=torch.float)
print('tensor3: ', tensor3,"size:",tensor3.shape)
ini
复制代码
tensor3: tensor([[-0.0608, 1.5656, 0.4083],
[ 1.1475, -0.7965, 0.8246],
[-1.1804, -0.4327, -1.2193],
[ 1.5783, 0.0615, 0.1998],
[ 0.9681, -0.1788, -0.2666]]) size: torch.Size([5, 3])
操作
加法操作,示例如下:
- “+” 运算符
- torch.add(tensor1, tensor2, [out=tensor3])
- tensor1.add_(tensor2):直接修改 tensor 变量
可以改变 tensor 变量的操作都带有一个后缀 , 例如 x.copy(y), x.t_() 都可以改变 x 变量
python
复制代码
tensor4 = torch.rand(5,3)
print("tensor3 + tensor4 = ",tensor4 + tensor3)
print('tensor3 + tensor4= ', torch.add(tensor3, tensor4))
# 新声明一个 tensor 变量保存加法操作的结果
result = torch.empty(5, 3)
torch.add(tensor3, tensor4, out=result)
print('add result= ', result)
# 直接修改变量
tensor3.add_(tensor4)
print('tensor3= ', tensor3)
css
复制代码
tensor3 + tensor4 = tensor([[ 0.9336, 1.6787, 0.9975],
[ 1.3947, 0.1874, 0.8959],
[-0.2482, 0.5251, -0.8883],
[ 1.9656, 0.2401, 0.3338],
[ 1.0201, -0.0755, 0.1412]])
tensor3 + tensor4= tensor([[ 0.9336, 1.6787, 0.9975],
[ 1.3947, 0.1874, 0.8959],
[-0.2482, 0.5251, -0.8883],
[ 1.9656, 0.2401, 0.3338],
[ 1.0201, -0.0755, 0.1412]])
add result= tensor([[ 0.9336, 1.6787, 0.9975],
[ 1.3947, 0.1874, 0.8959],
[-0.2482, 0.5251, -0.8883],
[ 1.9656, 0.2401, 0.3338],
[ 1.0201, -0.0755, 0.1412]])
tensor3= tensor([[ 0.9336, 1.6787, 0.9975],
[ 1.3947, 0.1874, 0.8959],
[-0.2482, 0.5251, -0.8883],
[ 1.9656, 0.2401, 0.3338],
[ 1.0201, -0.0755, 0.1412]])
除了加法运算操作,对于 Tensor 的访问,和 Numpy 对数组类似,可以使用索引来访问某一维的数据,如下所示:
python
复制代码
# 访问 tensor3 第一列数据
print(tensor3[:, 0])
scss
复制代码
tensor([ 0.9336, 1.3947, -0.2482, 1.9656, 1.0201])
对 Tensor 的尺寸修改,可以采用 torch.view() ,如下所示:
python
复制代码
x = torch.randn(4, 4)
y = x.view(16)
# 第一维的大小由-1自动推断,第二维的大小为8
z = x.view(-1, 8)
print(x.size(), y.size(), z.size())
css
复制代码
torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])
如果 tensor 仅有一个元素,可以采用 .item() 来获取类似 Python 中整数类型的数值:
python
复制代码
x = torch.randn(1)
print(x)
print(x.item())
scss
复制代码
tensor([-0.6999])
-0.6999301314353943
Numpy数组转换
Tensor 和 Numpy 的数组可以相互转换,并且两者转换后共享在 CPU 下的内存空间,即改变其中一个的数值,另一个变量也会随之改变。
Tensor转换为Numpy数组
python
复制代码
a = torch.ones(5)
print(a)
b = a.numpy()
print(b)
scss
复制代码
tensor([1., 1., 1., 1., 1.])
[1. 1. 1. 1. 1.]
两者是共享同个内存空间的,例子如下所示,修改 tensor 变量 a,看看从 a 转换得到的 Numpy 数组变量 b 是否发生变化。
python
复制代码
a.add_(1)
print(a)
print(b)
scss
复制代码
tensor([2., 2., 2., 2., 2.])
[2. 2. 2. 2. 2.]
Numpy数组转换成Tensor
在 CPU 上,除了 CharTensor 外的所有 Tensor 类型变量,都支持和 Numpy数组的相互转换操作。
python
复制代码
import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
np.add(a, 1, out=a)
print(a.shape,a.dtype,a)
print(b.shape,b.dtype,b)
ini
复制代码
(5,) float64 [2. 2. 2. 2. 2.]
torch.Size([5]) torch.float64 tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
CUDA 张量
Tensors 可以通过 .to 方法转换到不同的设备上,即 CPU 或者 GPU 上。例子如下所示
python
复制代码
# 当 CUDA 可用的时候,可用运行下方这段代码,采用 torch.device() 方法来改变 tensors 是否在 GPU 上进行计算操作
if torch.cuda.is_available():
device = torch.device("cuda") # 定义一个 CUDA 设备对象
y = torch.ones_like(x, device=device) # 显示创建在 GPU 上的一个 tensor
x = x.to(device) # 也可以采用 .to("cuda")
z = x + y
print(z)
print(z.to("cpu", torch.double)) # .to() 方法也可以改变数值类型
神经网络
对于神经网络来说,一个标准的训练流程是这样的:
- 定义一个多层的神经网络
- 对数据集的预处理并准备作为网络的输入
- 将数据输入到网络
- 计算网络的损失
- 反向传播,计算梯度 更新网络的梯度,一个简单的更新规则是 weight = weight - learning_rate * gradient
python
复制代码
import torch
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
# 输入图像是单通道,conv1 kenrnel size=5*5,输出通道 6
self.conv1 = nn.Conv2d(1, 6, 5)
# conv2 kernel size=5*5, 输出通道 16
self.conv2 = nn.Conv2d(6, 16, 5)
# 全连接层
self.fc1 = nn.Linear(16*5*5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
# max-pooling 采用一个 (2,2) 的滑动窗口
x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
# 核(kernel)大小是方形的话,可仅定义一个数字,如 (2,2) 用 2 即可
x = F.max_pool2d(F.relu(self.conv2(x)), 2)
x = x.view(-1, self.num_flat_features(x))
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
def num_flat_features(self, x):
# 除了 batch 维度外的所有维度
size = x.size()[1:]
num_features = 1
for s in size:
num_features *= s
return num_features
net = Net()
print(net)
params = list(net.parameters())
print("参数量:",len(params))
# conv1.weight
print("第一个参数大小:",params[0].size())
ini
复制代码
Net(
(conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
(fc1): Linear(in_features=400, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=84, bias=True)
(fc3): Linear(in_features=84, out_features=10, bias=True)
)
参数量: 10
第一个参数大小: torch.Size([6, 1, 5, 5])
python
复制代码
# 验证网络的正确性
input = torch.randn(1,1,32,32)
out = net(input)
print(out)
lua
复制代码
tensor([[ 0.0498, -0.0137, -0.0628, -0.1135, -0.0288, 0.0982, -0.0134, 0.0994,
0.0788, -0.1159]], grad_fn=<AddmmBackward0>)
python
复制代码
# 清空所有参数的梯度缓存,然后计算随机梯度进行反向传播
net.zero_grad()
out.backward(torch.randn(1,10))
损失函数
损失函数的输入是 (output, target) ,即网络输出和真实标签对的数据,然后返回一个数值表示网络输出和真实标签的差距。
python
复制代码
out = net(input)
print("out.shape:",out.shape)
# 定义伪标签,调整大小,需要保持和output一样的size
target = torch.randn(1,10)
print(target.shape)
# 定义均方误差
criterion = nn.MSELoss()
loss = criterion(out,target)
print(loss)
ini
out.shape: torch.Size([1, 10])
torch.Size([1, 10])
tensor(1.2594, grad_fn=<MseLossBackward0>)
反向传播
反向传播的实现只需要调用 loss.backward() 即可,当然首先需要清空当前梯度缓存,即.zero_grad() 方法,否则之前的梯度会累加到当前的梯度,这样会影响权值参数的更新。 下面是一个简单的例子,以 conv1 层的偏置参数 bias 在反向传播前后的结果为例:
python
# 清空所有参数的梯度缓存
net.zero_grad()
print('conv1.bias.grad before backward')
print(net.conv1.bias.grad)
loss.backward()
print('conv1.bias.grad after backward')
print(net.conv1.bias.grad)
scss
conv1.bias.grad before backward
None
conv1.bias.grad after backward
tensor([ 0.0010, -0.0127, 0.0054, 0.0048, -0.0075, 0.0059])
更新权重
采用随机梯度下降(Stochastic Gradient Descent, SGD)方法的最简单的更新权重规则如下:
weight = weight - learning_rate * gradient
按照这个规则,代码实现如下所示:
python
# 简单实现权重的更新例子
learning_rate = 0.01
for f in net.parameters():
f.data.sub_(f.grad.data*learning_rate)
python
# 其他优化算法,可以使用torch.optim库
import torch.optim as optim
optimizer = optim.SGD(net.parameters(),lr=0.01)
# 在训练过程中执行下列操作
optimizer.zero_grad() # 清空梯度
output = net(input)
loss = criterion(output,target)
loss.backward()
# 更新权重
optimizer.step()
训练分类器
- pytorch有一个专门的torchvision库,包含了dataloader和dataset
- 使用CIFAR10为例
训练图片分类器
一般流程如下:
- 通过调用
torchvision
加载和归一化CIFAR10训练集和测试集 - 构建一个卷积神经网络
- 定义一个损失函数
- 在训练集上训练网络
- 在测试集上测试网络性能
python
# 1.加载和归一化CIFAR10
# 导入必须包
import torch
import torchvision
import torchvision.transforms as transforms
python
# torchvision 的数据集输出的图片都是 PILImage ,即取值范围是 [0, 1] ,这里需要做一个转换,变成取值范围是 [-1, 1]
# 定义了一个组合变换
transform = transforms.Compose([
transforms.ToTensor(), # PIL Image或者Numpy ndarray转换成Pytorch的张量
transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5)) # 图像数据执行标准化操作,第一个三元组表示每个通道的均值 (0.5, 0.5, 0.5),而第二个三元组表示每个通道的标准差 (0.5, 0.5, 0.5)。
])
# 训练集
trainset = torchvision.datasets.CIFAR10(root='./data',train=True,download=True,transform=transform)
trainloader = torch.utils.data.DataLoader(trainset,batch_size=4,shuffle=True,num_workers=2)
# 测试集
testset = torchvision.datasets.CIFAR10(root='./data', train=False,
download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4,
shuffle=False, num_workers=2)
# 10个分类
classes = ('plane', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
Files already downloaded and verified
Files already downloaded and verified
python
# 可视化训练图片,也可以使用TensorBoard
import matplotlib.pyplot as plt
import numpy as np
# 展示图片
def imshow(img):
print(img.shape)
img = img/2 +0.5 # 对图像进行逆归一化。在进行训练前,图像很可能已经被归一化,其像素值范围在[-1, 1]之间。逆归一化之后,像素值范围将恢复到 [0, 1],从而能够以原始形式正确显示图像。
npimg = img.numpy() # pytorch张量转换成numpy
plt.imshow(np.transpose(npimg,(1,2,0))) # np.transpose() 对 NumPy 数组 npimg 进行转置,第1个轴(高度 H)变为新的第 0 个轴 2=>1 0=>2
plt.show()
# 随机获取训练集图片
dataiter = iter(trainloader)
# 返回的图片数量和设置的batch_size有关
images,labels = next(dataiter)
print(images.shape,labels)
# 展示图片
imshow(torchvision.utils.make_grid(images))
# 打印图片标签
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))
scss
torch.Size([4, 3, 32, 32]) tensor([7, 7, 9, 8])
torch.Size([3, 36, 138])
horse horse truck ship
附录
本文都是由python的notebook编写,包括结果都是运行后生成的结果。最终通过notebook转换成markdown,命令如下:
bash
jupyter nbconvert torch_basic.ipynb --to markdown
如何学习大模型 AI ?
由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。
但是具体到个人,只能说是:
“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。
这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。
我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
😝有需要的小伙伴,可以点击下方链接免费领取或者V扫描下方二维码免费领取🆓
第一阶段(10天):初阶应用
该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。
- 大模型 AI 能干什么?
- 大模型是怎样获得「智能」的?
- 用好 AI 的核心心法
- 大模型应用业务架构
- 大模型应用技术架构
- 代码示例:向 GPT-3.5 灌入新知识
- 提示工程的意义和核心思想
- Prompt 典型构成
- 指令调优方法论
- 思维链和思维树
- Prompt 攻击和防范
- …
第二阶段(30天):高阶应用
该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。
- 为什么要做 RAG
- 搭建一个简单的 ChatPDF
- 检索的基础概念
- 什么是向量表示(Embeddings)
- 向量数据库与向量检索
- 基于向量检索的 RAG
- 搭建 RAG 系统的扩展知识
- 混合检索与 RAG-Fusion 简介
- 向量模型本地部署
- …
第三阶段(30天):模型训练
恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。
到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?
- 为什么要做 RAG
- 什么是模型
- 什么是模型训练
- 求解器 & 损失函数简介
- 小实验2:手写一个简单的神经网络并训练它
- 什么是训练/预训练/微调/轻量化微调
- Transformer结构简介
- 轻量化微调
- 实验数据集的构建
- …
第四阶段(20天):商业闭环
对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。
- 硬件选型
- 带你了解全球大模型
- 使用国产大模型服务
- 搭建 OpenAI 代理
- 热身:基于阿里云 PAI 部署 Stable Diffusion
- 在本地计算机运行大模型
- 大模型的私有化部署
- 基于 vLLM 部署大模型
- 案例:如何优雅地在阿里云私有部署开源大模型
- 部署一套开源 LLM 项目
- 内容安全
- 互联网信息服务算法备案
- …
学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。
如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。
这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费
】
😝有需要的小伙伴,可以Vx扫描下方二维码免费领取==🆓