0%

Python人工智能从入门到放弃

Python AI从入门到放弃

1. 概述

1.1. 人工智能起源

  • 图灵测试
  • 达特茅斯会议

1.2. 人工智能三个阶段

  • 1980年代是正式成形期
  • 1990-2010年代是蓬勃发展期
  • 2012年之后是深度学习期

1.3. 人工智能、机器学习和深度学习

  • 机器学习是人工智能的一个实现途径
  • 深度学习是机器学习的一个方法发展而来

1.4. 主要分支

  • 计算机视觉 CV
    • 人脸识别
  • 自然语言处理 NLP
    • 语音识别
    • 语义识别
  • 机器人

1.5. 人工智能必备三要素

  • 数据
  • 算法
  • 计算力

1.6. GPU、CPU

  • GPU – 计算密集型
  • CPU – IO密集型

2. 机器学习

2.1. 工作流程

  1. 数据获取

数据类型构成

  • 特征值 + 目标值(目标值分为离散还是连续)
  • 仅有特征值,无目标值

数据划分

  • 训练集 0.7~0.8
  • 测试集 0.2~0.3
  1. 数据基本处理

对数据进行缺失值、去除异常值等处理

  1. 特征工程

把数据转换为机器更容易识别的数据

数据和特征决定了机器学习的上限,模型和算法只是逼近这个上限而已

  • 特征提取
  • 特征预处理
  • 特征降维
  1. 机器学习(模型训练)

选择合适的算法对模型进行训练

  1. 模型评估

对训练好的模型进行评估

2.2. 机器学习算法分类

  • 监督学习:有特征值,有目标值
    • 目标值连续:回归
    • 目标值离散:分类
  • 无监督学习:仅有特征值
  • 半监督学习:有特征值,但一部分数据有目标值 ,一部分没有
  • 强化学习:即自动进行决策,并可以做连续决策
    • 动态过程,上一步的输出是下一步的输入
    • 四要素:agent, action, environment, reward

2.3. 模型评估

  • 分类模型评估

    • 准确率:预测正确的数占样本总数的比例
    • 精确率:预测为正的数占全部预测为正的比例
    • 召回率: 预测为正占全部正样本的比例
    • F1-score:主要用于评估模型的稳健性
    • AUC指标:主要用于评估样本不均衡的情况
  • 回归模型评估

    p = predicted target

    a = actual target

    • 均方根误差(Root Mean Squared Error, RMSE)
    • 相对平方误差(Relative Squared Error, RSE)
    • 平均绝对误差(Mean Absolute Error, MAE)
    • 相对绝对误差(Relative Absolute Error, RAE)
    • 决定系数(Coefficient of Determination)
  • 拟合度(评估结果)

    • 欠拟合:学习到的特征太少(有两个眼睛的就是人)
    • 过拟合:学习到的特征太多(仅黄皮肤的才是人)

3. 机器学习环境配置

3.1. 环境安装

  • 创建虚拟环境: conda create --name=ai0 python=3.10
  • 安装相关包:
    • matplotlib==2.2.2
    • numpy==1.14.2
    • pandas==0.20.3
    • tables==3.4.2
    • jupyter=1.0.0
  • 先从cmd进入指定目录后执行jupyter notebook

3.2. jupyter基操

类似vim, 分不同的输入模式,命令也和vim基本相同

  • 两种模式通用快捷键
    • Shift + Enter 执行本单元代码,跳转到下一单元
    • Ctrl + Enter 执行本单元代码,留在本单元
  • 命令模式:按 ESC 进入
    • Y, cell 切换到Code模式
    • M, cell 切换到Markdown模式
    • A, 在当前cell上面添加cell
    • B, 在当前cell下面添加cell
    • DD, 删除当前cell
    • Z, 回退
    • L, 为当前cell加上行号<!–
    • Ctrl+Shift+P, 对话框输入命令直接运行
    • Ctrl+Home, 跳转到首个cell
    • Ctrl+End, 跳转到末个cell
    • Shift + M 合并下面的cell
  • 编辑模式: 按 Enter 进入
    • Ctrl + 点击, 多光标操作
    • Ctrl + Z, 回退
    • Ctrl + Y, 重做
    • TAB, 代码补全
    • Ctrl + / 注释/取消注释
    • 代码后 + ; 屏蔽输出

4. Matplotlib

用于开发2D、3D图表

使用简单,以渐进、交互式实现数据可视化

4.1. 三层结构

  • 容器层
    • Canvas: 最底层的系统层,充当画板角色,即放置画布(Figure)的工具
    • Figure: Canvas上第一层,充当画布角色
    • Axes:应用层的第二层,在绘图过程中相当于画布上的绘图区的角色
      • Axes: 坐标系,数据的绘图区域
      • Axis: 坐标轴
  • 辅助显示层:为Axes内除了根据数据绘制出的图像以外的内容,主要包括facecolor(Axes外观)spines(边框线)axis(坐标轴)axix lable(坐标轴名称)tick(坐标轴刻度)tick lable(坐标轴刻度标签)gird(网格线)legend(图例)title(标题)
  • 图像层:指Axes内通过 plot, scatter, histogram, pie等函数根据数据绘制出的图像。

4.2. 折线图与基操

help(plt.figure) 查看命令帮助

负号报错 plt.rcParams[“axes.unicode_minus”]=False 加这句

中文乱码,需要把系统使用的中文字体对应的英文名称添加到matplotlib配置中 matplotlib.matplotlib_fname() 可查到是 matplotlib/mpl-data/matplotlibrc 此文件,查 #font.sans-serif 解注释并把英文字体名加到第一个位置

报错missing from current font,加以下代码

from pylab import mpl mpl.rcParams['font.sans-serif'] = ['SimHei']

Hello World

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import matplotlib.pyplot as plt

# 1.创建画布
plt.figure()

# 2.图像绘制
x = [i for i in range(1, 6)]
y = [i for i in range(3, 8)]
plt.plot(x, y)

# 2.1. 图像保存, 要放到show前
plt.savefig()

# 3.显示图像
plt.show()

基操

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import random
import matplotlib.pyplot as plt

# 0.生成数据
x = range(60)
y_peking = [random.uniform(10, 15) for i in x]
y_shanghai = [random.uniform(15, 25) for i in x]

# 1. 创建画布
plt.figure(figsize=(20, 8), dpi=100)

# 2.图形绘制
plt.plot(x, y_peking, color="r", label="北京", linestyle="dashed")
plt.plot(x, y_shanghai, label="上海")

# 2.1. 添加x,y刻度
x_ticks_labels = [f"11点{i}" for i in x]
y_ticks = range(40)

plt.yticks(y_ticks[::5])
plt.xticks(x[::5], x_ticks_labels[::5])

# 2.2. 添加网络信息
# 参数:linestyle: 绘制网格的方式,alpha:透明度
plt.grid(True, linestyle="-", alpha=1)

# 2.3. 添加描述
plt.xlabel("时间")
plt.ylabel("温度")
plt.title("中午11:00到12:00温度变化")

# 2.4. 显示图例, 需要在显示前声明plot里面的值
plt.legend()

# 3. 图像显示
plt.show()

多个坐标系图像显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import random
import matplotlib.pyplot as plt

# 多个坐标系显示图像
# 0.生成数据
x = range(60)
y_peking = [random.uniform(10, 15) for i in x]
y_shanghai = [random.uniform(15, 25) for i in x]

# 1. 创建画布
# plt.figure(figsize=(20, 8), dpi=100)
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(20, 8), dpi=100)

# 2.图形绘制
# plt.plot(x, y_peking, color="r", label="北京", linestyle="dashed")
# plt.plot(x, y_shanghai, label="上海")
axes[0].plot(x, y_peking, color="r", label="北京", linestyle="dashed")
axes[1].plot(x, y_shanghai, label="上海")

# 2.1. 添加x,y刻度
x_ticks_labels = [f"11点{i}" for i in x]
y_ticks = range(40)

# plt.yticks(y_ticks[::5])
# plt.xticks(x[::5], x_ticks_labels[::5])

axes[0].set_xticks(x[::5])
axes[0].set_yticks(y_ticks[::5])
axes[0].set_xticklabels(x_ticks_labels[::5])

axes[1].set_xticks(x[::5])
axes[1].set_yticks(y_ticks[::5])
axes[1].set_xticklabels(x_ticks_labels[::5])

# 2.2. 添加网络信息
# 参数:linestyle: 绘制网格的方式,alpha:透明度
# plt.grid(True, linestyle="-", alpha=1)
axes[0].grid(True, linestyle="-", alpha=1)
axes[1].grid(True, linestyle="-", alpha=1)

# 2.3. 添加描述
# plt.xlabel("时间")
# plt.ylabel("温度")
# plt.title("中午11:00到12:00温度变化")

axes[0].set_xlabel("时间")
axes[0].set_ylabel("温度")
axes[0].set_title("中午11:00到12:00温度变化")

axes[1].set_xlabel("时间")
axes[1].set_ylabel("温度")
axes[1].set_title("中午11:00到12:00温度变化")

# 2.4. 显示图例, 需要在显示前声明plot里面的值
# plt.legend(loc=0)

axes[0].legend(loc=0)
axes[1].legend(loc=0)

# 3. 图像显示
plt.show()

5. Numpy

5.1. 基础

定义:

  • Numpy(Numerical Python) 是一个开源的Python科学计算库,用于快速处理任意维度的数组
  • Numpy支持觉的数组和矩阵操作,对于同样数值计算任务,使用Numpy比直接使用Python简洁的多
  • Numpy使用ndarray对象来处理多维数组,该对象是一个快速而灵活的大数据容器

优势:

  • 内存块风格:ndarray在存储数据时,数据和数据的地址是连续的,这样使得批量操作数组元素时速度更快

    • 原因:ndarray中所有的元素类型是相同的,而Python列表中的元素类型是任意的,所以ndarray在存储元素时内存可以连续,而原生列表只能通过寻址方式找到下一个元素
  • 并行化运算:向量化运算

  • Numpy底层使用C语言编写,内部解除了GIL,其对数组的操作速度不受Python解释器的限制,所以效率远高于纯Python代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import time
import random
import numpy as np

# 创建
score = np.array([random.sample(range(0, 100), 5) for i in range(8)])
score
"""
array([[41, 11, 1, 56, 40],
[30, 29, 38, 62, 68],
[75, 38, 76, 45, 2],
[63, 84, 68, 26, 60],
[45, 48, 58, 33, 21],
[ 1, 74, 44, 19, 97],
[15, 73, 63, 82, 95],
[20, 73, 15, 8, 93]])
"""

# 效率对比
a = [random.random() for _ in range(1000_0000)]

# %time 魔法方法,查看当前行代码运行耗时情况
# cpu times CPU执行耗时, wall time 总耗时
%time sum1 = sum(a)

b = np.array(a)

%time sum2 = np.sum(b)
"""
CPU times: total: 31.2 ms
Wall time: 31.9 ms
CPU times: total: 15.6 ms
Wall time: 9.97 ms
"""

常用属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
score
"""
array([[41, 11, 1, 56, 40],
[30, 29, 38, 62, 68],
[75, 38, 76, 45, 2],
[63, 84, 68, 26, 60],
[45, 48, 58, 33, 21],
[ 1, 74, 44, 19, 97],
[15, 73, 63, 82, 95],
[20, 73, 15, 8, 93]])
"""
score.shape # (8, 5)
score.ndim # 2 数组维度(也就是有几层[])
score.size # 40
score.itemsize # 4 每个元素占字节长度
score.dtype # dtype('int32')

# 设置ndarray类型
a = np.array([[1, 2, 3], [2, 3, 4]], dtype=np.float32)
a.dtype # dtype('float32')

5.1.1. 生成数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 0/1数组
np.ones([3, 4])
"""
array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
"""

np.zeros([3, 4])
"""
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
"""

# 从现有数组创建数组
a = np.array([[1,2,3], [4,5,6]])

a1 = np.array(a) # 深拷贝

a2 = np.asarray(a) # 浅拷贝

# 生成固定范围数组
np.linespace(0, 100, 11) # 等间隔生成11个
# array([ 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100.])

np.aragne(10, 50, 2) # 步长2来生成
# array([10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48])

生成随机数组

  • 生成均匀分布:np.random.uniform(low, high, size)

  • 正态分布

    • 均值:平均值
    • 标准差:方差开根号
    • 生成标准正态分布:np.random.normal(low, high, size)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import matplotlib.pyplot as plt
import numpy as np

# 均匀分布
x = np.random.uniform(1, 10, 1000_0000) # 准备数据
plt.figure(figsize=(20, 8), dpi=100) # 画布
plt.hist(x, bins=1000) # 绘制 x代表要使用的数据, bins表示要划分的区间数
plt.show() # 显示

# 正态分布
x = np.random.normal(1.75, 1, 1000_0000)
plt.figure(figsize=(20, 8), dpi=100)
plt.hist(x, bins=1000)
plt.show()

5.1.2. 数组索引、切片

  • 直接索引,先对行进行索引,再对列进行索引
  • 高维度索引,从宏观到微观
1
2
3
4
5
6
7
8
a = np.random.normal(0, 1, (8, 10))  # 8rows, 10cols
a[0:2, 0:3] # 前两行,前三列

a = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
a[0, 0, 0] # 1
a[1, 0, 0] # 7
a[1, 1, 2] # 12

5.1.3. 形状修改

  • .reshape([rows, cols]) 不进行行列互换,产生新变量

  • .resize([rows, cols]) 进行行列互换,对原值 进行更改

  • .T 行列互换

5.1.4. 类型修改

  • .astype(np.int32)

  • .tobytes()

  • np.unique(nparray) 去重

    1
    2
    3
    arr = np.array([[1, 2, 3, 3, 3], [2, 3, 4,4 , 5]])
    np.unique(arr)
    # array([1, 2, 3, 4, 5])

5.1.5 运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import numpy as np

# 逻辑运算
a = np.random.normal(0, 1, (8, 10))
a > 1 # 全部数据进行此运算,结果赋值为 True/False
a[a > 1] = 2 # 全部数据 >1 赋值为 2

# 通用判断函数,和python的all和any一样
b = a[0:2, 0:5] # 切为2行5列
np.all(b > 0) # False
np.any(b > 0) # True

# 三元运算
np.where(b > 0, 1, 0) # array([[1, 1, 0, 0, 1], [0, 1, 0, 1, 1]])

np.where(np.logical_and(b > -0.5, b < 0.5), 1, 0) # array([[1, 0, 0, 0, 0],[0, 1, 1, 0, 1]])

np.where(np.logical_or(b > -0.5, b < 0.5), 1, 0) # array([[1, 1, 1, 1, 1], [1, 1, 1, 1, 1]])

# 统计运算
min
max
median
mean
std 标准差
var 方差
argmax 最大值下标
argmin

5.2. 矩阵

  • 矩阵:二维数组
    • 向量:一维数组
  • 加法:对应位置相加
  • 标量乘法:标量和每个位置元素相乘
  • 矩阵乘法:[M行,N列] * [N行,L列] = [M行,L列]
    • 满足结合律,不满足交换律
  • 单位矩阵:对角线为1,其他位置为0的矩阵
  • 逆:A * B = 单位矩阵,A和B互为逆矩阵
  • 转置T:行列互换

5.3. 数组间运算

  • 数组和数字:可以直接运算

  • 数组和数组:广播机制

    • 维度相同
    • shape对应位置为1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np

# 数组运算
arr1 = np.array([[1, 2, 3], [2, 3, 4]]) # 2,3
arr2 = np.array([[2], [1]]) # 2, 1

arr1 + arr2 # 广播机制:2==2,1 in (1, 3) 输出: array([[3, 4, 5], [3, 4, 5]])

# 矩阵乘法
a = np.array([[1, 2], [2, 3], [3, 4]])
b = np.array([[3], [2]])

# 矩阵乘
np.matmul(a, b) # 要求 3行2列 * 2行1列 输出:3行1列 array([[ 7], [12], [17]])

# 点乘
np.dot(2, b) # array([[6], [4]])

6. Pandas

  • 封装了Numpy 和 matplotlib
  • 便捷的数据处理,展示能力
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import pandas as pd
import numpy as np

a = np.random.normal(0, 1, (10, 5))

a_shape = pd.DataFrame(a).shape # (10, 5)

row_index = [f"第{i+1}行" for i in range(a_shape[0])]
column_name = pd.date_range(start="20230713", periods=a_shape[1], freq="B") # freq:B 工作日 DatetimeIndex(['2023-07-13', '2023-07-14', '2023-07-17', '2023-07-18','2023-07-19'], dtype='datetime64[ns]', freq='B')

b = pd.DataFrame(a, index=row_index, columns=column_name) # 设置行索引, 列名

b.shape # 形状
b.index # 行索引
b.columns # 列名
b.values # array
b.T # 转置
b.head() # 前5行
b.tail() # 后5行


# 重设索引
b.index = row_index
c = b.reset_index(drop=False) # 默认drop=False不删除原索引,增加index列 值为原索引

# 设置某列为索引,可设置多列
c.set_index(keys=["index"])

7. K-近邻算法

根据邻居判断自己的类别,是一种分类算法,K Nearst Neighbor(KNN)

-

7.1. Scikit-learn

Classification 分类

Regression 回归

Clustering 聚类

Dimensionality reduction 维度缩小

Model selection 模型选择

Preprocessing 特征预处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from sklearn.neighbors import KNeighborsClassifier


# 获取数据
x = [[1], [2], [0], [0]]
y = [1, 1, 0, 0]

# machine learning
# 1. 实例化一个训练模型
estimator = KNeighborsClassifier(n_neighbors=2) # 选定几个参考数据

# 2. 调用fit方法进行训练
estimator.fit(x, y)

# 预测其他值
print(estimator.predict([[-1]]))

7.2. 距离度量

欧式距离:差平方开根号

曼哈顿距离(Manhattan Distance): 又称为城市街区距离(City Block distance)

  • d = |x1 - x2| + |y1 - y2|

切比雪夫距离(Chebyshev Distance): max(|x1-x2|, |y1-y2|)

闵可夫斯基距离(Minkowski Distance):
$$
d_{12} = p\sqrt{\sum_{k=1}^n|x_{1k} - x_{2k}|^p}
$$

  • 当p=1, 为曼哈顿距离
  • 当p=2,为欧氏距离
  • 当p$\to\infty$, 为切比雪夫距离

标准化欧氏距离(Standardized EuclideanDistance): 对欧氏距离的一种改进, 如果将方差的倒数看成一个权重,也可称为加权欧氏距离(Weighted Euclidean distance)

  • 既然数据各维分量的分布不同,将各个分量都标准化到均值、方差相等,假设样本均值为m(mean), 标准差(standard deviation)为s, 则公式为:

$$
d_{12} = \sqrt{\sum_{k=1}^n(\frac{x_{1k}-x_{2k}}{s_k})^2}
$$

余弦距离(Cosine Distance): 夹角余弦取值范围为[-1, 1], 余弦越大表示两个向量夹角越小,当两个向量的方向重合时值为1, 相反为-1,用来衡量样本间的差异

汉明距离(Hamming Distance): 一个字符串到另一个字符串需要变换几个字母,进行统计

杰卡德距离(Jaccard Distance): 通过交并集进行统计

马氏距离(Mahalanobis Distance): 通过样本分布进行计算

7.3. K值选择

过小:容易受到异常点的影响,容易过拟合

过大:受到样本均衡的问题,容易欠拟合

7.4. KD树

8. 线性回归

9. 逻辑回归

10. 决策树算法

11. 集成学习

12. 聚类算法