版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
人工智能AI:Keras PyTorch 深度学习实战(不定时更新)
PyTorch中文文档:https://pytorch-cn.readthedocs.io/zh/latest/
1.torch.div()
1.div_(value):div()的in-place运算形式
2.torch.div(input, value, out=None)
1.将input逐元素除以标量值value,并返回结果到输出张量out。 即 out=tensor/value
如果输入是FloatTensor or DoubleTensor类型,则参数 value 必须为实数,否则须为整数。
译注:似乎并非如此,无关输入类型,value取整数、实数皆可。
2.参数:
input (Tensor) – 输入张量
value (Number) – 除数
out (Tensor, optional) – 输出张量
3.例子
import torch
a = torch.randn(5)
a 输出
-0.6147
-1.1237
-0.1604
-0.6853
0.1063
[torch.FloatTensor of size 5]
torch.div(a, 0.5)
输出
-1.2294
-2.2474
-0.3208
-1.3706
0.2126
[torch.FloatTensor of size 5]
3.torch.div(input, other, out=None)
1.两张量input和other逐元素相除,并将结果返回到输出。即 out_i=input_i/other_i
两张量形状不须匹配,但元素数量须一致。
注意:当形状不匹配时,input的形状作为输出张量的形状。
2.参数:
input (Tensor) – 张量(分子)
other (Tensor) – 张量(分母)
out (Tensor, optional) – 输出张量
3.例子:
import torch
a = torch.randn(4,4)
a 输出
-0.1810 0.4017 0.2863 -0.1013
0.6183 2.0696 0.9012 -1.5933
0.5679 0.4743 -0.0117 -0.1266
-0.1213 0.9629 0.2682 1.5968
[torch.FloatTensor of size 4x4]
b = torch.randn(8, 2)
b 输出
0.8774 0.7650
0.8866 1.4805
-0.6490 1.1172
1.4259 -0.8146
1.4633 -0.1228
0.4643 -0.6029
0.3492 1.5270
1.6103 -0.6291
[torch.FloatTensor of size 8x2]
torch.div(a, b)
输出
-0.2062 0.5251 0.3229 -0.0684
-0.9528 1.8525 0.6320 1.9559
0.3881 -3.8625 -0.0253 0.2099
-0.3473 0.6306 0.1666 -2.5381
[torch.FloatTensor of size 4x4]
4.torch.div(a, b)
a和b必须是类型一致的,就是如果a是FloatTensor那么b也必须是FloatTensor,可以使用tensor.to(torch.float64)进行转换。
1.例子
>>> import torch
>>> a = torch.randn(4, 4)
>>> a
tensor([[-0.3711, -1.9353, -0.4605, -0.2917],
[ 0.1815, -1.0111, 0.9805, -1.5923],
[ 0.1062, 1.4581, 0.7759, -1.2344],
[-0.1830, -0.0313, 1.1908, -1.4757]])
>>> b = torch.randn(4)
>>> b
tensor([ 0.8032, 0.2930, -0.8113, -0.2308])
>>> torch.div(a, b)
tensor([[-0.4620, -6.6051, 0.5676, 1.2637],
[ 0.2260, -3.4507, -1.2086, 6.8988],
[ 0.1322, 4.9764, -0.9564, 5.3480],
[-0.2278, -0.1068, -1.4678, 6.3936]])
2.torch.div(a,0.6) 就是a直接除以一个数字。
>>> import torch
>>> a = torch.randn(5)
>>> a
tensor([ 0.3810, 1.2774, -0.2972, -0.3719, 0.4637])
>>> torch.div(a, 0.5)
tensor([ 0.7620, 2.5548, -0.5944, -0.7439, 0.9275])
2.Tensor张量化
1.torch.FloatTensor 用于生成数据类型为浮点型的Tensor,参数可以是一个列表,也可以是一个维度。
import torch
a = torch.FloatTensor(3,4) # 3行4列
a
Out[1]: tensor([[1.0561e-38, 1.0653e-38, 1.0469e-38, 9.5510e-39],
[8.7245e-39, 1.0194e-38, 9.0919e-39, 8.7245e-39],
[1.0194e-38, 1.0561e-38, 1.0286e-38, 1.6956e-43]])
a = torch.FloatTensor([2,3,4,5]) # 一个列表
2.torch.IntTensor 用于生成数据类型为整型的Tensor,参数可以是一个列表,也可以是一个维度。
a = torch.IntTensor(3,4) # 3行4列
a = torch.IntTensor([3,4,5,6]) # 一个列表
a
Out[9]: tensor([2., 3., 4., 5.])
3.torch.rand
torch.rand 用于生成数据类型为浮点型且维度指定的Tensor,与NumPy的numpy.rand相似,随机生成的浮点数据在0-1区间均匀分布
import torch
a = torch.rand(2,3)
Out[1]: tensor([[0.8768, 0.4990, 0.7870],
[0.9143, 0.8974, 0.9184]])
4.torch.randn
torch.randn 用于生成数据类型为浮点型且维度指定的随机Tensor,与NumPy的numpy.randn相似,随机生成的浮点数的取值满足均值为0,方差为1的正态分布。
import torch
a = torch.randn(2,2)
a
Out[11]:tensor([[ 0.7445, -0.4259],
[ 0.8912, 1.1891]])
5.torch.range、torch.arange
1.torch.range 用于生成数据类型为浮点型的且自定义取值范围的Tensor张量,参数有三个:起始值、结束值、步长。
import torch
a = torch.range(1,20,1)
a
Out[16]: tensor([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14.,15., 16., 17., 18., 19., 20.])
2.torch.arange(1,20,1) 用于生成数据类型为整数型的且自定义取值范围的Tensor张量,参数有三个:起始值、结束值、步长。
import torch
torch.arange(1,20,1)
Out[17]:tensor([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
6.torch.zeros
torch.zeros 用于生成数据类型为浮点型且维度指定的Tensor,元素全为0。
import torch
a = torch.zeros(3,2)
a
Out[23]: tensor([[0., 0.],
[0., 0.],
[0., 0.]])
7.torch的相关计算表达式
torch.abs(a) 各项参数的绝对值
torch.add(a,b) 求和
torch.clamp(a,b,c) 对输入的参数按照自定义范围进行裁剪,参数有3个:裁剪对象、裁剪的上、下界。(将区间里面的东西减掉)
torch.div(a,b) 求商
torch.mul(a,b) 求积(不一定是矩阵)
torch.pow(a,b) 求幂
torch.mm(a,b) 求积(按矩阵和矩阵之间的规则做)
torch.mv(a,b) 求积(按矩阵和向量之间的规则做)
8.matmul、bmm
1.matmul、bmm 都可实现 矩阵乘法。
2.例子
import torch
a = torch.rand((2,3,5))
b = torch.rand((2,2,5))
a
Out[6]:
tensor([[[0.6171, 0.4499, 0.1373, 0.8756, 0.1020],
[0.2728, 0.3179, 0.6932, 0.6209, 0.4951],
[0.5625, 0.9915, 0.7839, 0.6911, 0.8923]],
[[0.1649, 0.5676, 0.9854, 0.9652, 0.5538],
[0.1092, 0.1581, 0.5181, 0.2075, 0.3936],
[0.7013, 0.8210, 0.4233, 0.5804, 0.7319]]])
b
Out[8]:
tensor([[[0.6307, 0.2868, 0.1641, 0.7782, 0.5756],
[0.4989, 0.2141, 0.5136, 0.7803, 0.4585]],
[[0.6401, 0.0145, 0.9513, 0.2657, 0.9430],
[0.9943, 0.0030, 0.2987, 0.8750, 0.8087]]])
res1 = torch.matmul(a,b.transpose(1,2))
res2 = torch.bmm(a,b.transpose(1,2))
res1.size()
Out[16]: torch.Size([2, 3, 2])
res2.size()
Out[17]: torch.Size([2, 3, 2])
res1
Out[14]:
tensor([[[1.2810, 1.2048],
[1.1452, 1.2717],
[1.8193, 1.8440]],
[[1.8298, 1.7524],
[0.9913, 0.7636],
[1.7079, 1.9259]]])
res2
Out[15]:
tensor([[[1.2810, 1.2048],
[1.1452, 1.2717],
[1.8193, 1.8440]],
[[1.8298, 1.7524],
[0.9913, 0.7636],
[1.7079, 1.9259]]])
9.读取图片、保存图片
1.读取图片
import numpy
from PIL import Image
import os
#创建一个118x73x3包含随机数字的Ndarray对象,数组中元素的类型为uint8
data = numpy.empty((118,73 , 3), dtype="uint8")
#指定读取的文件夹,把该目录下所有图片文件构建为一个列表,读取的图片也是 118x73x3
imgs = os.listdir("E:\\photo")
#统计该文件夹下的图片数量
num = len(imgs)
for i in range(num):
#目的读取每个图片数据
img = Image.open("E:\\photo\\"+imgs[i])
#numpy.array和numpy.asarray都能把结构化数据(如数组)构建为一个Ndarray对象。
arr = numpy.asarray(img, dtype="uint8")
img.show()
#数组数据进行可视化
img1 = Image.fromarray(arr).convert('RGB')
img1.show()
#转置三维数组,把三维数组默认的0,1,2对应的x,y,z轴 转置为 2,1,0对应的z,y,x轴
convertARR=arr.transpose(2,1,0)
#取第一层,即取三维数组中一级索引为0的二维数组
img2=Image.fromarray(convertARR[0])
img2.show()
2.使用scipy.misc
from PIL import Image
import numpy
from scipy import misc
import imageio
image = Image.open("E:\\0_train.jpg") # 首先在该py文件所在目录下随便放一张图片,使用PIL.Image库的open方法打开
image_array = numpy.array(image) # 使用numpy将该图片的二进制数据转换成多维数组形式
print(image_array)
# imsave 在scipy 1.0.0中已弃用,将在1.2.0中删除
# misc.imsave('E:\\out.jpg', image_array) # 使用misc.imsave方法将数组保存为图片
imageio.imwrite('E:\\out.jpg', image_array)
3.使用PIL库
from PIL import Image
import numpy
im = Image.open("E:\\0_train.jpg") # 打开图片
# 使用PIL库和numpy 只是为了快速得到一个可以用于保存为图片的数组,即从现有的图片直接转换成数组
im_array = numpy.array(im) # 将图片转化为numpy数组
print(im_array)
img = Image.fromarray(im_array).convert('RGB') # 将数组转化回图片
img.save("E:\\out.jpg") # 将数组保存为图片
4.使用matplotlib库
注意:这种方式生成的图片默认是带坐标轴的,并且四周带有空白。你可以使用 matplotlib.pyplot中相关方法隐藏坐标轴。
from PIL import Image
import numpy
import matplotlib.pyplot as plt
im = Image.open("E:\\0_train.jpg") # 打开图片
im_array = numpy.array(im) # 将图片转化为numpy数组
print(im_array)
#注意:imshow和savefig必须同一步一起执行才能存储带坐标轴的并且四周带有空白的图片,如果这两个方法分开两次执行的话,只会存储一张白色图片
plt.imshow(im_array) # 绘制图片,绘制出的图片带坐标
plt.savefig("E:\\out.jpg") # 保存图片
5.使用opencv库
from PIL import Image
import numpy
import cv2
img = cv2.imread('E:\\0_train.jpg') # 打开图片
img_array = numpy.array(img) # 将图片转化为numpy数组
#注意:imshow显示图片的同时必须执行waitKey,才能正常显示图片
cv2.imshow('img',img) #显示图片
cv2.waitKey(0)
cv2.imwrite("E:\\out.jpg", img_array) # 保存图片
10.Conv2d
1.torch.nn.Conv2d(in_channels,out_channels,kernel_size,stride=1,padding=0,dilation=1,groups=1,bias=True)
将两个4维的向量input(样本数据矩阵)和filter(卷积核)做卷积运算,输出卷积后的矩阵
2.参数解释:
1.in_channels:输入维度为 [batch_size, in_channels, in_height, in_width]
out_channels:输出维度为 [batch_size, out_channels, out_height, out_width]
batch_size:样本的数量
channels:每个样本的channels通道数,RGB图像的channels通道数是3
in_channels:输入的通道数
out_channels:输出的通道数
height:每个样本的行数
width:每个样本的列数
in_height:输入的每个样本的行数
in_width:输入的每个样本的列数
out_height:输出的每个样本的行数
out_width:输出的每个样本的列数
2.kernel_size:卷积核大小为[filter_height, filter_width, in_channels, out_channels]
filter_height:卷积核的高,即行数
filter_width:卷积核的宽,即列数
in_channels:输入通道数
out_channels:输出通道数
比如第一层卷积核大小为 5*5,输入通道数是3,输出通道数是64,即这一层输出64个特征
比如第二层卷积核大小依然是5*5,输入则是64个通道即上一层的输出,输出通道数是64,即这一层输出64个特征
3.stride:步长,即卷积核每次移动的步长。
4.padding:每一维补零的数量。填充模式取值,只能为SAME或VALID。
卷积或池化后的节点数计算公式:output_w = int((input_w + 2*padding - filter_w)/strid_w) + 1
5.dilation:kernel间距,控制 kernel 点之间的空间距离。带孔卷积(atrous conv)
6.groups:控制 inputs 和 outputs 间的关联性(分组). 其中,要求 in_channels 和 out_channels 必须都可以被 groups 整除
3.卷积层原理
卷积层是用一个固定大小的矩形区去席卷原始数据,将原始数据分成一个个和卷积核大小相同的小块,然后将这些小块和卷积核相乘输出一个卷积值,
注意这里是一个单独的值,不再是矩阵了。卷积的本质就是用卷积核的参数来提取原始数据的特征,通过矩阵点乘的运算,提取出和卷积核特征一致的值,
如果卷积层有多个卷积核,则神经网络会自动学习卷积核的参数值,使得每个卷积核代表一个特征。
4.conv1d是一维卷积:只对宽度进行卷积。conv2d是二维卷积:对宽度和高度进行卷积。
conv1d 函数定义:torch.nn.functional.conv1d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1)
参数说明:
input:输入的Tensor数据为三维数组,格式为(batch, channels, W),第一维度是样本数量,第二维度是通道数或者记录数,第一维度是宽度。
weight:卷积核权重,也就是卷积核本身,是一个三维数组,(out_channels, in_channels/groups, kW)。
out_channels 是卷积核输出层的神经元个数,也就是这层有多少个卷积核;in_channels是输入通道数;kW是卷积核的宽度。
bias:位移参数,可选项,一般也不用管
stride:滑动窗口,默认为1,指每次卷积对原数据滑动1个单元格
padding:是否对输入数据填充0。Padding可以将输入数据的区域改造成是卷积核大小的整数倍,这样对不满足卷积核大小的部分数据就不会忽略了。
通过padding参数指定填充区域的高度和宽度,默认0(填充区域为0,不填充)。
dilation:卷积核之间的空格,默认1
groups:将输入数据分组,通常不用管这个参数
5.conv1d示例
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
print("conv1d sample")
a=range(16)
x = Variable(torch.Tensor(a))
x=x.view(1,1,16)
print("x variable:", x)
b=torch.ones(3)
b[0]=0.1
b[1]=0.2
b[2]=0.3
weights = Variable(b) #torch.randn(1,1,2,2)) #out_channel*in_channel*H*W
weights=weights.view(1,1,3)
print ("weights:",weights)
y=F.conv1d(x, weights, padding=0)
print ("y:",y)
输出结果为:
conv1d sample
x variable: tensor([[[ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15.]]])
weights: tensor([[[ 0.1000, 0.2000, 0.3000]]])
y: tensor([[[ 0.8000, 1.4000, 2.0000, 2.6000, 3.2000, 3.8000, 4.4000, 5.0000, 5.6000, 6.2000, 6.8000, 7.4000, 8.0000, 8.6000]]])
它是怎么计算的:
(1)原始数据大小是0-15的一共16个数字,卷积核宽度是3,向量是[0.1, 0.2, 0.3]. 第一个卷积是对 x[0:3] 共3个值 [0,1,2] 进行卷积,
公式如下:0x0.1+1x0.2+2x0.3=0.8
(2)对第二个目标卷积,是 x[1:4 ]共3个值 [1,2,3] 进行卷积,公式如下:1x0.1+2x0.2+3x0.3=1.4
看到和计算结果完全一致.
conv1d 示意图如下:conv1d 和 conv2d 的区别就是只对宽度卷积,不对高度卷积. 最后的结果的宽度是原始数据的宽度减去卷积核的宽度再加上1,这里就是14。