1-1数据操作
数据操作
为了能够完成各种数据操作,我们需要某种方法来存储和操作数据。 通常,我们需要做两件重要的事:(1)获取数据;(2)将数据读入计算机后对其进行处理。 如果没有某种方法来存储数据,那么获取数据是没有意义的。
n维数组,也称为张量(tensor)。
入门
张量表示一个由数值组成的数组,这个数组可能有多个维度。
张量中的每个值都称为张量的元素
###使用arange创建一个行向量x
import torch
x = torch.arange(12)
print(x)
----
tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
通过张量的shape属性来访问张量(沿每个轴的长度)的形状
import torch
x = torch.arange(12)
print(x)
print(x.shape)
-----
torch.Size([12])
###如果只想知道张量中元素的总数,即形状的所有元素乘积,可以检查它的大小(size)。 因为这里在处理的是一个向量,所以它的shape与它的size相同。
import torch
x = torch.arange(12)
print(x)
print(x.numel())
----
12
要想改变一个张量的形状而不改变元素数量和元素值,可以调用reshape函数。
###把张量x从形状为(12,)的行向量转换为形状为(3,4)的矩阵。
###这个新的张量包含与转换前相同的值,但是它被看成一个3行4列的矩阵。
###注意,通过改变张量的形状,张量的大小不会改变。
import torch
x = torch.arange(12)
y = x.reshape(3,4)
print(y)
---
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
###可以通过-1来调用此自动计算出维度的功能。
import torch
x = torch.arange(12)
y = x.reshape(-1,4)
z = x.reshape(3,-1)
print(y)
print(z)
----
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
###创建2个 全0的 3行4列 张量(2,3,4)
import torch
x = torch.zeros((2,3,4))
print(x)
----
tensor([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
###创建一个形状为(2,3,4)的张量,其中所有元素都设置为1
import torch
x = torch.ones((2,3,4))
print(x)
----
tensor([[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]],
[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]]])
随机初始化参数的值。
###创建一个形状为(3,4)的张量。 其中的每个元素都从均值为0、标准差为1的标准高斯分布(正态分布)中随机采样。
import torch
x = torch.randn((3,4))
print(x)
-----
tensor([[-0.6214, 1.1524, 0.4670, -0.5937],
[-0.5564, -0.4070, -0.1200, -0.6310],
[-0.4874, -0.4785, -0.9500, -0.3867]])
###通过提供包含数值的Python列表(或嵌套列表),来为所需张量中的每个元素赋予确定值。
import torch
x = torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
print(x)
----
tensor([[2, 1, 4, 3],
[1, 2, 3, 4],
[4, 3, 2, 1]])
运算符
###对于任意具有相同形状的张量, 常见的标准算术运算符(+、-、*、/和**)都可以被升级为按元素运算。
###可以在同一形状的任意两个张量上调用按元素操作。
import torch
x = torch.tensor([1.0, 2, 4, 8])
y = torch.tensor([2, 2, 2, 2])
print(x+y)
print(x-y ,x*y,x/y,x**y)
-----
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.])
###可以把多个张量连结(concatenate)在一起, 把它们端对端地叠起来形成一个更大的张量。
###只需要提供张量列表,并给出沿哪个轴连结。
###沿行(轴-0,形状的第一个元素) 和按列(轴-1,形状的第二个元素)连结两个矩阵
###第一个输出张量的轴-0长度(6)是两个输入张量轴-0长度的总和(3+3)3行+3行
###第二个输出张量的轴-1长度(8)是两个输入张量轴-1长度的总和(4+4) 4行+4行
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(torch.cat((X, Y), dim=0))
print(torch.cat((X, Y), dim=1))
----
tensor([[ 0., 1., 2., 3.], ###X的值
[ 4., 5., 6., 7.], ###X的值
[ 8., 9., 10., 11.], ###X的值
[ 2., 1., 4., 3.], ###Y的值
[ 1., 2., 3., 4.], ###Y的值
[ 4., 3., 2., 1.]]) ###Y的值
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.]])
###X的值 ###Y的值
###通过逻辑运算符构建二元张量
####若X和Y在该位置相等,则新张量中相应项的值为1,为真 否则为0
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]])
###对张量中的所有元素进行求和,会产生一个单元素张量。
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.sum())
----
tensor(66.)
广播机制
在某些情况下,即使形状不同,我们仍然可以通过调用 广播机制(broadcasting mechanism)来执行按元素操作。
工作方式
- 通过适当复制元素来扩展一个或两个数组,以便在转换之后,两个张量具有相同的形状;
- 对生成的数组执行按元素操作。
import torch
a = torch.arange(3).reshape((3, 1))
b = torch.arange(2).reshape((1, 2))
print(a)
print(b)
print(a + b)
---
tensor([[0],
[1],
[2]])
tensor([[0, 1]])
tensor([[0, 1],
[1, 2],
[2, 3]])
###由于a和b分别是3x1和1x2矩阵,如果让它们相加,它们的形状不匹配。 我们将两个矩阵广播为一个更大的3x2矩阵,
###矩阵a将复制列, 矩阵b将复制行,然后再按元素相加。
tensor([[0,0],
[1,1],
[2,2]])
tensor([[0, 1],
[0, 1],
[0, 1]])
索片和切片
张量中的元素也可以通过索引访问。
import torch
X = torch.arange(12, dtype=torch.float32).reshape((3,4))
print(X)
print("索引访问:")
print(X[-1]) ##选取最后一个元素
print(X[1:3]) ##选择第二个和第三个元素
---
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]])
索引访问:
tensor([ 8., 9., 10., 11.])
tensor([[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]])
指定索引来将元素写入矩阵
import torch
X = torch.arange(12, dtype=torch.float32).reshape((3,4))
print(X)
print("更改:")
X[1,2] = 9
print(X)
----
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]])
更改:
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 9., 7.],
[ 8., 9., 10., 11.]])
###如果我们想为多个元素赋值相同的值,我们只需要索引所有元素,然后为它们赋值
###[0:2, :]访问第1行和第2行,其中“:”代表沿轴1(列)的所有元素。
import torch
X = torch.arange(12, dtype=torch.float32).reshape((3,4))
print(X)
print("更改:")
X[0:2,:] = 12
print(X)
----
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]])
更改:
tensor([[12., 12., 12., 12.],
[12., 12., 12., 12.],
[ 8., 9., 10., 11.]])
转换为其他Python对象
### torch张量和numpy数组将共享它们的底层内存,就地操作更改一个张量也会同时更改另一个张量。
import torch
X = torch.arange(12, dtype=torch.float32).reshape((3,4))
A = X.numpy()
B = torch.tensor(A)
print(type(A))
print(type(B))
----
<class 'numpy.ndarray'>
<class 'torch.Tensor'>
将大小为1的张量转换为Python标量,我们可以调用item函数或Python的内置函数。
import torch
a = torch.tensor([3.5])
print(a)
print(a.item())
print(float(a))
print(int(a))
----
tensor([3.5000])
3.5
3.5
3
深度学习存储和操作数据的主要接口是张量(n维数组)。它提供了各种功能,包括基本数学运算、广播、索引、切片、内存节省和转换其他Python对象。