Tensors
tensors(张量)时一个特殊的数据结构他和矩阵数组相似。在pytorch中使用tensor作为模型的输入,输出,参数。
1. 初始化Tensor
- 直接来自数据
- numpy转换
- 另一个tensor转换
- 随机值或常数
import torch
import numpy as np
# 直接来自数据
data = [[1,2],[3,4]]
x_data = torch.tensor(data)
# numpy转换
np_array = np.array(data)
x_np = torch.from_numpy(np_array)
# 来自另一个tensor
x_ones =torch.ones_like(x_data) #保留x_data的属性
x_rand = torch.rand_like(x_data, dtype=torch.float) #覆写x_data的dtype属性
print(f"全一Tensor: \n {x_ones} \n")
print(f"随机Tensor: \n {x_rand} \n")
输出:
# 随机数或者常数
shape = (2,3,) # shape是tensor的维度元组, 它决定了输出的tensor的维度
rand_tensor = torch.rand(shape) #随机tensor
ones_tensor = torch.ones(shape) #全一的tensor
zeros_tensor = torch.zeros(shape) #全0的tensor
print(f"Random Tensor: \n {rand_tensor} \n")
print(f"Ones Tensor: \n {ones_tensor} \n")
print(f"Zeros Tensor: \n {zeros_tensor}")
输出:
2. Tensor的属性
Tensor的属性描述的他们的形状,数据类型和存储设备(shape, dtype, device)
tensor = torch.rand(3,4)
print(f"Tensor的形状:{tensor.shape}")
print(f"tensor的数据类型:{tensor.dtype}")
print(f"tensor的存储在:{tensor.device}")
3. Tensor的操作
tensor的操作包括算术运算,线性代数运算,矩阵处理(转置,索引,切片),采样。具体可参考官网。
这些操作可以上GPU上运行(通常会比CPU快点),默认tensor是创建在cpu上,可以使用to(device)的方法把张量转移到gpu上。跨设备复制张量可能会浪费时间和内存。
# 如果需要把tensor转移到GPU上
device = "cuda" if torch.cuda.is_available() else "cpu" #检查是否有cuda
tensor.to(device)
索引和切片
tensor =torch.arange(0,16).view(4,4) #生成从0到15,4*4矩阵
print("原始数据:",tensor)
print('第一行: ',tensor[0])
print('第一列: ', tensor[:, 0])
print('最后一列:', tensor[..., -1])
tensor[:,1] = 0 # 第二列置0
print(tensor)
连接操作
使用tensor.cat()将tensor按照指定维度连接
t1 = torch.cat([tensor,tensor,tensor], dim=1) #列连接
print(t1)
算数操作
# 矩阵乘法,下列计算是等价得
y1 = tensor @ tensor.T
y2 = tensor.matmul(tensor.T)
y3 = torch.ones_like(tensor)
torch.matmul(tensor,tensor.T,out=y3)
print(f"y1: {y1}")
print(f"y2: {y2}")
print(f"y3: {y3}")
# 按元素相乘
z1 = tensor * tensor
z2 = tensor.mul(tensor)
z3 = torch.ones_like(tensor)
torch.mul(tensor, tensor, out=z3)
print(f"z1: {z1}")
print(f"z2: {z2}")
print(f"z3: {z3}")
就地操作(in-place operation)
将结果存储到操作数中得操作称为就地操作,他们通常形式如a_后缀,例如:x.copy_(y), x.t_(), 将会改变x
print(tensor,"\n")
tensor.add_(5)
print(tensor)
4. Tensor与numpy的转换
张量在CPU和NumPy数组上可以共享它们的底层内存位置,改变一个就会改变另一个。
# Tensor to Numpy
t = torch.ones(5)
print(f"t: {t}")
n = t.numpy()
print(f"n: {n}")
t.add_(1)
print(f"t: {t}")
print(f"n: {n}")
# Numpy to tensor
n = np.ones(5)
t = torch.from_numpy(n)
np.add(n, 1, out=n)
print(f"t: {t}")
print(f"n: {n}")
5. 小试牛刀:线性回归
线性回归是机器学习入门知识,应用十分广泛。线性回归利用数理统计中回归分析,
来确定两种或两种以上变量间相互依赖的定量关系的,其表达形式为
y
=
w
x
+
b
y = wx+b
y=wx+b
首先让我们来确认线性回归的损失函数:
l
o
s
s
=
∑
i
N
1
2
(
y
i
−
(
w
x
i
+
b
)
)
2
loss = \sum_i^N\frac{1}{2}(y_i-(wx_i+b))^2
loss=i∑N21(yi−(wxi+b))2
然后利用随机梯度下降法更新参数
w
\textbf{w}
w和
b
\textbf{b}
b来最小化损失函数,最终学得
w
\textbf{w}
w和
b
\textbf{b}
b的数值。
import torch as t
%matplotlib inline
from matplotlib import pyplot as plt
from IPython import display
# 设置随机数种子,保证每次输出的结果一致
t.manual_seed(1000)
def get_fake_data(batch_size):
'''随机产生: y = 2x+3,再加上一些噪声'''
x = t.rand(batch_size,1,device=device) * 5
y = x * 2 + 3 + torch.randn(batch_size,1, device=device)
return x,y
# 看看xy的分布
x, y = get_fake_data(100)
plt.scatter(x.squeeze().cpu().numpy(),y.squeeze().cpu().numpy())
# 随机初始化参数
w = t.rand(1,1).to(device)
b = t.zeros(1,1).to(device)
lr = 0.01 #学习率
for i in range(500):
x , y = get_fake_data(batch_size=4)
x, y = x.to(device),y.to(device)
# 1.前向计算
y_pred = torch.matmul(x,w) + b
# 2.计算损失
loss = 0.5 * (y_pred - y) ** 2 #均方误差
loss = loss.mean()
# 3.反向传播
dloss = 1
dy_pred = dloss * (y_pred-y)
dw = torch.matmul(x.t(), dy_pred) #dw = dl/d
db = dy_pred.sum()
# 更新参数
w = w - lr * dw
b = b - lr * db
if i % 50 ==0 :
# 画图
plt.cla()
display.clear_output(wait=True)
x = t.arange(0,6,dtype=t.float).view(-1,1).to(device)
y = torch.matmul(x, w) +b
plt.plot(x.cpu().numpy(), y.cpu().numpy(),'r-',lw=5) #画出预测结果
x3, y3 = get_fake_data(batch_size=32)
plt.scatter(x3.cpu().numpy(), y3.cpu().numpy()) # true data
plt.xlim(0, 5)
plt.ylim(0, 13)
plt.show()
plt.pause(0.5)
print("w:",w.item(),"b: ",b.item())