1、机器学习导论 8、核方法
2、KNN及其实现 9、稀疏表示
3、K-means聚类 10、高斯混合模型
4、主成分分析 11、嵌入学习
5、线性判别分析 12、强化学习
6、贝叶斯方法 13、PageRank
7、逻辑回归 14、深度学习
维数灾难最早是由理查德·贝尔曼(Richard E. Bellman)在考虑优化问题时提出来的 ,它用来描述当(数学)空间维度增加时,分析和组织高维空间(通常有成百上千维)中的数据,因体积指数增加而遇到各种问题场景。
维数灾难这个概念具有的共同特点是:当维度增加时,空间的体积增加得很快,使得可用的数据变得稀疏。
生活中多维数据比较的例子很多,比如人的三围及身高体重、游戏角色的六维属性等等。我们拿大家最熟悉的成绩来说,小学时,我们可能只有语数英三科(三维),想要和小伙伴比较成绩,关键看到底是哪一个科目(某一特征值)具体影响了我们之间的差距,因为科目不多,还比较容易,但到了中学,我们可能要学八科、九科、十科…,身边小伙伴也变多了,想要比较起来就没有之前那么容易了,而当分析某一数学问题时,可能有成百上千维的数据,样本个数也不在少数,那么总体分析就显得举步维艰。因此,我们就想让数据变得简单一些,就有了维数约简思想。
维数约简又称降维,是机器学习的一种必要手段。若数据 X = X= X={ x i x_i xi} 是属于 n n n 维空间的,通过特征提取或者特征选择的方法,将原空间的维数降至 k k k 维,要求 k k k 远小于 n n n,并满足: k k k 维空间的特性能反映原空间数据的特征,这个过程称之为维数约简
维数约简即通过某种数学变换,将原始高维属性空间转变为一个低维子空间,在这个子空间中样本密度大幅度提高,距离计算也变得容易起来
由线性代数的知识我们知道,空间维度的改变依赖于变换矩阵,如 X X X 是一个 n n n 维列向量 X = [ 1 , 2 , . . . , n ] T X=[1,2,...,n]^T X=[1,2,...,n]T,我们想要把它变成 Y = [ 1 , 2 , . . . , m ] T Y=[1,2,...,m]^T Y=[1,2,...,m]T,即在 X X X 前面乘上一个 m × n m×n m×n 的变换矩阵 A A A
而主成分分析,就是降维里的一种重要方法。
既然要对已有的特征值进行降维变换,那么首先,我们要先得到原样本集的特征值,回顾一下线性代数的知识。
有一个 n n n 阶矩阵 A A A,若存在数 λ λ λ 和非零 n n n 维列向量 X X X,满足 A X = λ X AX=λX AX=λX,则称 λ λ λ 为 A A A 的一个特征值, X X X 为 A A A 的对应于 λ λ λ 的一个特征向量
主成分分析(Principal Component Analysis) 的出发点是从一组特征 ( n n n 维)中计算出一组按重要性从大到小排列的新特征( k k k 维, k ≤ n k≤n k≤n,通常取远小于 n n n),它们是原有特征的线性组合,并且相互之间不相关。(比如你和小伙伴的理科成绩非常接近,那么决定你们之间差距的主要科目 (新特征值PC) 就是文科类的了,只关注这几科,即降维了)
1. 源于质心的矢量
2. 主成分 ① 指向最大方差的方向
3. 各后续主成分与前一主成分正交,且指向残差(剩余)子空间最大方差的方向
为了便于分析说明,我们举二维样本集的例子:
如下图所示,红色的两向量表示“蓝色椭圆”的长轴短轴,很明显可以看出,假如我们把样本集的点投影到长轴上,更能反映出样本集整体的分布,故在这个例子里我们把长轴记为主成分#1,与长轴正交(互不相关)的短轴记为主成分#2,理想情况下,短轴的模(高维情况下称范数)为 0,即仅通过长轴就可以完全分析出样本集的分布,这就实现了完美的降维,因而我们容易知道,长短轴的模(范数)相差越大,即降维的效果越好,所以我们的目标就是,找出尽量长的长轴(标号靠前的主成分)
通常,我们认为信号具有较大的方差,噪声具有较小的方差,信噪比就是信号与噪声的功率之差( 10 l g ( P s P n ) 10lg(\frac{P_s}{P_n}) 10lg(PnPs)),越大越好。如下图所示,我们把紫色线上的数据认为是信号,而蓝色线上的数据认为是噪声,因此我们的目的就是最大化投影数据的方差(样本点在紫线上最分散),最小化数据点与投影之间的均方距离(蓝线和越小)
PCA 的目的就是“降噪”和“去冗余”。
“降噪”即使保留下来的维度间的相关性尽可能小
“去冗余”即使保留下来的维度含有的方差(能量)尽可能大
输入:样本集 { x i xi xi} i = 1 n ^n_{i=1} i=1n,低维空间维数 k k k(即所要保留的新特征值个数)
输出:投影矩阵 W = [ w 1 , w 2 , . . . , w k ] W=[w_1,w_2,...,w_k] W=[w1,w2,...,wk]
下面介绍两种 PCA 的实现方法:
1.对所有样本进行中心化(和期望作差) x i ← x i − 1 n ∑ i = 1 n x i x_i←x_i-\frac{1}{n}∑^n_{i=1}x_i xi←xi−n1i=1∑nxi
2.对中心化的数据 { x 1 , x 2 , . . . , x n x_1,x_2,...,x_n x1,x2,...,xn},计算主成分#1:(即目标函数)
w 1 = arg m a x ∣ ∣ w 1 ∣ ∣ = 1 1 n ∑ i = 1 n ( w 1 T x i ) 2 w_1=\arg \underset{||w_1||=1}{max}\frac{1}{n}∑^n_{i=1}(w^T_1x_i)^2 w1=arg∣∣w1∣∣=1maxn1i=1∑n(w1Txi)2
w 1 T x i w^T_1x_i w1Txi 即内积运算( w 1 w_1 w1 为单位向量),求的是 x i x_i xi 在 w 1 w_1 w1 上的投影,平方是为了省去求绝对值
利用拉格朗日乘数法求解最优 λ λ λ,约束条件为 ∣ ∣ w ∣ ∣ = 1 ||w||=1 ∣∣w∣∣=1(即 w T w = 1 w^Tw=1 wTw=1)
L ( w , λ ) = 1 n ( w T x i ) 2 − λ ( w T w − 1 ) L(w,λ)=\frac{1}{n}(w^Tx_i)^2-λ(w^Tw-1) L(w,λ)=n1(wTxi)2−λ(wTw−1)
(矩阵求导)对 w w w求导
∂ L ∂ w = ( 1 n ∑ i = 1 n x i x i T ) w − λ w \frac{\partial L}{\partial w}=(\frac{1}{n}∑^n_{i=1}x_ix_i^T)w-λw ∂w∂L=(n1i=1∑nxixiT)w−λw
实际上,令 X = [ x 1 , x 2 , . . . , x n ] X=[x_1,x_2,...,x_n] X=[x1,x2,...,xn],则 X X T = 1 n ∑ i = 1 n x i x i T XX^T=\frac{1}{n}∑^n_{i=1}x_ix_i^T XXT=n1∑i=1nxixiT
3.最大化投影方差
w k = arg m a x ∣ ∣ w 1 ∣ ∣ = 1 1 n ∑ i = 1 n [ w k T ( x i − ∑ j = 1 k − 1 w j w j T x i ⏟ x i ′ ) ] 2 w_k=\arg \underset{||w_1||=1}{max}\frac{1}{n}∑^n_{i=1}[w^T_k(\underbrace{x_i-∑^{k-1}_{j=1}w_jw_j^Tx_i}_{\text{$x_i'$}})]^2 wk=arg∣∣w1∣∣=1maxn1i=1∑n[wkT(xi′ xi−j=1∑k−1wjwjTxi)]2
后面一串 x i − ∑ j = 1 k − 1 w j w j T x i x_i-∑^{k-1}_{j=1}w_jw_j^Tx_i xi−∑j=1k−1wjwjTxi 可以简单点理解为,扣掉前面那个主成分的方向,在剩下的残差子空间里求新的主成分
1.对所有样本进行去中心化(和期望作差) x i ← x i − 1 n ∑ i = 1 n x i x_i←x_i-\frac{1}{n}∑^n_{i=1}x_i xi←xi−n1i=1∑nxi
2.计算样本的协方差矩阵 C C C
C = ( c i j ) n × n = [ c 11 c 12 . . . c 1 n c 21 c 22 . . . c 2 n . . . . . . . . . . . . c n 1 c n 2 . . . c n n ] C=(c_{ij})_{n×n}=\left[ \begin{matrix} c_{11} & c_{12} & ... & c_{1n}\\ c_{21} & c_{22} & ... & c_{2n} \\ ... & ... & ... & ... \\ c_{n1} & c_{n2} & ... & c_{nn} \end{matrix} \right] C=(cij)n×n=⎣⎢⎢⎡c11c21...cn1c12c22...cn2............c1nc2n...cnn⎦⎥⎥⎤
c i j = C o v ( X i , Y j ) c_{ij}=Cov(X_i,Y_j) cij=Cov(Xi,Yj) i , j = 1 , 2 , . . . , n i,j=1,2,...,n i,j=1,2,...,n
(对角线元素为某一维度的方差)
3.对协方差矩阵C做特征值分解(即求所有满足的特征值和特征向量) C W ′ = λ W ′ CW'=λW' CW′=λW′(也可以用拉格朗日乘数法只求所需的最大的 k k k 个)
4.取最大的 k k k 个特征值所对应的特征向量 w 1 , w 2 , . . . , w k w_1,w_2,...,w_k w1,w2,...,wk
比较详细的 PCA 数学推导过程 主成分分析(PCA)原理详解
——————————这节课的理论理解是真的费劲啊!————————
1.给定的图像数据集,可视化并输出聚类性能(上节课还想偷懒,没想到该来的这么快就来了)
2.给定的图像数据集,计算相应的特征脸(Eigenfaces)
注:不是每一组 20 张算一个特征脸,是 200 张取前十个特征脸(这特征脸有点恐怖,不是说好提取完是张伟吗)
3.给定图像数据集,探讨 PCA 降维后特征个数与聚类性能的关系
1、今天要用到 python 的库 cv2(版本更新被合并到 opencv_python 里了),提前装一下
pip install opencv_python -i https://pypi.tuna.tsinghua.edu.cn/simple
import matplotlib.pyplot as plt
import os
import cv2 as cv
import numpy as np
from sklearn.cluster import KMeans
from PIL import Image
from ML_clustering_performance import clusteringMetrics
path = 'C:/Users/1233/Desktop/Machine Learning/face_images/'
h, w = 200, 180
IMAGE_COLUMN = 20 # 列
IMAGE_ROW = 10 # 行
to_image = Image.new('RGB', (IMAGE_COLUMN * w, IMAGE_ROW * h))
def createDatabase(path):
# 查看路径下所有文件
TrainFiles = os.listdir(path) # 遍历每个子文件夹
# 计算有几个文件(图片命名都是以 序号.jpg方式)
Train_Number = len(TrainFiles) # 子文件夹个数
train = []
y_sample = []
# 把所有图片转为1维并存入T中
for k in range(0, Train_Number):
Trainneed = os.listdir(path + '/' + TrainFiles[k]) # 遍历每个子文件夹里的每张图片
Trainneednumber = len(Trainneed) # 每个子文件里的图片个数
for i in range(0, Trainneednumber):
img = Image.open(path + '/' + TrainFiles[k] + '/' + Trainneed[i])
to_image.paste(img, (i * w, k * h)) # 把读出来的图贴到figure上
image = cv.imread(path + '/' + TrainFiles[k] + '/' + Trainneed[i]).astype(np.float32) # 数据类型转换
image = cv.cvtColor(image, cv.COLOR_RGB2GRAY) # RGB变成灰度图
train.append(image)
y_sample.append(k)
train = np.array(train)
y_sample = np.array(y_sample)
return train, y_sample
# n_samples, h, w = 200, 200, 180
X, y = createDatabase(path)
# print(X.shape)
X_ = X.reshape(X.shape[0], h*w)
kms = KMeans(n_clusters=10)
y_sample = kms.fit_predict(X_, y)
print(clusteringMetrics(y, y_sample))
plt.imshow(to_image)
plt.show()
( ↓ ↓ ↓别人家的代码系列)
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import matplotlib.image as imgplt
import os
import pandas as pd
from ML_clustering_performance import clusteringMetrics
name = []
target = []
def getimage():
# 获取文件并构成向量
# 预测值为1维,把一张图片的三维(RGB)压成1维,那么n张图片就是二维
global total_photo
file = os.listdir('C:\\Users\\1233\\Desktop\\Machine Learning\\face_images') # 遍历face_images里每个子文件夹
i = 0
for subfile in file:
photo = os.listdir('C:\\Users\\1233\\Desktop\\Machine Learning\\face_images\\' + subfile) # 遍历每个子文件夹里的照片
for name in photo:
photo_name.append('C:\\Users\\1233\\Desktop\\Machine Learning\\face_images\\' + subfile+'\\'+name)
target.append(i)
i += 1
print(photo_name)
for path in photo_name:
photo = imgplt.imread(path)
# photo = cv.imread(path)
photo = photo.reshape(1, -1)
photo = pd.DataFrame(photo)
total_photo = total_photo.append(photo, ignore_index=True)
total_photo = total_photo.values
def kmeans():
clf = KMeans(n_clusters=10)
clf.fit(total_photo)
y_predict = clf.predict(total_photo)
centers = clf.cluster_centers_
result = centers[y_predict]
result = result.astype("int64")
result = result.reshape(200, 200, 180, 3) # 图像的矩阵大小为200,180,3
return result, y_predict
def draw():
fig, ax = plt.subplots(nrows=10, ncols=20, sharex=True, sharey=True, figsize=[15, 8], dpi=80)
plt.subplots_adjust(wspace=0, hspace=0)
count = 0
for i in range(10):
for j in range(20):
ax[i, j].imshow(result[count])
count += 1
plt.show()
def score():
print(clusteringMetrics(target, y_predict))
total_photo = pd.DataFrame()
getimage()
result, y_predict = kmeans()
draw()
score()
2、直接放代码吧,PCA 理论分析比较难,但用起来挺简单的,学着别人的例子用改改参数就行了(Python 真香)
参考了 Scikit-learn实例之Pca+Svm人脸识别(AT&T数据集)
import matplotlib.pyplot as plt
import os
import cv2 as cv
import numpy as np
from sklearn.decomposition import PCA
path = 'C:/Users/1233/Desktop/Machine Learning/face_images/'
h, w = 200, 180
def createDatabase(path):
TrainFiles = os.listdir(path)
Train_Number = len(TrainFiles)
train = []
y_sample = []
for k in range(0, Train_Number):
Trainneed = os.listdir(path + '/' + TrainFiles[k])
Trainneednumber = len(Trainneed)
for i in range(0, Trainneednumber):
image = cv.imread(path + '/' + TrainFiles[k] + '/' + Trainneed[i]).astype(np.float32)
image = cv.cvtColor(image, cv.COLOR_RGB2GRAY)
train.append(image)
y_sample.append(k)
train = np.array(train)
y_sample = np.array(y_sample)
return train, y_sample
# n_samples, h, w = 200, 200, 180
X, y = createDatabase(path)
X_ = X.reshape(X.shape[0], h*w)
# 从200张图里挑出特征值前10的特征脸
n_components = 10
pca = PCA(n_components).fit(X_) # svd_solver='randomized', whiten=True
eigenfaces = pca.components_.reshape((n_components, h, w))
# 将输入数据投影到特征面正交基上
X_train_pca = pca.transform(X_)
def plot_gallery(images, titles, h, w, n_row=1, n_col=10):
"""Helper function to plot a gallery of portraits"""
plt.figure(figsize=(1.8 * n_col, 2 * n_row))
plt.subplots_adjust(bottom=0, left=.01, right=.99, top=.90, hspace=.35) # 图片位置布局
for i in range(10):
plt.subplot(n_row, n_col, i + 1)
plt.imshow(images[i].reshape((h, w)))
# plt.imshow(images[i].reshape((h, w)), cmap=plt.cm.gray)
plt.title(titles[i], size=12)
# 把坐标去了
plt.xticks(())
plt.yticks(())
eigenface_titles = ["eigenface %d" % (i+1) for i in range(eigenfaces.shape[0])]
plot_gallery(eigenfaces, eigenface_titles, h, w)
plt.show()
效果图
不需要用到 opencv,直接用 matplotlib 的相关函数求特征脸
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
import matplotlib.image as imgplt
import os
import pandas as pd
path = 'C:/Users/1233/Desktop/Machine Learning/face_images/'
n_row, n_col = 1, 10
n_components = n_row * n_col
image_shape = (200, 540)
photo_name = []
target = []
total_photo = pd.DataFrame()
def getinfo(path):
# 获取文件并构成向量
# 预测值为1维,把一张图片的三维压成1维,那么n张图片就是二维
global total_photo
file = os.listdir(path)
# 遍历每个图片
for subfile in file:
photo = os.listdir(path + subfile)
for name in photo:
photo = imgplt.imread(path + subfile + '/' + name)
photo = photo.reshape(1, -1)
photo = pd.DataFrame(photo)
total_photo = total_photo.append(photo, ignore_index=True)
total_photo = total_photo.values
getinfo(path)
faces = total_photo
def plot_gallery(images, title, n_col=n_col, n_row=n_row):
plt.figure(figsize=(1.8 * n_col, 2 * n_row))
plt.subplots_adjust(bottom=0, left=.01, right=.99, top=.90, hspace=.35)
plt.suptitle(title, size=16)
for i, comp in enumerate(images):
plt.subplot(n_row, n_col, i + 1)
# vmax = max(comp.max(), -comp.min())
plt.imshow(comp.reshape(image_shape)) # cmap=plt.cm.gray interpolation='nearest', vmin=-vmax, vmax=vmax
plt.xticks(())
plt.yticks(())
estimators = [("", PCA(n_components=10, whiten=True))]
for name, estimator in estimators:
# print("Extracting the top %d %s..." % (n_components, name))
# print(faces.shape)
estimator.fit(faces)
components_ = estimator.components_
plot_gallery(components_[:n_components], name)
plt.show()
效果图(跑出来效果差一点,应该是有地方修改的,改半天没搞定,先放着了)
3、循环聚类下画个图就OK了
import matplotlib.pyplot as plt
import os
import cv2 as cv
import numpy as np
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from PIL import Image
from ML_clustering_performance import clusteringMetrics
path = 'C:/Users/1233/Desktop/Machine Learning/face_images/'
h, w = 200, 180
IMAGE_COLUMN = 20
IMAGE_ROW = 10
def createDatabase(path):
TrainFiles = os.listdir(path)
Train_Number = len(TrainFiles)
train = []
y_sample = []
for k in range(0, Train_Number):
Trainneed = os.listdir(path + '/' + TrainFiles[k])
Trainneednumber = len(Trainneed)
for i in range(0, Trainneednumber):
img = Image.open(path + '/' + TrainFiles[k] + '/' + Trainneed[i])
image = cv.imread(path + '/' + TrainFiles[k] + '/' + Trainneed[i]).astype(np.float32)
image = cv.cvtColor(image, cv.COLOR_RGB2GRAY)
train.append(image)
y_sample.append(k)
train = np.array(train)
y_sample = np.array(y_sample)
return train, y_sample
# n_samples, h, w = 200, 200, 180
X, y = createDatabase(path)
X_ = X.reshape(X.shape[0], h*w)
n_components = 10
ACCS = []
NMIS = []
ARIS = []
for i in range(1, 9):
n_components = i
pca = PCA(n_components=n_components).fit(X_) # svd_solver='randomized', whiten=True
eigenfaces = pca.components_.reshape((n_components, h, w))
# 将输入数据投影到特征面正交基上
X_train_pca = pca.transform(X_)
# 聚类
kms = KMeans(n_clusters=10)
y_sample = kms.fit_predict(X_train_pca, y)
ACC, NMI, ARI = clusteringMetrics(y, y_sample)
ACCS.append(ACC)
NMIS.append(NMI)
ARIS.append(ARI)
fig, ax = plt.subplots()
bar_width = 0.35
opacity = 0.4 # 不透明度
index = np.arange(8)
# error_config = {'ecolor': '0.3'}
rects1 = ax.bar(index, ACCS, bar_width, alpha=opacity, color='r', label='ACC') # error_kw=error_config
rects2 = ax.bar(index + bar_width, NMIS, bar_width, alpha=opacity, color='g', label='NMI')
rects3 = ax.bar(index + 2*bar_width, ARIS, bar_width, alpha=opacity, color='b', label='ARI')
ax.set_xticks(index + bar_width / 2)
ax.set_xticklabels(('1', '2', '3', '4', '5', '6', '7', '8'))
ax.legend()
plt.show()