Pytorch基础-对张量的定义、运算和维度操作全解析(1)

一、什么是张量tensor?

张量是一种特殊的数据结构,与数组和矩阵非常相似。类似于Numpy 的ndarray。 在 PyTorch 中,我们使用张量对模型的输入和输出以及模型的参数进行编码。 张量都可以通过Numpy来定义、操作,通常存储在Nunpy数组,所以这就需要我们把数据转换为Numpy数组,目的就是把所有的输入数据转变为一个统一的标准,以便能够容易的处理。

张量是根据一共具有多少坐标轴来定义。比如可以把二维张量看作为一个带有行和列的数字网格。这个行和列表示两个坐标轴,一个矩阵就是二维张量,矩阵的每一行或每一列,都可以视为一维张量(向量)。如果把一系列的二维张量存储在列表中,这就形成了三维张量。你也可以把三维张量视为一个有长宽高立方体,张量能够被转换和操作,使列变为行或者行变为列。

维度是指在一个数据轴上的许多点,也就是样本的个数或者特征的个数。

张量的每一个数据轴,统称为阶。因此说一阶(1D)向量,二阶向量,三阶向量,而不是说维。

0D张量/标量 标量是一个数字

1D张量/向量 称为“向量”。只有一个坐标轴。 可以把向量视为一个单列的数字。

2D张量 2维张量称为矩阵也就是有两个坐标轴的张量。

3D张量 公用数据存储在张量 字符串文本,视频, 彩色图片(RGB),三维张量有三个坐标轴

二、机器学习中的张量

0、0D张量(标量)

仅包含一个数字的张量叫做标量,标量的功能主要在于程序流程控制、设置参数值等。

import torch
import numpy as np
#data = [[1, 2],[3, 4]]
x_data = torch.tensor(8)
print(f"X的值:{x_data}")
print(f"X的阶:{x_data.ndim}") #ndim属性显示张量轴的个数
print(f"Shape of tensor: {x_data.shape}")# shape属性显示张量形状
print(f"Datatype of tensor: {x_data.dtype}")# dtype属性显示张量数据类型
print(f"Device tensor is stored on: {x_data.device}")#存储它们的设备

 torch.Size([])此处标量的形状为(),既标量的阶为0

X的值:8
X的阶:0
Shape of tensor: torch.Size([])
Datatype of tensor: torch.int64
Device tensor is stored on: cpu

1、1D张量(向量)

一阶张量可以理解为一个向量,由一组数字组成的数组叫做向量(vector),也就是一阶张量,或称1D张量。一阶张量只有一个轴。

import torch
import numpy as np
data = [1, 2,3, 4]
np_array = np.array(data)
x_data = torch.from_numpy(np_array)
print(f"X的值:{x_data}")
print(f"X的阶:{x_data.ndim}") #ndim属性显示张量轴的个数
print(f"Shape of tensor: {x_data.shape}")# shape属性显示张量形状

torch.Size([4])代表的data是一个4维向量(也是1D张量)。

X的值:tensor([1, 2, 3, 4], dtype=torch.int32)
X的阶:1
Shape of tensor: torch.Size([4])

 2、2D张量(矩阵)

二阶张量可以理解为矩阵,形状为(samples,features),数据集中的每一行或每一列,都可以视为向量,但是数据集整体是一个矩阵。

from keras.datasets import boston_housing # 波士顿房价数据集
(X_train, y_train), (X_test, y_test) = boston_housing.load_data()
print(f"X_train的形状:{X_train.shape}")
print(f"X_train中第一个样本的形状:{X_train[0].shape}")
print(f"X_train的阶:{X_train.ndim}") #ndim属性显示张量轴的个数
print(f"y_train的形状:{y_train.shape}")

这个是Keras内置的波士顿房价数据集,是一个2D的普通数值数据集。X_train是一个2D矩阵,是404个样本数据的集合。X_train[0]代表的是X_train训练集的第一行数据,是一个13维向量(也是1D张量)。也就是说,训练集的每行数据都包含13个特征。

X_train的形状:(404, 13)
X_train中第一个样本的形状:(13,)
X_train的阶:2
y_train的形状:(404,)

 3、3D张量(时间序列)

在机器学习中,3D张量可用于存储时间序列。在矩阵数据的基础上再增加一个阶,就形成了3D张量。

import torch
shape = (2,3,2)
rand_tensor = torch.rand(shape)
print(f"Random Tensor: \n {rand_tensor} \n")
print(f"X的阶:{rand_tensor.ndim}") #ndim属性显示张量轴的个数
print(f"X_train中第一个样本的形状:{rand_tensor[0].shape}")
print(f"Shape of tensor: {rand_tensor.shape}")

rand_tensor是一个3D张量,是2个样本数据的集合。rand_tensor[0]代表的是rand_tensor第一个样本数据是一个形状为(3,2)的2D张量(也是矩阵)。

Random Tensor: 
 tensor([[[0.5826, 0.3287],
         [0.3100, 0.6388],
         [0.8254, 0.8289]],

        [[0.6451, 0.7861],
         [0.6652, 0.4813],
         [0.7998, 0.3282]]]) 

X的阶:3
X_train中第一个样本的形状:torch.Size([3, 2])
Shape of tensor: torch.Size([2, 3, 2])

4、4D张量(图像数据)

4D张量中的第四维表示存储样本量,比如图像数据包括高度、宽度,颜色深度,对图像数据集来说,再加上数据集大小 。用4D张量表示,如cifar10特征数据集的形状(50000,32,32,3)

from keras.datasets import cifar10
(train_images, train_labels), (test_images, test_labels) = cifar10.load_data()
print("train_images:", train_images.shape)
print("train_images中第一个样本的形状:", train_images[0].shape)
print("train_labels的形状:",train_labels.shape)

 这个是Keras内置的cifar10数据集图像分类,是一个4D的普通数值数据集,其中train_image是一个4D矩阵,是50000个样本数据的集合。X_train[0]代表的是X_train训练集的第一行数据,是一个3D张量。train_labels是一个2D矩阵,也就是说是50000个样本数据都有一个标签。

train_images: (50000, 32, 32, 3)
train_images中第一个样本的形状: (32, 32, 3)
train_labels的形状: (50000, 1)

5、5D张量(视频数据)

视频可以看作是由一帧一帧的彩色图像组成的数据集。
每一帧都保存在一个形状为(高度、宽度、颜色深度)的3D张量中。
一系列帧则保存在一个形状为(帧、高度、宽度、颜色深度)的4D张量中。
因此,视频数据集需要5D张量才放得下,其形状为(样本、帧、高度、宽度、颜色深度)。

5D张量可以用来存储视频数据。如果有10段视频,一段30秒,(1920 x 1080像素),每秒15帧(总共450帧),深度为3的视频:(视频数据的数据量是非常大的。)

(10,450,1920,1080,3)

三、Python张量的运算

超过 100 种张量运算,包括算术、线性代数、矩阵操作(转置、 索引,切片),采样等等

1、初始化张量

直接从数据,张量可以直接从数据中创建。 数据类型是自动推断的。

data = [[1, 2],[3, 4]]
x_data = torch.tensor(data)

来自 NumPy 数组,张量可以从 NumPy 数组创建

np_array = np.array(data)
x_np = torch.from_numpy(np_array)

从另一个张量:新张量保留参数张量的属性(形状、数据类型),除非显式覆盖。

x_ones = torch.ones_like(x_data) 
print(f"Ones Tensor: \n {x_ones} \n")

x_rand = torch.rand_like(x_data, dtype=torch.float) 
print(f"Random Tensor: \n {x_rand} \n")

2、类似 numpy 的索引和切片:

    对自定义的二维矩阵进行操作

import torch
import numpy as np
array1=np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
print(f"First column: {array1[1:2]},{array1[1:2].shape}")
print(f"First column: {array1[1:2][0]},{array1[1:2][0].shape}")
tensor = torch.from_numpy(array1)
print(f"First row: {tensor[1:2]}")
print(f"First column: {tensor[:,0]}")
print(f"Last column: {tensor[:,-1]},{tensor[:,-1].shape}")
tensor[:1] = 0
print(tensor)
First column: [[4 5 6]],(1, 3)
First column: [4 5 6],(3,)
First row: tensor([[4, 5, 6]], dtype=torch.int32)
First column: tensor([ 1,  4,  7, 10], dtype=torch.int32)
Last column: tensor([ 3,  6,  9, 12], dtype=torch.int32),torch.Size([4])
tensor([[ 0,  0,  0],
        [ 4,  5,  6],
        [ 7,  8,  9],
        [10, 11, 12]], dtype=torch.int32)

对keras中的数据集进行操作

from keras.datasets import mnist #需要打开internet选项)
(X_train, y_train), (X_test, y_test) = mnist.load_data()
print (X_train.shape)
X_train_slice = X_train[10000:15000,:,:]
print (X_train_slice.shape)
(60000, 28, 28)
(5000, 28, 28)

2、加入张量

可以使用 torch.cat沿给定维度连接一系列张量。

import torch
import numpy as np
array2=np.array([[1,2,3],[4,5,6]])
x = torch.from_numpy(array2)
t1 = torch.cat([x,x], dim=0)
t2 = torch.cat([x,x,x], dim=1)
print(t1)
print(t2)
tensor([[1, 2, 3],
        [4, 5, 6],
        [1, 2, 3],
        [4, 5, 6]], dtype=torch.int32)
tensor([[1, 2, 3, 1, 2, 3, 1, 2, 3],
        [4, 5, 6, 4, 5, 6, 4, 5, 6]], dtype=torch.int32)

3、张量的整体运算

import numpy as np
array2=np.array([[1,2,3],[4,5,6]])
array2+=1
print(array2)
for i in range(array2.shape[0]):
    for j in range(array2.shape[1]):
        array2[i,j] += 1
print(array2)
[[2 3 4]
 [5 6 7]]
[[3 4 5]
 [6 7 8]]

 4、张量的变形和转置

import numpy as np
array3 = np.arange(6)
print (array3,'形状是', array3.shape,'阶为', array3.ndim)
array4 = array3.reshape(6,1)
print (array4,'形状是', array4.shape,'阶为', array4.ndim)
array5 = array4.T # 矩阵的转置
print (array5,'形状是', array5.shape,'阶为', array5.ndim)
print (array5[0],'形状是', array5[0].shape,'阶为', array5[0].ndim)
[0 1 2 3 4 5] 形状是 (6,) 阶为 1
[[0]
 [1]
 [2]
 [3]
 [4]
 [5]] 形状是 (6, 1) 阶为 2
[[0 1 2 3 4 5]] 形状是 (1, 6) 阶为 2
[0 1 2 3 4 5] 形状是 (6,) 阶为 1

5、Pytorch中张量维度大小与数目的获取

在pytorch中对张量tensor维度及维度数目的获取可以有以下方法:ndimension方法可以获取张量的维数,nelement方法可以获取张量总的元素个数。。想要获得张量的每个维度的大小,也就是张量的形状信息,可以通过tensor.size()或者tensor.shape得到。想要获得特定维度的大小可以在使用size方法时输入想要的维度。

import torch
tensor0=torch.randn(1,3,28,28)
print(tensor0.ndimension(),tensor0.nelement())
print(tensor0.size(),tensor0.size(1))
4 2352
torch.Size([1, 3, 28, 28]) 3

四、与 NumPy 桥接

CPU 和 NumPy 数组上的张量可以共享它们的底层内存 位置,改变一个会改变另一个。

1、张量到 NumPy 数组

import torch
import numpy as np
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 数组中

t: tensor([1., 1., 1., 1., 1.])
n: [1. 1. 1. 1. 1.]
t: tensor([2., 2., 2., 2., 2.])
n: [2. 2. 2. 2. 2.]

2、NumPy 数组到张量

import torch
import numpy as np
n = np.ones(5)
t = torch.from_numpy(n)
np.add(n, 1, out=n)
print(f"t: {t}")
print(f"n: {n}")

 NumPy 数组的变化反映在张量中。

t: tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
n: [2. 2. 2. 2. 2.]

总结:

    机器学习中的数据结构称为张量,下面是几种重要的张量格式,用于处理不同类型的数据集。
    ·普通向量数据集结构:2D张量,形状为(样本,标签)
    ·时间序列数据集或序列数据集:3D张量,形状为(样本,时戳,特征)
    ·图像数据集:4D 张量,形状为(样本量、高度、宽度、颜色深度)
    Python语句操作方面,NumPy数组的操作都是重点内容。
    ·张量的切片操作
    ·用reshape进行张量变形
    ·加入张量、张量的整体运算
    ·张量维度大小与数目的获取
    ·张量的变形和转置

你可能感兴趣的:(矩阵,线性代数,python,pytorch)