目录
一、张量基本概念
张量是一个多维数组,是标量、向量、矩阵的高维拓展
Tensor(张量)类似于NumPy的ndarray,但还可以在GPU上使用来加速计算。
二、Tensor
2.1 Variable
Variable是torch.autograd中的数据类型,主要用于Tensor封装,进行自动求导。
Variable的5个属性:
1. data:被包装的Tensor
2. grad:data的梯度
3. grad_fn:创建Tensor的Function,是自动求导的关键
4. requires:指示是否需要梯度
5. is_leaf:指示是否是叶子
2.2.Tensor
Pytorch0.4.0及以后版本已将Variable并入Tensor
当前Tensor具有8个属性,除了并入的Variable 5个属性之外,另外3个是:
dtype:张量的数据类型
shape:张量的形状
device:张量所在设备,cup/gpu,是加速的关键
三、张量的创建
3.1 直接创建
torch.tensor(data) #data可以是list、numpy
arr = np.ones((3, 3))
print("arr数据类型:", arr.dtype)
# t = torch.tensor(arr, device='cuda')
t = torch.tensor(arr)
print(t)
torch.from_numpy(arr) #从numpy创建tensor,这种方法创建的tensor与原ndarray共享内存。
arr = np.array([[1, 2, 3], [4, 5, 6]])
print("arr数据类型:", arr.dtype)
# t = torch.tensor(arr, device='cuda')
t = torch.from_numpy(arr)
print(t)
3.2 依据数值创建
torch.zeros(size,out) #size是张量形状,如(3,3);out是输出的张量
out_t = torch.tensor([1])
t = torch.zeros((3, 3), out=out_t) #out用来接收全0张量, 类似赋值操作
print(t, '\n', out_t)
print(id(t), id(out_t), id(t) == id(out_t))
torch.zeros_like(input)
torch.ones(size)
torch.full(size, value) #创建全为value的张量
torch.arange(start,end,step) #创建等差的1维张量
torch.linspace(start, end, steps) #均分数,从start到end取steps个数
torch.logspace(start, end, steps, base) #创建对数均分的1维张量,base为对数的底,默认10
torch.eye(n) #创建对角矩阵,对角为1
3.3 依据概率分布创建张量
torch.normal(mean, std) #生成正太分布(高斯分布)。mean: 均值 , std:标准差
torch.normal(mean, std) 具有四种模式
- mean为标量,std为标量
- mean为标量,std为张量
- mean为张量,std为标量
- mean为张量,std为张量
# mean为标量,std为张量
mean = 1
std = torch.arange(1, 5, dtype=torch.float)
t_normal = torch.normal(mean, std)
mean, std, t_normal
torch.randn() #生成标准正太分布 mean=0,std=1
torch.randn_like()
torch.rand() #0,1均匀分布
torch.rand_like()
torch.randint() #[low, hight)生成均匀分布
torch.randperm #生成从0到n-1的随机排列
torch.bernoulli() #以input为概率,生成伯努利分布(0,1分布)
四、张量操作
4.1 张量拼接与切分
torch.cat(tensors,dim) #将张量按维度dim进行拼接
t = torch.ones((2, 3))
t_0 = torch.cat([t, t], dim=0)
t_1 = torch.cat([t, t, t], dim=1)
print("t_0:{} shape:{}\nt_1:{} shape:{}".format(t_0, t_0.shape, t_1, t_1.shape))
输出:
t_0:tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]]) shape:torch.Size([4, 3])
t_1:tensor([[1., 1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1., 1.]]) shape:torch.Size([2, 9])
torch.stack(tensors,dim) #在新创建的维度dim上进行拼接
torch.chunk(input, chunks, dim) #将张量按维度dim平均切分为chunks份,若不能整除,最后一个张量小于其他张量
torch.split(tensor, split_size_or_sections, dim) #split_size_or_sections为int时,表示每一份长度;为list时,按list元素切分
4.2 张量索引
torch.index_select(input, dim, index) #在维度dim上,按index索引数据
t = torch.randint(0, 9, size=(3, 3))
idx = torch.tensor([0, 2], dtype=torch.long) # float
t_select = torch.index_select(t, dim=0, index=idx)
print("t:\n{}\nt_select:\n{}".format(t, t_select))
输出:
t:
tensor([[5, 3, 0],
[0, 4, 7],
[7, 8, 3]])
t_select:
tensor([[5, 3, 0],
[7, 8, 3]])
torch.masked_select(input,mask) #按mask中的True进行索引,返回值是一维张量
4.3 张量变换
torch.reshape(input, shape) #变化张量形状
torch.transpose(input, dim0, dim1) #交换张量维度
torch.t() #二维张量转置
torch.squeeze(input, dim) #压缩长度为1的维度
torch.unsqueeze(input, dim) #依据dim扩展维度
五、张量的数学运算
torch.add(input, alpha, other) #input+alpha*other #input第一个张量,alpha乘项因子,other第二个张量
torch.addcdiv()
torch.addcmul()
torch.sub()
torch.div()
torch.mul()
torch.log()
torch.exp()
torch.pow()
torch.abs()
torch.cos()
t_0 = torch.randn((3, 3))
t_1 = torch.ones_like(t_0)
t_add = torch.add(t_0, 10, t_1)
print("t_0:\n{}\nt_1:\n{}\nt_add_10:\n{}".format(t_0, t_1, t_add))
输出:
t_0:
tensor([[-0.8489, -1.0848, 1.0664],
[ 0.6338, 1.5542, -0.3933],
[ 0.2490, -0.1785, 0.1496]])
t_1:
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
t_add_10:
tensor([[ 9.1511, 8.9152, 11.0664],
[10.6338, 11.5542, 9.6067],
[10.2490, 9.8215, 10.1496]])
Process finished with exit code 0
六、线性回归
线性回归是分析一个变量与另外一(多)个变量之间关系的方法。
求解步骤:
1. 确定模型
Model: y = wx + b
2. 选择损失函数
MSE:
3. 求解梯度并更新 w、b
w = w - LR * w.grad (LR是步长,也称为学习率)
b = b - LR * w.grad
import torch
import matplotlib.pyplot as plt
torch.manual_seed(10)
lr = 0.05 # 学习率 20191015修改
# 创建训练数据
x = torch.rand(20, 1) * 10 # x data (tensor), shape=(20, 1)
y = 2*x + (5 + torch.randn(20, 1)) # y data (tensor), shape=(20, 1)
# 构建线性回归参数
w = torch.randn((1), requires_grad=True)
b = torch.zeros((1), requires_grad=True)
for iteration in range(1000):
# 前向传播
wx = torch.mul(w, x)
y_pred = torch.add(wx, b)
# 计算 MSE loss
loss = (0.5 * (y - y_pred) ** 2).mean()
# 反向传播
loss.backward()
# 更新参数
b.data.sub_(lr * b.grad)
w.data.sub_(lr * w.grad)
# 清零张量的梯度 20191015增加
w.grad.zero_()
b.grad.zero_()
# 绘图
if iteration % 20 == 0:
plt.scatter(x.data.numpy(), y.data.numpy())
plt.plot(x.data.numpy(), y_pred.data.numpy(), 'r-', lw=5)
plt.text(2, 20, 'Loss=%.4f' % loss.data.numpy(), fontdict={'size': 20, 'color': 'red'})
plt.xlim(1.5, 10)
plt.ylim(8, 28)
plt.title("Iteration: {}\nw: {} b: {}".format(iteration, w.data.numpy(), b.data.numpy()))
plt.pause(0.5)
if loss.data.numpy() < 1:
break