数据操作:
0-d:标量,可表示一个类别
1-d:向量,可表示一个特征向量(把样本抽象成一行数字)
2-d:矩阵,可表示样本的特征矩阵,比如一个三行三列的矩阵,每一行表示一个样本,每一列表示不同的特征
3-d:可表示RGB图片(宽x高x通道),宽即为列数,高为行数,通道即为RGB三个通道。
4-d:可表示一个RGB图片的批量(批量大小x宽x高x通道)
5-d:可表示一个视频批量(批量大小x时间x宽x高x通道)
由此可见,维度越高,我们能表示的数据的信息就越多。
[::3, ::2]
::3表示每3行一跳,::2表示每2列一跳
数据操作实现:
1.张量表示一个数值组成的数组,这个数组可能有多个维度
2.要改变一个张量的形状而不改变元素数量和元素值,可以调用reshape函数
import torch
x = torch.arange(12)
X = x.reshape(3, 4)
print(X)
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
3.使用全0、全1、其他常量或者从特定分布中随机采样的数字
torch.zeros((2, 3, 4))
torch.ones((2, 3, 4))
4.通过提供包含数值的Python列表(或嵌套列表)来为所需张量中的每个元素赋予确定值
torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
5.常见的标准算数运算符(+、-、*、/和**)都可以升级为按元素运算
import torch
# 1.0 表示该数组元素为浮点数,运算为浮点运算
x = torch.tensor([1.0, 2, 4, 8])
y = torch.tensor([2, 2, 2, 2])
print(x + y, x - y, x * y)
# ** 运算符是求幂运算
print(x / y, x ** y)
print(torch.exp(x))
tensor([ 3., 4., 6., 10.]) tensor([-1., 0., 2., 6.]) tensor([ 2., 4., 8., 16.])
tensor([0.5000, 1.0000, 2.0000, 4.0000]) tensor([ 1., 4., 16., 64.])
tensor([2.7183e+00, 7.3891e+00, 5.4598e+01, 2.9810e+03])
6.可以把多个张量连结在一起
import torch
X = torch.arange(12, dtype=torch.float32).reshape((3, 4))
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
# 在第0维合并,即按行合并
print(torch.cat((X, Y), dim=0))
# dim=1,按列合并
print(torch.cat((X, Y), dim=1))
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[ 2., 1., 4., 3.],
[ 1., 2., 3., 4.],
[ 4., 3., 2., 1.]])
tensor([[ 0., 1., 2., 3., 2., 1., 4., 3.],
[ 4., 5., 6., 7., 1., 2., 3., 4.],
[ 8., 9., 10., 11., 4., 3., 2., 1.]])
import torch
X = torch.arange(12).reshape((2, 3, 2))
Y = torch.tensor([[[1, 2], [3, 4], [5, 6]], [[6, 5], [4, 3], [2, 1]]])
print(X)
print(Y)
print(torch.cat((X, Y), dim=2))
tensor([[[ 0, 1],
[ 2, 3],
[ 4, 5]],
[[ 6, 7],
[ 8, 9],
[10, 11]]])
tensor([[[1, 2],
[3, 4],
[5, 6]],
[[6, 5],
[4, 3],
[2, 1]]])
tensor([[[ 0, 1, 1, 2],
[ 2, 3, 3, 4],
[ 4, 5, 5, 6]],
[[ 6, 7, 6, 5],
[ 8, 9, 4, 3],
[10, 11, 2, 1]]])
7.通过逻辑运算符构建二维张量
import torch
X = torch.arange(12, dtype=torch.float32).reshape((3, 4))
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
print(X == Y)
tensor([[False, True, False, True],
[False, False, False, False],
[False, False, False, False]])
8.对张量中的所有元素进行求和会产生一个只有一个元素的张量
import torch
X = torch.arange(12, dtype=torch.float32).reshape((3, 4))
print(X.sum())
tensor(66.)
9.即使形状不同,仍然可以通过广播机制(broadcasting mechanism)来执行按元素操作
import torch
# 维度的数量一样的情况下
a = torch.arange(3).reshape((3, 1))
b = torch.arange(2).reshape((1, 2))
print(a)
print(b)
# 广播机制会把a复制成3 * 2的矩阵,把b复制成3 * 2的矩阵,之后再相加
print(a + b)
tensor([[0],
[1],
[2]])
tensor([[0, 1]])
tensor([[0, 1],
[1, 2],
[2, 3]])
10.可以用[-1]选择最后一行元素,用[1:3]选择第一行和第二行元素
11.除读取外,还可以通过指定索引来将元素写入矩阵
X[1, 2] = 9
12.为多个元素赋值相同的值,我们只需要索引所有元素,然后为它们赋值
X[0:2, :] = 12
13.运行一些操作可能会导致为新结果分配内存(尽量少地对很大的矩阵进行不断的复制操作)
# id可以认为是C++中指针一样的东西, id表示object在python中的唯一标识号
before = id(Y)
Y = Y + X
id(Y) == before
Output:
False
执行原地操作
Z = torch.zeros_like(Y)
print('id(Z):', id(Z))
# 对Z的元素进行一次改写
Z[:] = X + Y
print('id(Z):', id(Z))
如果在后续计算中没有重复使用X,也可以使用X[:] = X + Y或X += Y来减少操作的内存开销
14.转换为NumPy张量
A = X.numpy()
B = torch.tensor(A)
type(A), type(B)
Output:
(numpy.ndarray, torch.Tensor)
将大小为1的张量转换为Python标量
a = torch.tensor([3.5])
a, a.item(), float(a), int(a)
Output:
(tensor([3.5000]), 3.5, 3.5, 3)
数据预处理:
如果有原始数据,如何将其读取进来使得我们能够通过机器学习的方法处理。
import os
import pandas as pd
os.makedirs(os.path.join('..', 'data'), exist_ok=True)
data_file = os.path.join('..', 'data', 'house_tiny.csv')
with open(data_file, 'w') as f:
f.write('NumRooms,Alley,Price\n') # 列名
f.write('NA,Pave,127500\n') # 每行表示一个数据样本
f.write('2,NA,10600\n')
f.write('4,NA,178100\n')
f.write('NA,NA,140000\n')
data = pd.read_csv(data_file)
print(data)
NumRooms Alley Price
0 NaN Pave 127500
1 2.0 NaN 10600
2 4.0 NaN 178100
3 NaN NaN 140000
为了处理缺失的数据,典型的方法包括插值和删除,这里我们考虑插值
# iloc: index location
inputs, outputs = data.iloc[:, 0:2], data.iloc[:, 2]
inputs = inputs.fillna(inputs.mean())
print(inputs)
NumRooms Alley
0 3.0 Pave
1 2.0 NaN
2 4.0 NaN
3 3.0 NaN
对于inputs中的类别值或离散值,我们将"NaN"视为一个类别
inputs = pd.get_dummies(inputs, dummy_na=True)
print(inputs)
NumRooms Alley_Pave Alley_nan
0 3.0 1 0
1 2.0 0 1
2 4.0 0 1
3 3.0 0 1
现在inputs和outputs中的所有条目都是数值类型,它们可以转换为张量格式
import torch
X, y = torch.tensor(inputs.values), torch.tensor(outputs.values)
print(X)
print(y)
tensor([[3., 1., 0.],
[2., 0., 1.],
[4., 0., 1.],
[3., 0., 1.]], dtype=torch.float64)
# 传统的python一般默认浮点数为float64,但64位浮点数一般计算比较慢,深度学习一般采用32位浮点数
tensor([127500, 10600, 178100, 140000])