Python的张量运算


在这里插入图片描述

想学习架构师构建流程请跳转:Java架构师系统架构设计

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))

运算结果:
在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赵广陆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值