文章目录
url
https://download.csdn.net/download/qq_34405401/12208225
1.机器学习常用算法
- 监督
- 线性回归
- 逻辑回归 (正则化)
- SVM(支撑向量机support Vector Machine)
- DT(决策树)
- 集成算法
- 随机森林
- XGBoost
- k-NN
- Bayes分类
- 无监督
- PCA
- 规则关联(推荐)
- k-Means
2.以线性回归为例进行机器学习入门
2.1 numpy实现
- 线性回归的场景
- 数据呈现正比关系。
- 线性回归举例(身高与年龄的关系):
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
# 读取数据
age = np.loadtxt('ex2x.dat')
tall = np.loadtxt('ex2y.dat')
# 用数据画一个散点图
figure = plt.figure(1, figsize=(5, 4))
ax = figure.add_axes([0.1, 0.1, 0.8, 0.8], title='年龄与身高')
#下面设置x轴,x轴是年龄,left=1.0代表最小一岁,right=10.0代表最大十岁
ax.set_xlim(left=1.0, right=10)
#设置y轴,y轴是身高,最低0.5,最高1.5
ax.set_ylim(bottom=0.5, top=1.5)
ax.scatter(x=age, y=tall, color='blue')
plt.show()
# 简单分析数据
- 结论:
- 年龄与身高成正比关系。
- 学习目标:
- 找出一条直线,使得点尽可能在直线周围。
- 建模
- y i = w 1 ∗ x i + w 2 ∗ 1 y_i = w_1 \ast x_i + w_2 \ast 1 yi=w1∗xi+w2∗1
- 最优的w1与w2
- 简化模式:线性回归的数学模型:(即令w最后多一列1,把w2放入x最后一列)
- $ y = W \cdot x$
- 理论模型与现实测量数据存在误差
- ϵ = y − y ′ \epsilon = y - y ^ \prime ϵ=y−y′
- 测量的样本与理想模型计算的数据存在误差,而且是误差平方和最小。(不靠谱)
- ϵ = ∑ i = 1 , ⋯ , N ( y i − y i ′ ) 2 \epsilon = \sum \limits _{i=1,\cdots, N} (y_i - y_i ^\prime)^2 ϵ=i=1,⋯,N∑(yi−yi′)2
- 理论基础
- 测量误差:误差服从高斯分布:中心点是正确值,越接近中心点(正确值)概率越大。
- L = ∏ i p ( ϵ ∣ x i ) L = \prod \limits _i p(\epsilon | x_i) L=i∏p(ϵ∣xi)
- 损失函数(误差函数)的最优计算
- 求极小值点(数学求解问题)
- 代码中已有求解损失函数的算法。这些算法封装成模块,叫:优化器
- 最小化损失函数的一些常用算法:
- 最小二乘法。
- 梯度下降法。
- 坐标下降法。
- 牛顿迭代法。
- 拟牛顿法
- …
上面身高-年龄线性模型求解(继续上面的代码,使用最小二乘法求W):
import numpy.linalg as ln
#需要的训练数据age、tall已获取,打印查看它们的类型
print(age.shape,tall.shape)
(50,) (50,)
#上面输出的(50,)意味着一维数组,数组中有50个元素;若是(50,1)那就是二维数组,即50行1列
#我们需要把数据转成矩阵,意味着二维数组
X = np.zeros(shape=(age.shape[0], 2), dtype=np.float)#此处X是两列是因为对应上面的 6.简化模型,即最后一列都是1
Y = tall.reshape(tall.shape[0], 1)#即转成矩阵(二维数组)的50行1列形式
#X=np.zeros()中的元素都是0,因此需要克隆数据
X[:, 0] = age
X[:, 1] = 1 #最后一列都是1
W计算公式: W = ( X T X ) − 1 X T Y W = (X^T X)^{-1}X^TY W=(XTX)−1XTY
W = np.matmul(np.matmul(ln.inv(np.matmul(X.T, X)), X.T), Y)
print(W)
[[0.06388117]
[0.75016254]]
预测的Y(tall)的计算公式: $Y = X W $
#我们要把学习得到的线性模型画出来,再把原来的真实数据散点图也画出来,看看点是否在习得模型的周围
#画线性模型可以用真实数据的x(age)和预测y(tall)来画,也可以再生成50个x,带入线性模型中求y,并画出模型
#在0到10岁之间生成50个点
X_AX = np.linspace(0, 10, 50, dtype=np.float)
#格式处理
X_X = np.zeros(shape=(X_AX.shape[0], 2), dtype=np.float) # 构造连续50个样本-年龄
X_X[:, 0] = X_AX
X_X[:, 1] = 1
#求出预测值Y_X
Y_X = np.matmul(X_X, W)
#画出线性模型
fig = plt.figure(1, figsize=(5, 4))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], title="训练模型")
ax.set_xlim(0,10)
ax.set_ylim(0, 1.7)
ax.plot(X_AX, Y_X, color='blue')
#画出真实值的散点图
ax.scatter(x=age, y=tall, color='red')
plt.show()
- 11.结果比较
- 回归模型比较真实值与理想值之间的拟合关系:相关系数
- r ( Y ′ , Y ) = c o v ( Y ′ , Y ) V a r ( Y ′ ) V a r ( Y ) r(Y ^ \prime, Y) = \dfrac{cov(Y^\prime,Y)}{\sqrt{Var(Y ^ \prime)Var(Y)}} r(Y′,Y)=Var(Y′)Var(Y)cov(Y′,Y)
Y_ = np.matmul(X, W)#Y_是真实数据X的预测值
r = np.corrcoef(Y.T, Y_.T)#比较预测的Y和真实的Y_
print(r)
[[1. 0.92631702]
[0.92631702 1. ]]
总结:
先确定模型,然后根据误差概率模型确定损失函数,再选择优化器最小化损失函数,最后模型编程。
2.2 sklearn实现
from sklearn.linear_model import LinearRegression
# 1. 对象构建
regressor = LinearRegression()
# 2. fit是训练
regressor.fit(X, Y) # sklearn提供数据格式的自动处理,但是要求我们形成数据格式的规范。
# 3. 预测
Y_PRE = regressor.predict(X)
#coef是系数,此时对应W;intercept是截距
print(regressor.coef_, regressor.intercept_)
[[0.06388117 0. ]] [0.75016254]
#评估预测的拟合情况
score = regressor.score(X, Y)
print(score)
0.858063223720823
3.图像分类
分类算法有:SVM、Logistic、PCA等
3.1 支持向量机分类
import numpy as np
#机器视觉方面使用opencv
import cv2
# 读取图像
img_test = cv2.imread("./att_faces/s1/1.pgm")
print(img_test.shape)
(112, 92, 3)
#每张图片的形状为112行(高),92列(长),3为深度即带三个颜色通道
#接下来展示这张图片
%matplotlib inline
import matplotlib.pyplot as plt
#cmap=plt.cm.gray是按灰度展示
plt.imshow(img_test, cmap=plt.cm.gray)
plt.show()
# 接下来读取图像到矩阵,一共有四百张图
# 定义常量
#每个人有十张自己的图像
ONE_PERSON_FACE_NUM = 10
#一共有40个人
PERSON_NUM = 40
#图像数量自然是40*10
SAMPLE_NUM = ONE_PERSON_FACE_NUM * PERSON_NUM
#每张图像高112,宽92
IMG_W = 92
IMG_H = 112
#定义存放图像信心的矩阵
#因为有400张图,因此行是SAMPLE_NUM,列是每张图的信息,最后效果是一行代表一张图
data_faces = np.zeros(shape=(SAMPLE_NUM, IMG_W * IMG_H), dtype=np.int32)
#一行代表一个图片的类别,因此只需要一列
label_faces = np.zeros(shape=(SAMPLE_NUM, 1), dtype=np.int32)
#把图片信息复制到矩阵中
idx = 0 # 数据集的位置,即在哪个文件夹
for i in range(1, PERSON_NUM + 1): # 40个人的目录,此处是使角标从1到PERSON_NUM,因为range不包含PERSON_NUM,所以得+1
for j in range(1, ONE_PERSON_FACE_NUM + 1):
path_ = "./att_faces/s{i}/{j}.pgm".format(i=i,j=j)
img_ = cv2.imread(path_)
#因为读取的是三通道图像,为了大大减少计算量,转化为灰度图像(因为做图像识别,颜色没有太大价值,所以可转灰度)
gray_ = cv2.cvtColor(img_, cv2.COLOR_BGR2GRAY)
data_faces[idx, :] = gray_.reshape(IMG_W * IMG_H)
label_faces[idx, :] = i
idx += 1
print(data_faces.shape,label_faces.shape)
(400, 10304) (400, 1)
#此时图像转矩阵完毕,查看矩阵是否信息正确
#查看矩阵里的最后一张图像
plt.imshow(data_faces[-1:].reshape((IMG_H, IMG_W)), cmap='gray')
plt.show()
#查看文件夹存放的最后一张
img_test = cv2.imread("./att_faces/s40/10.pgm")
plt.imshow(img_test, cmap=plt.cm.gray)
plt.show()
#确定矩阵信息正确,接下来对图像进行预处理,即PCA降维,其中会自动归一化
#降维的原因是原先数据维度太高,特征太多;且经实验降到20维效果最好
from sklearn.decomposition import PCA
#降到20维
n_dims = 20
# 训练,whiten为白化,svd_solver为奇异值分解
pca = PCA(n_components=n_dims, whiten=True, svd_solver='randomized')
# 用data_faces来训练得到降维后的特征
pca.fit(data_faces)
#将降维后得到的第一个人脸特征显示出来,并打出来
eg_faces = pca.components_.reshape((n_dims, IMG_H, IMG_W))
plt.imshow(eg_faces[0], cmap='gray')
plt.show()
print(eg_faces[0])
[[-0.00212508 -0.00211277 -0.0021425 ... -0.00192885 -0.00195297
-0.00202584]
[-0.00215919 -0.00206477 -0.00235067 ... -0.00176855 -0.00173679
-0.00189663]
[-0.0019191 -0.00201744 -0.00217899 ... -0.0018383 -0.00174359
-0.00175921]
...
[-0.01346525 -0.01375571 -0.01361521 ... -0.00615034 -0.00604953
-0.00588547]
[-0.01411743 -0.01450171 -0.01444153 ... -0.00682447 -0.00679768
-0.00701538]
[-0.01481082 -0.01578775 -0.01547279 ... -0.00704006 -0.00639096
-0.00734479]]
#查看降维后所有的人脸特征
rows = 5
cols = 4
plt.figure(figsize=(1.8 * cols, 2.4 * rows))
for i in range(n_dims):
ax = plt.subplot(rows, cols, i+1)
plt.imshow(eg_faces[i], cmap="gray")
plt.xticks(())
plt.yticks(())
plt.show()
#通过上述对降维的训练,已经得出了20个特征脸,接下来将数据降维成20维
#此处用data_faces训练,用data_faces降维,这样做不好;其实应该用一部分数据训练,然后对所有数据降维
pca_data = pca.transform(data_faces)
print(pca_data.shape)
(400, 20)
#调用逻辑回归进行分类,SVC是支持向量机分类运算
from sklearn.svm import SVC
classifier = SVC(kernel='rbf', C=1000, gamma=0.1)
#训练
classifier.fit(pca_data, label_faces[:,0])
#预测,用训练的数据进行预测,不太好
pre_labels = classifier.predict(pca_data)
#打印预测的类
print(pre_labels)
[ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3
3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5
5 5 6 6 6 6 6 6 6 6 6 6 7 7 7 7 7 7 7 7 7 7 8 8
8 8 8 8 8 8 8 8 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10
10 10 10 10 11 11 11 11 11 11 11 11 11 11 12 12 12 12 12 12 12 12 12 12
13 13 13 13 13 13 13 13 13 13 14 14 14 14 14 14 14 14 14 14 15 15 15 15
15 15 15 15 15 15 16 16 16 16 16 16 16 16 16 16 17 17 17 17 17 17 17 17
17 17 18 18 18 18 18 18 18 18 18 18 19 19 19 19 19 19 19 19 19 19 20 20
20 20 20 20 20 20 20 20 21 21 21 21 21 21 21 21 21 21 22 22 22 22 22 22
22 22 22 22 23 23 23 23 23 23 23 23 23 23 24 24 24 24 24 24 24 24 24 24
25 25 25 25 25 25 25 25 25 25 26 26 26 26 26 26 26 26 26 26 27 27 27 27
27 27 27 27 27 27 28 28 28 28 28 28 28 28 28 28 29 29 29 29 29 29 29 29
29 29 30 30 30 30 30 30 30 30 30 30 31 31 31 31 31 31 31 31 31 31 32 32
32 32 32 32 32 32 32 32 33 33 33 33 33 33 33 33 33 33 34 34 34 34 34 34
34 34 34 34 35 35 35 35 35 35 35 35 35 35 36 36 36 36 36 36 36 36 36 36
37 37 37 37 37 37 37 37 37 37 38 38 38 38 38 38 38 38 38 38 39 39 39 39
39 39 39 39 39 39 40 40 40 40 40 40 40 40 40 40]
#查看预测的准确率,此处是100%正确
corr_num = (pre_labels == label_faces[:,0]).sum()
corr_num/=400.0
print(corr_num)
1.0
4.分类算法的评判标准
- 识别准确率:
- 误识率:(FAR)是指在标准指纹数据库上测试指纹识别算法时,不同指纹的匹配分数大于给定阈值,从而被认为是相同指纹的比例,简单地说就是“把不应该匹配的指纹当成匹配的指纹”的比例。
- 拒识率:(FRR)是指在标准指纹数据库上测试指纹识别算法时,相同指纹的匹配分数低于给定阈值,从而被认为是不同指纹的比例,简单地说就是 “把应该相互匹配成功的指纹当成不能匹配的指纹”的比例。
- 度量模式:
- 混淆矩阵
- 分类报告
- 精确度得分
采用上面图像分类程序作为例子
# 混淆矩阵
from sklearn.metrics import confusion_matrix
matrix = confusion_matrix(pre_labels, label_faces[:,0])
print(matrix)
[[10 0 0 ... 0 0 0]
[ 0 10 0 ... 0 0 0]
[ 0 0 10 ... 0 0 0]
...
[ 0 0 0 ... 10 0 0]
[ 0 0 0 ... 0 10 0]
[ 0 0 0 ... 0 0 10]]
# 分类报告
from sklearn.metrics import classification_report
report = classification_report(pre_labels, label_faces[:,0])
print(report)
precision recall f1-score support
1 1.00 1.00 1.00 10
2 1.00 1.00 1.00 10
3 1.00 1.00 1.00 10
4 1.00 1.00 1.00 10
5 1.00 1.00 1.00 10
6 1.00 1.00 1.00 10
7 1.00 1.00 1.00 10
8 1.00 1.00 1.00 10
9 1.00 1.00 1.00 10
10 1.00 1.00 1.00 10
11 1.00 1.00 1.00 10
12 1.00 1.00 1.00 10
13 1.00 1.00 1.00 10
14 1.00 1.00 1.00 10
15 1.00 1.00 1.00 10
16 1.00 1.00 1.00 10
17 1.00 1.00 1.00 10
18 1.00 1.00 1.00 10
19 1.00 1.00 1.00 10
20 1.00 1.00 1.00 10
21 1.00 1.00 1.00 10
22 1.00 1.00 1.00 10
23 1.00 1.00 1.00 10
24 1.00 1.00 1.00 10
25 1.00 1.00 1.00 10
26 1.00 1.00 1.00 10
27 1.00 1.00 1.00 10
28 1.00 1.00 1.00 10
29 1.00 1.00 1.00 10
30 1.00 1.00 1.00 10
31 1.00 1.00 1.00 10
32 1.00 1.00 1.00 10
33 1.00 1.00 1.00 10
34 1.00 1.00 1.00 10
35 1.00 1.00 1.00 10
36 1.00 1.00 1.00 10
37 1.00 1.00 1.00 10
38 1.00 1.00 1.00 10
39 1.00 1.00 1.00 10
40 1.00 1.00 1.00 10
accuracy 1.00 400
macro avg 1.00 1.00 1.00 400
weighted avg 1.00 1.00 1.00 400
# 精确度得分
from sklearn.metrics import accuracy_score
acc = accuracy_score(pre_labels, label_faces[:,0])
print(acc)
1.0
5.交叉验证+参数调优(网格搜索)
- 样本数据集划分为:训练集、测试集
- 划分方案:
- 直接分
- n-折
- 划分方案:
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split,GridSearchCV
from sklearn.svm import SVC
#加载数据集
data,target=datasets.load_iris(return_X_y=True)
print(data.shape)
#交叉验证:训练集+测试集
#test_size=0.2,测试集是原数据规模的0.2
data_train,data_test,target_train,target_test=train_test_split(data,target,test_size=0.2)
print(data_train.shape)
#调用机器学习算法完成训练(常规训练+网格搜索训练)
#classifier=SVC(kernel='rbf',C=1000,gamma=0.1) #这个算法参数是固定的
#参数字典
dic_p={
'C':[1,10,100,10000],
'gamma':[0.01,0.1,1],
}
#网格搜索:这个是从参数字典里自动找到最佳参数,即网格搜索
classifier=GridSearchCV(SVC(kernel='rbf'),dic_p)
classifier.fit(data_train,target_train)
#结果
pre=classifier.predict(data_test)
#测试集一共三十个,打印正确预测的个数
print((pre==target_test).sum())
(150, 4)
(120, 4)
30
6.总结
- 模式识别 ,机器学习(机器视觉),神经网络,深度学习关系
- sklearn:机器学习:分类,回归,聚类,模型,降维, 数据预处理:数据分析 -> 数据挖掘
- tensorflow/pytorch: 深度学习
- 机器视觉(图像opencv) + 自然语言(NLTK)