什么是张量?
三维以上的数组,在二维矩阵没法满足数据表示的时候就需要引入张量
Tensor与Variable
Variable是torch中的一种数据类型,主要用来封装张量,进行自动求导,该数据类型中的内容有:
data:被包装的向量
grad:data的梯度
grad_fn:用来创建张量的Function
requires_grad:指示是否需要梯度
is_leaf:指示是否是叶子节点
dtype:张量的数据类型
shape:张量的形状(如64,3,224,224)
device:张量所在设备,确定是在GPU还是CPU上
如何创建张量
一.直接创建
torch.tensor(
data,
dtype=None,
device=None,
requires_grad=False,
pin_memory=False)
"""功能:从data创建tensor
data:数据,可以是list,numpy
dtype:数据类型,默认与data的一致
device:所在设备,cuda/cpu
requires_grad:是否需要梯度
pin_memory:是否存于琐页内存"""
tensor = torch.from_numpy(arr)
"""从numpy创建tensor,这样创建的tensor和原数组属于共享内存,
修改其中一个,另一个也会被修改
*似乎使用np的操作对arr数组进行操作不会影响tensor的数组内容"""
二.依据数值创建
可以创建全0,全1,均分,等差数列,等比数列等
torch.zeros(
*size,
out=None,
dtype=None,
layout=troch.strided,
device=None,
requires_grad=False)
"""功能,依据size创建全0张量
size:张量的形状,如(3,3)
out:输出的张量(也就是赋值)
layout:内存中布局形式,有strided,sparse_coo等
device:所在设备,gpu/cpu
requires_grad:是否需要梯度"""
torch.zeros_like(
*input,
dtype=None,
layout=troch.strided,
device=None,
requires_grad=False)
torch.ones(
*size,
out=None,
dtype=None,
layout=troch.strided,
device=None,
requires_grad=False)
torch.ones_like(
*input,
dtype=None,
layout=troch.strided,
device=None,
requires_grad=False)
"""功能:依据input形状创建全0张量
input:创建与input形状相同的全0的张量
dtype:数据类型
layout:内存中的布局形式
requires_grad:是否需要梯度
device:所在设备"""
torch.full(
size,
fill_value,
out=None,
dtype=None,
layout=troch.strided,
device=None,
requires_grad=False)
torch.full_like(
*input,
fill_value,
dtype=None,
layout=troch.strided,
device=None,
requires_grad=False)
"""功能:依据input形状创建全0张量
size:张量的形状
fill_value:张量的值"""
torch.arange(start=0,end,step=1,
out=None,
dtype=None,
layout=troch.strided,
device=None,
requires_grad=False)
"""功能:创建等差数列的一维张量,数列起始区间为[start,end)
strat:数列起始值
end:数列结束值
step:数列公差,默认为1"""
torch.linspace(
start,
end,
steps=100,
out=None,
dtype=None,
layout=troch.strided,
device=None,
requires_grad=False
)
"""功能:创建均分的一维张量(也就是按step对start和end进行均分),数列起始区间为[start,end]
strat:数列起始值
end:数列结束值
steps:数列长度,默认为1"""
torch.logspace(
start,
end,
steps=100,
base=10.0,
out=None,
dtype=None,
layout=troch.strided,
device=None,
requires_grad=False
)
"""功能:创建均分的一维张量(也就是按step对start和end进行均分),
数列起始区间为[start,end],底为base,
strat:数列起始值
end:数列结束值
steps:数列长度,默认为1
base:对数函数的底,默认为10"""
torch.eye(
n,
m=None,
out=None,
dtype=None,
layout=troch.strided,
device=None,
requires_grad=False
)
"""功能:创建单位对角矩阵(2维),默认为方阵
n:矩阵行数
m:矩阵列数
"""
三.依据概率创建
torch.normal(mean,
std,
out=None)
"""mean=均值,std=标准差
一共按照均值与标准差是否是张量或者标量,有四种模式
mean为张量,std为张量:按照对应行和列来赋值均值和方差
mean为标量,std为标量:正常操作,注意需要添加size操作来确定大小
mean或者std其中一个为张量,另一个为标量:按照张量的位置取固定的另一个值来赋值
"""
torch.randn(*size)
"""标准正态分布,size=形状"""
torch.randperm(n)
"""0-n的随机排列,n是大小"""
torch.bernoulli(input,generator=None,out=None)
"""0-1分布,input为概率"""
张量的操作与线性回归
一.张量的拼接和切分
torch.cat(tensors,
dim=0,
out=None)
"""功能,将张量按维度dim进行拼接
`tensors:张量序列
`dim:维度"""
torch.stack(tensors,
dim =0,
out = None)
"""二者的区别是,cat是直接在原张量上拼接,stack是会新建一个维度,然后构建新的张量"""
torch.chunk(input,chunks,dim=0)
"""将张量按维度dim进行平均切分,返回值是一个张量的列表.
若不能整除,则最后一份张量小于其他张量(向上取整).
input:要切分的张量
chunks:要切分的份数
dim:要切分的维数"""
torch.split(tensor,
split_size_or_sections,
dim=0)
"""更为强大的切分,split_size_or_sections为int时,表示每一份的长度,
为list时,按list元素切分(比如一个(2,3)的矩阵按[1,2]切分,就会变成一个(2,1)的矩阵和一个(2,2)的矩阵)"""
torch.index_select(
input,
dim,
index,
out=None)
"""在dim维度上按index索引数据,返回值是依照index索引数据拼接的张量"""
torch.masked_select(
input,
mask,
out=None)
"""按mask中的True进行索引,返回值:<<一维张量>>; mask:与input同形状的布尔类型张量(相当于一个遮罩))
*Tensor.ge(int) 这个函数可以用来生成一个mask,是指当张量Tensor中对应位置的数值大于等于int时,将在新生成的mask的对应位置置为True,否则为False;
同样有Tensor.gt(int) 这个不包括等于
二.张量变换
torch.reshape(input,shape)
"""变换张量形状,就是按行优先重新分配元素来符合新的形状,所以m*n一定要一直等于元素数;注意:当张量在内存中是连续时,新张量与input<<共享数据内存>>
*shape里可以使用参数-1,表示动态改变对应的维度值"""
torch.transpose(input,dim0,dim1)
"""交换张量的两个维度
*注意:张量的dim,是从最高向最低从左往右算的,
比如dim0,在3维的张量里表示三个二维张量,并不是从行开始然后是列然后是矩阵个数,这样的想法是错的"""
torch.t(input)
"""二维张量转置"""
torch.squeeze(input,
dim=None,
out=None)
"""压缩长度为1的维度,(轴);
dim若为None,移除所有长度为1的轴;若指定维度,则仅当该轴长度为1时移除"""
torch.usqueeze(input,
dim,
out=None)
"""根据dim扩展维度"""
三.张量数学运算
"""加减乘除运算:"""
torch.add(input,alpha=1,other,out=None) #alpha为乘项因子,也就是权重input+alpha*other
torch.addcdiv(input,value=1,tensor1,tensor2) #addcdiv和addcmul分别指input_i+value*
torch.addcmul(input,value=1,tensor1,tensor2) #(tensor1_i/tensor2_i)和
#input_i+value*tensor1_i*tensor2_i
torch.sub()
torch.div()
torch.mul()
"""对指幂:"""
torch.log(input)
torch.log10(input)
torch.log2(input)
torch.exp(input)
torch.pow()
"""三角函数"""
torch.abs(input)
torch.acos(input)
torch.cosh(input)
torch.cos(input)
torch.asin(input)
torch.atan(input)
torch.atan2(input,other)
四.线性回归
求解步骤:
1.确定模型 y=wx+b
2.选择顺势函数 均方差
3.求解梯度并更新w,b w=w-LR(Learn rate)*w.grad;b同理
import matplotlib.pyplot as plt
import torch
lr = 0.01 # 学习率
# 创建训练数据
x = torch.rand((20, 1)) * 10 # 创建x的data
y = 2 * x + (5 + torch.rand(20, 1)) # 创建斜率为2,斜矩为5的因变量y,同时增加噪声rand
# 创建参数
w = torch.rand(1, requires_grad=True)
b = torch.zeros(1, requires_grad=True)
min_loss = 0.2
for iteration in range(500000):
# 前向传播
wx = torch.mul(w, x)
y_hat = torch.add(wx, b)
# 计算损失函数
loss = (0.5 * (y - y_hat) ** 2).mean()
# 反向传播
loss.backward()
# 更新参数
b.data.sub_(lr * b.grad)
w.data.sub_(lr * w.grad)
# 输出最小loss的参数
if loss.data.numpy() < min_loss:
min_loss = loss.data.numpy()
print('iteration{},loss{},w{},b{}'.format(iteration,
loss.data.numpy(),w.item(),b.item()))
print('DONE')