Posted by Shen's Blog on Monday, January 1, 0001

3.Numpy

numpy的功能

引入Numpy的目的

  • 为何不直接用list?
    • 缺少数学操作
heights = [1.73, 1.68, 1.71, 1.89, 1.79] # 5人的身高
weights = [65.4, 59.2, 63.6, 88.4, 68.7] # 5人的体重
bmis = weights / heights ** 2            # 却不能直接计算5人的BMI
import numpy as np 
np_heights = np.array(heights)        # array,向量,通常只包含数值
np_weights = np.array(weights)
bmis = np_weights / np_heights ** 2   # 这里计算的单元是一个向量
bmis

运行结果如下:

array([21.85171573, 20.97505669, 21.75028214, 24.7473475 , 21.44127836])
更新BMI公式,现在是对向量做计算

\begin{equation}\vec{BMIS} = \frac{\vec{weights}}{\vec{heights}^{2}}\end{equation}

bmis > 21  # 符合直觉的结果, array([ True, False,  True,  True,  True])
round(bmis) # 只有numpy.ndarray支持的方法 报错
np.round(bmis) # 需要使用np重载的方法

# array([22., 21., 22., 25., 21.])

np.round(bmis,1) # 需要使用np重载的方法
array([21.9, 21. , 21.8, 24.7, 21.4])

np.max(bmis) == max(bmis) # 大胆地猜想这两种方法应该都可以

help(np.ndarray)  # 文档即教程

type(np_weights)                   # 应该返回numpy的类型   numpy.ndarray

mixed_list = [1.0, "is", True] # 通用类型的list
type(np.array(mixed_list))     # 转化为numpy array    numpy.ndarray

np.array(mixed_list)               # 数据类型是字符串   array(['1.0', 'is', 'True'], dtype='<U32')

深入了解numpy数据类型

dtype

数理统计和线性代数基础

数理统计的例子
  • 在大样本数据上计算身高体重指数
  • 把前面5人的例子扩大1000倍
  • 随机产生一个正态分布

正态分布生成文档快照

中国成年人身高,体重均值和标准差的参考值 (2015)
性别 东北华北 西北 东南 华中 华南 西南
身高,体重 均值,标准差 均值,标准差 均值,标准差 均值,标准差 均值,标准差 均值,标准差
男(mm) 1693, 56.6 1684, 53.7 1686, 55,2 1669, 56.3 1650, 57.1 1647, 56.7
女(mm) 1586, 51.8 1575, 51.9 1575, 50.8 1560, 50.7 1549, 49.7 1546, 53.9
男(kg) 64, 8.2 60, 7.6 59, 7.7 57, 6.9 56, 6.9 55, 6.8
女(kg) 55, 7.1 52, 7.1 51, 7.2 50, 6.8 49, 6.5 50, 6.9

选择东南地区成年男性数据:身高:1686, 55.2,体重:59, 7.7

height_5k = np.random.normal(1.686, 0.0552, 5000)   # 5000身高数据
weight_5k = np.random.normal(59, 7.7, 5000)         # 5000体重数据
shmale_5k = np.column_stack((height_5k, weight_5k)) # 5000上海男性数据
shmale_5k                                           # 随机产生一些瘦子和胖子

返回结果如下:

array([[ 1.71673326, 59.30856039],
       [ 1.78173268, 53.59941495],
       [ 1.63402604, 76.34316629],
       ...,
       [ 1.82961841, 53.30531369],
       [ 1.64105013, 60.11390686],
       [ 1.70708758, 66.51344072]])
shmale_weight = shmale_5k[:,1]
shmale_height = shmale_5k[:,0]
shmale_height_mean = np.mean(shmale_height)  # 身高均值
shmale_height_std = np.std(shmale_height)    # 身高标准差
shmale_weight_mean = np.mean(shmale_weight)  # 体重均值
shmale_weight_std = np.std(shmale_weight)    # 体重标准差
from tabulate import tabulate                # 格式化成表格样式
print(tabulate([['身高(米)', shmale_height_mean, shmale_height_std], 
                ['体重(公斤)', shmale_weight_mean, shmale_weight_std]], 
               headers=['上海男','均值', '标准差']))

运行结果示例:

上海男            均值     标准差
------------  --------  ---------
身高(米)     1.68597  0.0548796
体重(公斤)  59.1071   7.75585
shmale_bmi = shmale_weight / shmale_height ** 2 # 计算5000身高体重指数
shmale_bmi

print(np.mean(shmale_bmi), np.std(shmale_bmi))  # 上海男性体型分布
线性代数例子
  • 解方程组 $\begin{bmatrix}2x + 3y = 8 \end{bmatrix}$ $\begin{bmatrix}5x + 2y = 9 \end{bmatrix}$

  • 用矩阵的形式表示为 $$ A = \begin{bmatrix}2 & 3\5 & 2\end{bmatrix} ;;;; \vec{b} = \begin{bmatrix}8\9\end{bmatrix}$$

  • 目标是求向量x $$ A\vec{x}= \vec{b} $$

a = np.array([[2, 3], [5, 2]]) # 方程组系数矩阵
a.transpose()                  # 转置

转置后结果如下:

b = np.array([8, 9])
print(b.shape, a.shape)         # shape不是函数,是tuple
b.transpose()

运行结果如下:

(2,) (2, 2)
array([8, 9])

矩阵的索引

print(tabulate([['0', a[0,0], a[0,1]], 
                ['1', a[1,0], a[1,1]]], 
               headers=['A', '0', '1']))

运行结果如下:

  A    0    1
---  ---  ---
  0    2    3
  1    5    2

矩阵运算文档 linalg

矩阵求逆

# 矩阵求逆
from numpy.linalg import inv as inv
a_inv = inv(a)
a_inv

运行结果如下:

array([[-0.18181818,  0.27272727],
       [ 0.45454545, -0.18181818]])

$$ A^{-1}A=\begin{bmatrix}1 & 0\0 & 1\end{bmatrix} $$

np.round(a_inv @ a) # 逆矩阵和原矩阵乘来验证求逆, @代表矩阵乘

运行结果如下:

array([[ 1.,  0.],
       [-0.,  1.]])

$$ A^{-1}A\vec{x}=A^{-1}\vec{b}$$

$$ \begin{bmatrix}1 & 0\0 & 1\end{bmatrix}\vec{x}= A^{-1}\vec{b}$$

$$ \vec{x} = A^{-1}\vec{b}$$

x = a_inv @ b
x

运行结果如下:

array([1., 2.])

方程组求解:

from numpy.linalg import solve as solve # 引入求解方法
solve(a, b)

运行结果如下:

array([1., 2.])

$$ \vec{x} = \begin{bmatrix}1\2\end{bmatrix} $$

$$ x=1 $$ $$ y=2 $$