Python的张量运算

简介: Python的张量运算

1 机器学习中张量的创建

机器学习中的张量大多是通过NumPy数组来实现的。NumPy数组和Python的内置数据类型列表不同。列表的元素在系统内存中是分散存储的,通过每个元素的指针单独访问,而NumPy数组内各元素则连续的存储在同一个内存块中,方便元素的遍历,并可利用现代CPU的向量化计算进行整体并行操作,提升效率。因此NumPy数组要求元素都具有相同的数据类型,而列表中各元素的类型则可以不同。

import numpy as np # 导入NumPy数学工具集
list=[1,2,3,4,5] # 创建列表
array_01=np.array([1,2,3,4,5]) # 列表转化成数组
array_02=np.array((6,7,8,9,10)) # 元组转化成数组
array_03=np.array([[1,2,3],[4,5,6]]) # 列表转化成2D数组
print ('列表:', list)
print ('列表转化为数组:', array_01)
print ('元组转化为数组:', array_02)
print ('2D数组:', array_03)
print ('数组的形状:', array_01.shape)
# print ('列表的形状:', list.shape) # 列表没有形状,程序会报错

运行结果

上面都是使用Num Py的array方法把元组或者列表转换为数组,而Num Py也提供了一些方法直接创建一个数组

array_04=np.arange(1, 5, 1) # 通过arange函数生成数组
array_05=np.linspace(1, 5, 5) # 通过linspace函数生成数组
print (array_04)
print (array_05)

运行结果:

arange和linspace都是创建连续等差数组,但是两者有区别:

(1)arange()函数类似内置函数range(),通过指定初始值,终值,步长来创建等差数列的一维数组,默认是不包括终值的。


linSpace()是lin space 的缩写,代表的是线性等分向量的含义。它是通过指定初始值,终值,元素个数来创建等差数组的,默认是包括终值的。


(2)arange的类型是int64,而linspace是float64的。


当然,机器学习的数据集并不是在程序里面创建的,大多是先从文本文件中把所有样本读取至Dataframe格式的数据,然后用array方法或其他方法把Dataframe格式的数据转换为NumPy数组,也就是张量,再进行后续操作。


2 索引和切片访问张量中的数据

array_06 = np.arange(10)
print (array_06)
index_01 = array_06[3] # 索引-第4个元素
print ('第4个元素', index_01)
index_02 = array_06[-1] # 索引-最后一个元素
print ('第-1个元素', index_02)
slice_01 = array_06[:4] # 从0到4切片
print ('从0到4切片', slice_01)
slice_02 = array_06[0:12:4] # 从0到12切片,步长为2
print ('从0到12切片,步长为4', slice_02)

注:

数组无论是生成的时候,还是访问的时候,都是从0开始的。索引3,就是第4个元素。

负号,表示针对当前轴终点的相对位置,因此这里-1指的就是倒数第一个元素。冒号,是指区间内的所有元素,如果没限定区间,就代表轴上面的所有元素。反正Python的语法挺灵活的,你们甚至可以用3个点(省略号)来代替多个冒号。

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,:,:]

10000:15000,就是把样本轴进行了切片。而后面两个冒号的意思是,剩下的两个轴里面的数据,全都保留(对这个图片样本集,如果后面两个轴也切片,图片的28px×28px的结构就被破坏了,相当于把图片进行了裁剪)。

array_07 = np.array([[1,2,3],[4,5,6]])
print (array_07[1:2],'它的形状是', array_07[1:2].shape) 
print (array_07[1:2][0], '它的形状又不同了', array_07[1:2][0].shape)

此示例意在提高大家对数组(即张量)形状和阶数的敏感度。同样都是4、5、6这3个数字形成的张量,[[4 5 6]]被两个方括号括起来,[4 5 6]被一个方括号括起来,两者阶的数目就不一样。还是那句话,张量是机器学习的数据结构,其形状是数据处理的关键,这是不能马虎的。

3 张量的整体操作和逐元素运算

张量的算术运算,包括加、减、乘、除、乘方等,既可以整体进行,也可以逐元素进行。

这种整体性的元素操作,省时、省力、速度快,是大规模并行计算优越性的实现。

4 张量的变形和转置

4.1 变形

注:

调用reshape方法时,变形只是暂时的,调用结束后,张量本身并无改变。如果要彻底地改变张量的形状需要赋值操作array_07 = array_07.reshape(3,2) #进行赋值才能改变数组本身

4.2 转置

数学概念:行变列,列变行

5 Python中的广播

广播(broadcasting)是NumPy对形状不完全相同的数组间进行数值计算的方式,可以自动自发地把一个数变成一排的向量,把一个低维的数组变成高维的数组。

机器学习领域有这样一种说法,如果使用很多的for循环语句,那么说明此人还未了解机器学习的精髓。首先利用了Python对于数组,也就是张量整体地并行操作。很大、很高阶的数据集,读入Num Py数组之后,并不需要循环嵌套来处理,而是作为一个整体,直接加减乘除、赋值、访问。这种操作很好地利用了现代CPU以及GPU/TPU的并行计算功能,效率提升不少。

array_08 = np.array([[0,0,0], [10,10,10], [20,20,20], [30,30,30]])
array_09 = np.array([[0,1,2]])
array_10 = np.array([[0],[1],[2],[3]])
list_11 = [[0,1,2]]
print ('array_08的形状:', array_08.shape)
print ('array_09的形状:', array_09.shape)
print ('array_10的形状:', array_10.shape)
array_12 = array_09.reshape(3)
print ('array_12的形状:', array_12.shape)
array_13 = np.array([1])
print ('array_13的形状:', array_13.shape)
array_14 = array_13.reshape(1,1)
print ('array_14的形状:', array_14.shape)
print ('08 + 09结果:',array_08 + array_09)
print ('08 + 10结果:',array_08 + array_10)
print ('08 + 11结果:',array_08 + list_11)
print ('08 + 12结果:',array_08 + array_12)
print ('08 + 13结果:',array_08 + array_13)
print ('08 + 14结果:',array_08 + array_14)

运行结果:

对两个数组, 从后向前比较它们的每一个阶(若其中一个数组没有当前阶则忽略此阶的运算)

对于每一个阶, 检查是否满足下列条件:

if当前阶的维度相等

then可以直接进行算术操作

else if当前阶的维度不相等, 但其中一个的值是1

then通过广播将值为1的维度进行“复制”(也形象地称为“拉伸”)后, 进行算术操作;

else if, 上述条件都不满足, 那么两个数组当前阶不兼容, 不能够进行广播操作

then抛出 “Value Error: operands could not be broadcast together” 异常;

注:

如果两个张量出现形状不匹配而不能广播的情况,系统会报错。此时可以通过reshape方法转换其中一个张量的形状。


6 向量和矩阵的点积运算

点积运算在机器学习中是非常重要6.1 向量点积运算

这个过程中要求向量a和向量b的维度相同。向量点积的结果是一个标量,也就是一个数值。

vector_01 = np.array([1,2,3])
vector_02 = np.array([[1],[2],[3]])
vector_03 = np.array([2])
vector_04 = vector_02.reshape(1,3)
print ('vector_01的形状:', vector_01.shape)
print ('vector_02的形状:', vector_02.shape)
print ('vector_03的形状:', vector_03.shape)
print ('vector_04的形状:', vector_04.shape)
print ('01和01的点积:', np.dot(vector_01,vector_01))
print ('01和02的点积:', np.dot(vector_01,vector_02))
print ('04和02的点积:', np.dot(vector_04,vector_02))
print ('01和数字的点积:', np.dot(vector_01,2))
print ('02和03的点积:', np.dot(vector_02,vector_03))
print ('02和04的点积:', np.dot(vector_02,vector_04))
# print ('01和03的点积:', np.dot(vector_01,vector_03)) # 程序会报错
# print ('02和02的点积:', np.dot(vector_02,vector_02))

运算结果:

6.2 矩阵点积运算

矩阵和矩阵之间的点积,大家就只需要牢记一个原则:第一个矩阵的第1阶,一定要和第二个矩阵的第0阶维度相同。即,形状为(a,b)和(b,c)的两个张量中相同的b维度值,是矩阵点积实现的关键,其点积结果矩阵的形状为(a,c)。

matrix_01 = np.arange(0,6).reshape(2,3)
matrix_02 = np.arange(0,6).reshape(3,2)
print(matrix_01)
print(matrix_02)
print ('01和02的点积:', np.dot(matrix_01,matrix_02))
print ('02和01的点积:', np.dot(matrix_02,matrix_01))
print ('01和01的点积:', np.dot(matrix_01,matrix_01))

目录
相关文章
|
21天前
|
Python
python增量赋值运算的应用
Python中的增量赋值运算符用于便捷地执行算术操作,如`+=`, `-=`等,它们分别代表加法、减法、乘法、除法、取模、整除和幂运算。
14 1
|
2月前
|
Python
python----输入输出&&算数运算
python----输入输出&&算数运算
21 0
|
10天前
|
Python
Python运算深入探索
Python运算深入探索
7 0
|
17天前
|
Python
python-基本类型,运算,循环
python-基本类型,运算,循环
29 0
|
2月前
|
Python
Python中的math和cmath模块:数学运算的得力助手
Python作为一种功能强大的编程语言,提供了丰富的数学运算功能。其中,math和cmath模块就是Python中用于数学运算的重要工具。math模块提供了基本的数学函数和常量,适用于实数运算;而cmath模块则提供了对复数运算的支持,使得Python在数学计算和工程应用中更加灵活和强大。
|
2月前
|
存储 SQL 数据挖掘
python数据分析——数据的选择和运算
在数据分析中,数据的选择和运算是非常重要的步骤。数据选择和运算是数据分析中的基础工作,正确和高效的选择和运算方法对于数据分析结果的准确性和速度至关重要。
46 0
|
3月前
|
Python
详解 Python 的二元算术运算,为什么说减法只是语法糖?
详解 Python 的二元算术运算,为什么说减法只是语法糖?
29 0
|
4月前
|
索引 Python C++
C/C++每日一练(20230416) 数列第n项、整数转英文、数组最大值及索引
C/C++每日一练(20230416) 数列第n项、整数转英文、数组最大值及索引
30 0
C/C++每日一练(20230416) 数列第n项、整数转英文、数组最大值及索引
|
4月前
|
Python Java Go
Python每日一练(20230415) 路径总和、两数相除、不同的二叉搜索树II
Python每日一练(20230415) 路径总和、两数相除、不同的二叉搜索树II
25 0
Python每日一练(20230415) 路径总和、两数相除、不同的二叉搜索树II
|
4月前
|
Python
Python 教程之 Pandas(12)—— series 的二元运算
Python 教程之 Pandas(12)—— series 的二元运算
21 0
Python 教程之 Pandas(12)—— series 的二元运算