1.张量

1.1创建张量

张量创建主要有3种方式

  • 直接创建
  • 依数值创建
  • 依概率创建 ```python

    1.直接创建

    a = np.ones((3,3)) arr = torch.tensor(a,device=’cuda’) print(arr)

    data、dtype

    device 所在设备

    requires_grad 是否需要梯度

    pin_memory 是否锁页内存

2.依据数值创建

a = np.array([[1,2,3],[3,4,5]]) arr = torch.from_numpy(a) print(arr)

通过from_numpy创建的张量适合narrady共享内存的

arr[0][0] = 0 print(a)

创建全零张量 out:输出的张量

out_t = torch.tensor([1]) zero_tensor = torch.zeros((3,3),out=out_t) print(zero_tensor)

创建全一张量 out:输出的张量

out_t = torch.tensor([1]) ones_tensor = torch.ones((3,3),out=out_t) print(ones_tensor)

创建指定数值的全数值张量

full_tensor = torch.full((3,3),10) print(full_tensor)

等差张量

t = torch.arange(1,20,2) print(t)

均分张量

s = torch.linspace(1,20,5) print(s)

对数均分

log = torch.logspace(1,20,5) print(log)

3.依据概率创建

正态分布

根据mean以及std是否为标量还是张量,总共有四种情况

mean1 = torch.arange(1,5,dtype=torch.float) std1 = torch.arange(1,5,dtype=torch.float) guass1 = torch.normal(mean=mean1,std=std1) print(“m张s张:”,guass1) mean0 = 0.0 std0 = 1.0 guass2 = torch.normal(mean=mean0,std=std0,size=(4,1)) print(“m标s标:”,guass2) guass3 = torch.normal(mean=mean1,std=std0) print(“m张s标:”,guass3) guass4 = torch.normal(mean=mean0,std=std1) print(“m标s张:”,guass4)

标准正态分布

stdnol = torch.randn((3,3)) print(stdnol )

均匀分布

r = torch.randint(0,3,(3,3)) print(r)

0~n-1的随即排列

randp = torch.randperm(10) print(randp)

伯努利

b = torch.bernoulli(torch.zeros(3, 3)) print(b)

  1. <a name="DIWih"></a>
  2. ## 1.2 张量操作
  3. 操作主要分为3部分:
  4. - 拼接与切分
  5. - 索引和变形
  6. - 压缩与扩展
  7. ```python
  8. # 拼接与切分
  9. # torch.cat() 张量序列,dim要拼接维度,在制定维度接续
  10. # torch.stack() 张量序列,dim要拼接的维度,在指定维度创建新的张量
  11. t = torch.ones((1,3))
  12. c1 = torch.cat([t,t,t],dim=0)
  13. c2 = torch.cat([t,t,t],dim=1)
  14. s1 = torch.stack([t,t,t],dim=0)
  15. print(c1,c1.shape)
  16. print(c2,c2.shape)
  17. print(s1,s1.shape)
  18. # 切分
  19. # torch.chunk() 将张量按维度平均切分,返回张量列表 chunks要切分的2份数,dim要切分的维度
  20. ch1 = torch.chunk(c1,dim=1,chunks=3)
  21. ch2 = torch.chunk(c1,dim=0,chunks=3)
  22. print(ch1)
  23. print(ch2)
  24. # torch.split() split_size_or_sections 为int标长度,为list按元素切分
  25. list_of_tensor1 = torch.split(t,3,dim=1)
  26. list_of_tensor2 = torch.split(t,[1,1,1],dim=1) # list之和等于维度上的长度t[1]
  27. print(list_of_tensor1)
  28. print(list_of_tensor2)
  29. # 索引 torch.index_select\torch.masked_select
  30. t2 = torch.randint(0,9,size=(3,3))
  31. print(t2)
  32. index = torch.tensor([0,2],dtype=torch.long)
  33. idx = torch.index_select(t2,dim=0,index=index) # index的数据类型时指定的必须是torch.long
  34. print(idx)
  35. mask = t2.ge(3) # ge大于等于x gt大于x le小于等于 lt
  36. ms = torch.masked_select(t2,mask) # 通过mask为True进行索引,返回的是一维张量
  37. print(ms) # 返回大于等于mask的值
  38. # 形状变换torch.reshape
  39. t_reshape = torch.reshape(t2,(1,3,3,1))
  40. print(t_reshape)
  41. # torch.transpose(tensor,dim0=,dim1=) # 交换两个维度
  42. # torch.squezze() 压缩
  43. # torch.unquezze() 扩展

1.3 张量的数学运算

  1. # 数学运算
  2. # 加减除乘
  3. torch.add()
  4. torch.sub()
  5. torch.div()
  6. torch.mul()
  7. # torch.addcmul() 加法结合乘法
  8. # torch.addcdiv() 加法结合除法

1.4 autograd

  • autograd.backward() 更新梯度
  • autograd.grand() 高阶求导

2. 线性回归

  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. import torch
  4. # 线性回归 [y] = [w][x] + [b]
  5. best_loss,best_w,best_b = 9999,0,0
  6. x = torch.rand(20,1) * 10
  7. y = 2*x + (5+torch.randn(20,1))
  8. lr = 0.1
  9. w = torch.randn((1),requires_grad=True)
  10. b = torch.zeros((1),requires_grad=True)
  11. for iteration in range(1000):
  12. # 前向传播
  13. wx = torch.mul(w,x)
  14. y_pred = torch.add(wx,b)
  15. # loss MSE
  16. loss = (0.5 * (y-y_pred)**2).mean()
  17. # loss反向传播
  18. loss.backward()
  19. # 更新参数
  20. b.data.sub_(lr * b.grad)
  21. w.data.sub_(lr * w.grad)
  22. # 作图
  23. if loss < best_loss :
  24. best_loss,best_w,best_b = loss,w.data.numpy(),b.data.numpy()
  25. best_y_pred = y_pred.data.numpy()
  26. plt.scatter(x.data.numpy(),y.data.numpy())
  27. plt.plot(x.data.numpy(),y_pred.data.numpy(),'r-',lw=3)
  28. plt.text(2,20,'Loss:%.4f' % loss.data.numpy(),fontdict={'size':20,'color':'red'})
  29. plt.xlim(1.5,10)
  30. plt.ylim(8,28)
  31. plt.title("epochs:{}\nw:{} b:{}".format(iteration,w.data.numpy(),b.data.numpy()))
  32. plt.pause(0.5)
  33. if loss.data.numpy()<1:
  34. break
  35. # 最佳拟合曲线
  36. plt.scatter(x.data.numpy(),y.data.numpy())
  37. plt.plot(x.data.numpy(),best_y_pred,'r-',lw=3)
  38. plt.text(2,20,'Loss:%.4f' % best_loss,fontdict={'size':20,'color':'red'})
  39. plt.xlim(1.5,10)
  40. plt.ylim(8,28)
  41. plt.title("Best_line\nw:{} b:{}".format(best_w,best_b))
  42. plt.show()

image.png

3.逻辑回归

  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. import torch
  4. import torch.nn as nn
  5. sample_num = 100
  6. mean_value = 1.5
  7. bias = 1
  8. n_data = torch.ones(sample_num,2)
  9. x0 = torch.normal(mean_value*n_data,1)+bias
  10. y0 = torch.zeros(sample_num)
  11. x1 = torch.normal(- mean_value*n_data,1)+bias
  12. y1 = torch.ones(sample_num)
  13. train_x = torch.cat((x0,x1),dim=0)
  14. train_y = torch.cat((y0,y1),dim=0)
  15. # 超参数
  16. lr = 0.01
  17. epochs = 100
  18. best_acc = -0.1
  19. acc=0.0
  20. # 逻辑回归模型
  21. class LR(nn.Module):
  22. def __init__(self):
  23. super(LR,self).__init__()
  24. self.features = nn.Linear(2,1)
  25. self.sigmoid = nn.Sigmoid()
  26. def forward(self,x):
  27. x = self.features(x)
  28. x = self.sigmoid(x)
  29. return x
  30. pass
  31. lr_clf = LR() # 实例化
  32. loss_fn = nn.BCELoss()
  33. optimizer = torch.optim.SGD(lr_clf.parameters(),lr=lr,momentum=0.9)
  34. for iteration in range(1000):
  35. # 前向传播
  36. y_pred = lr_clf(train_x)
  37. # 计算loss
  38. loss = loss_fn(y_pred.squeeze(),train_y)
  39. # 反向传播
  40. loss.backward()
  41. # 更新参数
  42. optimizer.step()
  43. mask = y_pred.ge(0.5).float().squeeze()
  44. correct = (mask==train_y).sum()
  45. acc = correct.item() / train_y.size(0)
  46. # 绘图
  47. if best_acc < acc:
  48. best_acc = acc
  49. if best_acc > 0.9:
  50. plt.scatter(x0.data.numpy()[:,0],x0.data.numpy()[:,1],c='r',label='class 0')
  51. plt.scatter(x1.data.numpy()[:,0],x1.data.numpy()[:,1],c='b',label='class 1')
  52. w0,w1 = lr_clf.features.weight[0]
  53. w0,w1 = float(w0.item()),float(w1.item())
  54. plot_b = float(lr_clf.features.bias[0].item())
  55. plot_x = np.arange(-6,6,0.1)
  56. plot_y = (- w0 * plot_x - plot_b) / w1
  57. plt.xlim(-5,7)
  58. plt.ylim(-5,7)
  59. plt.plot(plot_x,plot_y)
  60. plt.text(-5,5,' acc:%.4f' % best_acc,fontdict={'size':20,'color':'red'})
  61. plt.title("epochs:{}\n w0:{:.2f} w1:{:.2f} b:{:.2f} \n acc:{}".format(iteration,w0,w1,plot_b,acc))
  62. plt.pause(0.5)
  63. if acc >= 0.999:
  64. break

image.png

数据 - 模型 - 迭代器 - 优化

4. 数据封装和迭代

  • torch.utils.data.DataLoader # 数据迭代器
  • torch.utils.data.Dataset # 继承类

    4.1 Dataset

  • Dataset是一个继承类,一遍创建一个对象封装好数据读取,实例:

    1. class CustomDataset(data.Dataset):
    2. """
    3. 下载数据、初始化数据,都可以在这里完成
    4. """
    5. # 初始化
    6. def __init__(self,data):
    7. xy = data # 传入一个numpy数组,最后一列为标签,其余为特征
    8. self.x_data = torch.from_numpy(xy[:, 0:-1])
    9. self.y_data = torch.from_numpy(xy[:, [-1]])
    10. self.len = xy.shape[0]
    11. # __getitem_() 主要作用是可以让对象实现迭代功能
    12. def __getitem__(self, index):
    13. return self.x_data[index], self.y_data[index]
    14. # __len__() 主要作用是获取长度
    15. def __len__(self):
    16. return self.len

4.2 DataLoader

image.png

  • Epoch:所有训练样本 称为一个Epoch
  • iteration:一批数据
  • BatchSize:批大小
  • 样本总数:80 Batchsize:10 ;1 Epoch = 8 iteration
  1. # 模拟迭代器
  2. x = np.random.randint(1,5,(100)).reshape(-1,1)
  3. y = np.ones((100),dtype=np.int64).reshape(-1,1)
  4. data = np.concatenate((x,y),axis=1)
  5. # 实例化数据
  6. # 小技巧,添加一个with_labels来区分传入的是带标签还是不带标签的数据
  7. train = CustomDataset(data)
  8. # 构造迭代器
  9. train_loader = DataLoader(dataset=train,
  10. batch_size=12,
  11. shuffle=True,
  12. drop_last=True)
  13. # 运行迭代器
  14. from torch.autograd import Variable
  15. for epoch in range(2):
  16. for i, data in enumerate(train_loader):
  17. # 将数据从 train_loader 中读出来,一次读取的样本数是32个
  18. inputs, labels = data
  19. # 将这些数据转换成Variable类型
  20. inputs, labels = Variable(inputs), Variable(labels)
  21. # 接下来就是跑模型的环节了,我们这里使用print来代替
  22. print("epoch:", epoch, "的第" , i, "个inputs", inputs.data.size(), "labels", labels.data.size())

5.网络模型的创建

建模基本流程
image.png

5.1 nn.Module模块

  • nn.Parameter 张量子类,表示可学习参数,如weight,bias
  • nn.Module 所有网络层基类,管理网络属性
  • nn.functional 函数具体实现,如卷积,池化,激活函数等
  • nn.init 参数初始化
  1. import torch.nn as nn
  2. import torch.nn.functional as F
  3. from torchsummary import summary
  4. class CNNmodel(nn.Module):
  5. def __init__(self,classes):
  6. super(CNNmodel, self).__init__()
  7. self.conv1 = nn.Conv2d(3,6,5)
  8. self.conv2 = nn.Conv2d(6,16,5)
  9. self.fc1 = nn.Linear(16*5*5,120)
  10. self.fc2 = nn.Linear(120,84)
  11. self.fc3 = nn.Linear(84,classes)
  12. def forward(self,x):
  13. out = F.relu(self.conv1(x))
  14. out = F.max_pool2d(out,2)
  15. out = F.relu(self.conv2(out))
  16. out = F.max_pool2d(out,2)
  17. # view函数相当于numpy的reshape,-1表示一个不确定的数
  18. # 将代码tensor转为一维 和 flatten()类似
  19. out = out.view(out.size(0),-1)
  20. out = F.relu(self.fc1(out))
  21. out = F.relu(self.fc2(out))
  22. out = self.fc3(out)
  23. return out
  24. def _init_weight(self):
  25. for m in self.modules(): # 继承nn.Module的方法
  26. if isinstance(m, nn.Conv2d):
  27. nn.init.kaiming_normal_(m.weight)
  28. elif isinstance(m, nn.BatchNorm2d):
  29. m.weight.data.fill_(1)
  30. m.bias.data.zero_()
  31. # 注意 classes=3 不是 3分类 而是4分类
  32. mymodel = CNNmodel(classes=3)
  33. mymodel._init_weight()
  34. summary(mymodel)

image.png

5.2 Containers

  • nn.Sequetial 按顺序包装多个网络层 顺序性
  • nn.ModuleList 像list一样包装多个网络层 迭代性
  • nn.ModuelDict 像dict一样包装多个网络层 索引性

5.2.1 Sequetial

  1. import torch.nn as nn
  2. import torch.nn.functional as F
  3. from torchsummary import summary
  4. class CNNSequential(nn.Module):
  5. def __init__(self,classes):
  6. super(CNNSequential, self).__init__()
  7. # 特征提取
  8. self.feature = nn.Sequential(
  9. nn.Conv2d(3,6,(5,)),
  10. nn.ReLU(),
  11. nn.MaxPool2d(kernel_size=2,stride=2),
  12. nn.Conv2d(6,16,(5,)),
  13. nn.ReLU(),
  14. nn.MaxPool2d(kernel_size=2, stride=2),
  15. )
  16. # 分类
  17. self.classifier = nn.Sequential(
  18. nn.Linear(16*5*5,120),
  19. nn.ReLU(),
  20. nn.Linear(120,84),
  21. nn.ReLU(),
  22. nn.Linear(84,classes)
  23. )
  24. def forward(self,x):
  25. out = self.feature(x)
  26. out = out.view(out.size[0],-1)
  27. out = self.classifier(out)
  28. return out
  29. def _init_weight(self):
  30. for m in self.modules(): # 继承nn.Module的方法
  31. if isinstance(m, nn.Conv2d):
  32. nn.init.kaiming_normal_(m.weight)
  33. elif isinstance(m, nn.BatchNorm2d):
  34. m.weight.data.fill_(1)
  35. m.bias.data.zero_()
  36. mymodel = CNNSequential(classes=3)
  37. mymodel._init_weight()
  38. summary(mymodel)

image.png

5.2.2 Modules

  • append() # 在ModuleList后面添加网络层
  • extend() # 拼接两个ModuleList
  • insert() # 指定位置传入网络层
  1. import torch
  2. import torch.nn as nn
  3. import torch.nn.functional as F
  4. from torchsummary import summary
  5. class ModulesList(nn.Module):
  6. def __init__(self):
  7. super(ModulesList, self).__init__()
  8. self.linears = nn.ModuleList([nn.Linear(10,10) for i in range(20)])
  9. def forward(self,x):
  10. for i,linear in enumerate(self.linears):
  11. x = linear(x)
  12. return x
  13. def _init_weight(self):
  14. for m in self.modules(): # 继承nn.Module的方法
  15. if isinstance(m, nn.Conv2d):
  16. nn.init.kaiming_normal_(m.weight)
  17. elif isinstance(m, nn.BatchNorm2d):
  18. m.weight.data.fill_(1)
  19. m.bias.data.zero_()
  20. # flag2 = False
  21. flag2 = True
  22. if flag2:
  23. fake_data = torch.ones((10,10))
  24. mymodel = ModulesList()
  25. mymodel._init_weight()
  26. summary(mymodel)
  27. output = mymodel(fake_data)
  28. print(output)

image.png

5.2.3 ModuleDiect

  1. import torch
  2. import torch.nn as nn
  3. import torch.nn.functional as F
  4. from torchsummary import summary
  5. class ModuleDict(nn.Module):
  6. def __init__(self):
  7. super(ModuleDict, self).__init__()
  8. self.choices = nn.ModuleDict({
  9. "conv":nn.Conv2d(10,10,3),
  10. "pool":nn.MaxPool2d(3),
  11. })
  12. self.activations = nn.ModuleDict({
  13. "relu":nn.ReLU(),
  14. "prelu":nn.PReLU(),
  15. })
  16. def forward(self,x,choice,act):
  17. x = self.choices[choice](x)
  18. x = self.activations[act](x)
  19. return x
  20. def _init_weight(self):
  21. for m in self.modules(): # 继承nn.Module的方法
  22. if isinstance(m, nn.Conv2d):
  23. nn.init.kaiming_normal_(m.weight)
  24. elif isinstance(m, nn.BatchNorm2d):
  25. m.weight.data.fill_(1)
  26. m.bias.data.zero_()
  27. # flag3 = False
  28. flag3 = True
  29. if flag3:
  30. fake_data = torch.randn((4,10,32,32))
  31. mymodel = ModuleDict()
  32. mymodel._init_weight()
  33. summary(mymodel)
  34. output = mymodel(fake_data,"conv","prelu")
  35. print(output)

image.png

6. AlexNet 卷积池化

image.png
【卷积 - 池化】迭代

  1. #!/usr/bin/env python
  2. # -*- encoding: utf-8 -*-
  3. '''
  4. @File : AlexNet.py
  5. @Contact : htkstudy@163.com
  6. @Modify Time @Author @Version @Desciption
  7. ------------ ------- -------- -----------
  8. 2021/3/29 21:04 Armor(htk) 1.0 None
  9. '''
  10. import torch
  11. import torch.nn as nn
  12. import torch.nn.functional as F
  13. from torchsummary import summary
  14. class AlexNet(nn.Module):
  15. def __init__(self,num_classes=1000):
  16. super(AlexNet, self).__init__()
  17. self.features = nn.Sequential(
  18. nn.Conv2d(3,64,kernel_size=11,stride=4,padding=2),
  19. nn.ReLU(inplace=True),
  20. nn.MaxPool2d(kernel_size=3,stride=2),
  21. nn.Conv2d(64, 192, kernel_size=5, padding=2),
  22. nn.ReLU(inplace=True),
  23. nn.MaxPool2d(kernel_size=3, stride=2),
  24. nn.Conv2d(192, 384, kernel_size=3,padding=1),
  25. nn.ReLU(inplace=True),
  26. nn.Conv2d(384,256, kernel_size=3, padding=1),
  27. nn.ReLU(inplace=True),
  28. nn.Conv2d(256,256, kernel_size=3, padding=1),
  29. nn.ReLU(inplace=True),
  30. nn.MaxPool2d(kernel_size=3,stride=2)
  31. )
  32. self.avgpool = nn.AdaptiveAvgPool2d((6,6))
  33. self.classifier = nn.Sequential(
  34. nn.Dropout(),
  35. nn.Linear(256*6*6,4006),
  36. nn.ReLU(inplace=True),
  37. nn.Dropout(),
  38. nn.Linear(4096,4096),
  39. nn.ReLU(inplace=True),
  40. nn.Linear(4096,num_classes),
  41. )
  42. summary(AlexNet())

参数列表
**
Conv2D参数:

  • in_channels:输入通道数
  • out_channels:输出通道数,等价于卷积核个数
  • kernel_size:卷积核大小
  • stride:步长
  • padding:填充个数
  • dilation:空洞卷积大小
  • groups:分组卷积设置
  • bias:偏置

补充:

  • 尺寸计算:……
  • ConvTranspose2d 转置卷积

MaxPool2d参数:

  • kernel_size:池化核大小
  • stride:步长
  • padding:填充个数
  • dilation:池化核间隔大小
  • ceil_mode:尺寸向上取整
  • return_indices:记录池化像素索引

AvgPool2d参数:

  • kernel_size:池化核大小
  • stride:步长
  • padding:填充个数
  • ceil_mode:尺寸向上取整
  • count_include_pad:填充值用于计算
  • divisor_override:除法因子

Linear参数:

  • in_features:输入结点个数
  • out_features:输出结点个数
  • bias:偏置

7.激活函数

7.1 nn.Sigmoid

image.png

7.2 nn.tanh

image.png

7.3 nn.ReLu

image.png

7.4 ReLu变体

  • nn.LeakyReLu
  • nn.PReLu
  • nn.RReLU

image.png

8.权值初始化

10种初始化方法
image.png

  1. # 初始化
  2. nn.init.kaiming_normal_(tensor=m.weight)
  3. # 初始化增益
  4. nn.init.calculate_gain(nonlinearity='ReLU')

9.损失函数

9.1 nn.CrossEntropyLoss

  • 损失函数 Loss Function: 计算一个样本

image.png

  • 代价函数 Cost Function:计算所有样本的平均值

image.png

  • 目标函数 Object Function:

Obj = Cost + Regularization

  1. 交叉熵函数
  2. loss_fcuntion = nn.CrossEntropyLoss(weight=,ignore_index=,reduction='mean')
  • weight:个类别的loss设置权值
  • ignore_index:忽略某个类别
  • reduction:计算模式
    • mean 加权平均 返回标量
    • sum 所有元素求 返回标量
    • none 逐个计算

image.png
KL散度就是相对熵

  1. # map和lambda结合起来使用,代码更加简洁:
  2. list_x = [1, 2, 3, 4, 5, 6, 7, 8]
  3. r = map(lambda x:x*x,list_x)
  4. print(list(r))
  5. -----------------------------------------
  6. 输出:
  7. [1, 4, 9, 16, 25, 36, 49, 64]

9.2 nn.NLLoss

image.png

9.3 nn.BCELoss

image.png

9.4 nn.BCEWithLogitsLoss

image.png

9.5 其余14种损失函数

  • nn.L1Loss
  • nn.MSELoss

image.png

  • SmoothL1Loss 平滑

image.png

  • PoissonNLLLoss 泊松

image.png

  • nn.KLDivLoss KL散度

image.png

  • nn.MarginRankingLoss 排序

image.png

  • nn.MultiLabelMarginLoss 多标签

image.png

  • nn.SoftMarginLoss 二分类

image.png

  • nn.MultiLabelSoftMarginLoss SoftMarginLoss多标签分类

image.png
**

  • nn.MultiMarginLoss 多分类

image.png

  • nn.TripletMarginLoss 三元组损失

image.png

  • nn.HingeEmbeddingLoss 非线性相似性损失

image.png

  • nn.CosineEmbeddingLoss 余弦相似度 关注方向上的差异

image.png

  • nn.CTCLoss 时序损失

image.png

10.优化器

  • pytorch特性:张量梯度不自动清零
  • optim的几个方法

    • zero_grad() 清零
    • step() 更新

      1. optimizer = nn.optim.Adam()
      image.png
  • Momentum 冲量,动量 :结合当前梯度遇上一次更新信息用于当前更新,保持更新惯性。

  • 学习率

image.png

image.png