文章目录
系列文章
机器学习入门 01 —— 机器学习概述
机器学习入门 02 —— 环境搭建(Jupyter Notebook 及扩展库的安装与使用)
机器学习入门 03 —— Matplotlib使用
机器学习入门 04 —— Numpy使用
机器学习入门 05 —— Pandas使用
机器学习入门 06 —— Seaborn使用
Numpy
学习目标:
- 了解Numpy运算速度上的优势
- 知道数组的属性、形状、类型
- 应用Numpy实现数组的基本操作
- 应用随机数组的创建实现正态分布应用
- 应用Numpy实现数组的逻辑运算
- 应用Numpy实现数组的统计运算
- 应用Numpy实现数组之间的运算
4.1 Numpy优势
1 Numpy介绍
Numpy(Numerical Python)是一个开源的Python科学计算库,用于快速处理任意维度的数组。
Numpy支持常见的数组和矩阵操作。对于同样的数值计算任务,使用Numpy比直接使用Python要简洁的多。
Numpy使用ndarray对象来处理多维数组,该对象是一个快速而灵活的大数据容器。
2 ndarry介绍
Numpy提供了一个N维数组类型ndarray,它描述了相同类型的“items”的集合。 例如,使用ndarry对下面表格进行存储:
提问:使用Python列表可以存储一维数组,通过列表的嵌套可以实现多维数组,那么为什么还需要使用Numpy的ndarray呢?
3 ndarray与Python原生list效率对比
这里通过代码来进行对比:
从中我们看到ndarray的计算速度要快很多,节约了时间。
机器学习的最大特点就是大量的数据运算,那么如果没有一个快速的解决方案,那可能现在python也在机器学习领域达不到好的效果。
Numpy专门针对ndarray的操作和运算进行了设计,所以数组的存储效率和输入输出性能远优于Python中的嵌套列表,数组越大,Numpy的优势就越明显。
4 ndarray的优势
区别一:
从图中我们可以看出ndarray在存储数据的时候,数据与数据的地址都是连续的,这样就给使得批量操作数组元素时速度更快。
这是因为ndarray中的所有元素的类型都是相同的,而Python列表中的元素类型是任意的,所以ndarray在存储元素时内存可以连续,而python原生list就只能通过寻址方式找到下一个元素,这虽然也导致了在通用性能方面Numpy的ndarray不及Python原生list,但在科学计算中,Numpy的ndarray就可以省掉很多循环语句,代码使用方面比Python原生list简单的多。
区别二:
numpy内置了并行运算功能,当系统有多个核心时,做某种计算时,numpy会自动做并行计算。
区别三:
Numpy底层使用C语言编写,内部解除了GIL(全局解释器锁),其对数组的操作速度不受Python解释器的限制,所以,其效率远高于纯
Python代码。
5 小结
-
numpy介绍【了解】
- 一个开源的Python科学计算库
- 计算起来要比python简洁高效
- Numpy使用ndarray对象来处理多维数组
-
ndarray介绍【了解】
- NumPy提供了一个N维数组类型ndarray,它描述了相同类型的“items”的集合。
- 生成numpy对象:np.array()
-
ndarray的优势【掌握】
- 内存块风格
- list – 分离式存储,存储内容多样化
- ndarray – 一体式存储,存储类型必须一样
- ndarray支持并行化运算(向量化运算)
- ndarray底层是用C语言写的,效率更高,释放了GIL
- 内存块风格
4.2 N维数组—ndarray
1 ndarray的属性
import numpy as np
# 这是一个三维数组
array = np.array([[[1, 2, 3], [4, 5, 6]],
[[1, 2, 3], [4, 5, 6]]])
# 返回数组维度元祖
print(array.shape) # (2, 2, 3) 表示 2个二维数组,每个二维数组是 2行,3列
# 返回数组是几维
print(array.ndim) # 3, 表示3维数组
# 数组中元素的总数量
print(array.size) # 12
# 数组一个元素的字节大小
print(array.itemsize) # 8个字节
# 数组元素的类型
print(array.dtype) # int64
2 ndarray的元素类型
- 可以在创建数组时指定类型
a = np.array(['123','1234'], dtype=np.string_)
。 - 如果是字符串类型,返回dtype时会显示长度
array([b'123', b'1234'], dtype='|S4')
,最后的|S4
表示数组中最长的字符串长度为4。
3 基本操作
0/1数组
# 生成 0 数组(2行3列)
a = np.zeros([2,3])
b = np.zeros_like(a)
# 生成 1 数组(3行2列)
c = np.ones([3, 2])
d = np.ones_like(c)
拷贝数组
a = np.array([1, 2, 3])
# 深拷贝(新创建的数组)
b = np.arryay(a)
# 浅拷贝(不会新创建数,还是指向a,会随着a的改变而改变)
c = np.asarray(a)
等差/等比数组
# 创建等差数组 np.linspace (start, stop, num, endpoint)
'''
start:序列的起始值
stop:序列的终止值
num:要生成的等间隔样例数量,默认为50
endpoint:序列中是否包含stop值,默认为ture
'''
np.linspace(0, 100, 11)
# 结果:array([ 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100.])
# 创建指定步长的等差数组 np.arange(start,stop, step, dtype);step表示步长,默认为1
np.arange(10, 20, 2)
# 结果:array([10, 12, 14, 16, 18])
# 创建等比数组 np.logspace(start,stop, num);num表示要生成的等比数量,默认为50。
np.logspace(0, 2, 3) # 生成 10的x次方,即10的0次方,10的1次方,10的2次方
# 结果:array([ 1., 10., 100.])
正态分布和均匀分布
这里要使用到numpy的random模块,它可以按照分布律随机生成数。当然,它也和普通的random模块一样,可以生成随机整数那些。
正态分布
正态分布里主要是均值μ和标准差σ来来发挥作用,当μ=0,σ=1时是标准正态分布。
这里提一下,正态分布是概率论里面的,其中方差就是标准差的平方,方差的公式如下:
其中M是平均值,n是数据总数,σ是标准差,σ2是方差,由于n是固定的,所以每个x趋近于M时,σ越小。因此,标准差越小说明数据越聚合,对应的正态分布图像越高。而均值μ是决定正态分布的中心位置,当μ=0时,正态分布就在原点。
import numpy as np
import matplotlib.pyplot as plt
# np.random.normal(loc=0.0, scale=1.0, size=None)
data = np.random.normal(0, 1, 100000000) # loc是均值,scale是标准差,size是数据大小【1000表示1000个数据,(2,3)表示2行3列个数据】
plt.figure(figsize=(20, 10), dpi=100)
plt.hist(data, 1000) # 绘制直方图,把数据分为1000组
plt.show()
np.random.normal(0, 1, (4, 5))
# 结果 array([[-0.63742603, -0.177 , -0.36085334],
# [-0.5501791 , -0.52541693, 1.04454327]])
效果:
均匀分布
# np.random.uniform(low=0.0, high=1.0, size=None) 下限、上线、数据量
data = np.random.uniform(-1, 1, 100000)
plt.figure(figsize=(15, 8), dpi=100)
plt.hist(data, 100)
plt.show()
效果:
形状修改
# 原来的样子是2行4列
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
# reshape重新构造行列,需要保持数目一致。这里返回4行2列
b = a.reshape([4,2]) # 如果写[-1, 2] 则会自动计算 2列需要多少行
# resize 是重新构造原来的数组,reshape是返回新数组对象。
a.resize([4,2])
# T是数组转置。即行列互换。
a.T
类型修改
astype(dtype)
返回修改类型后的数组
a = np.array([1.1, 2.1, 3.1])
a.astype(np.int64)
# 结果:array([1, 2, 3])
还有tostring([order])
和tobytes([order])
构造包含数组中原始数据字节的Python字节。
如果遇到报错:
IOPub data rate exceeded.
The notebook server will temporarily stop sending output
to the client in order to avoid crashing it.
To change this limit, set the config variable
`--NotebookApp.iopub_data_rate_limit`.
这个问题是由于jupyter对输出的字节数有限制。
数组去重
unique()函数返回去重后的数组,数组都会变成一维。
temp = np.array([[1, 2, 3, 4],[3, 4, 5, 6]])
np.unique(temp)
# 结果:array([1, 2, 3, 4, 5, 6])
4 ndarray运算
逻辑运算
可以直接对数组对象进行逻辑运算(>、<等),比较的是数组对象里的每个元素。
通用判断函数 all和any
np.all()
判断数组所有元素是否满足条件,满足则返回True。
np.any()
判断数组是否有一个元素满足条件,满足则返回True。
三元运算符 where
和普通的三元运算符类似条件?表达式1:表达式2
,where也是在满足条件时赋值表达式1,不满足赋值表达式2。
通常,where可以配合逻辑与和逻辑或进行更为复杂的运算:np.logical_and()
和np.logical_or()
统计运算
np.min(a, axis)
:计算数组a最小值,如果指定了axis,则找每行或每列的最小值。axis=0表示列。不指定则找整个数组的最小值。np.argmin(a, axis)
:获取最小值的下标,如果指定了axis,则找出每行或每列最小值的下标。axis=0表示列。不指定则找整个数组的最小值下标。np.max(a, axis)
:计算最大值。np.median(a, axis)
:计算中位数。np.mean(a, axis,dtype)
:计算平均值。np.std(a, axis, dtype)
:计算标准差。np.var(a,axis, dtype)
:计算方差。
5 数组间的运算
数组与数进行运算
numpy的数组与数进行运算,就是每个元素都与数进行运算。
数组与数组进行运算
如果两个数组形状相同,那么就是每个对应位置的元素进行运算。
如果形状不相同,要看是否满足广播机制。
即满足下列任一条件:
- 最后维度相等。(例如 3x2和2x2,最后维度都是2)
- 最后维度是 1。(例如 2x2和3x1,最后维度是1)
若不满足,则抛出ValueError: frames are not aligned
异常。
若满足广播机制,则会按照下列方式对数组进行扩展:
下面举例:
6 矩阵乘法
numpy可以把数组进行矩阵相乘(这里的矩阵就是线性代数里的那个矩阵),调用下函数np.matmul()
或者np.dot()
可以执行矩阵相乘。
np.matmul()
和np.dot()
的区别是,matmul只能两个矩阵相乘,而dot可以矩阵乘数字。