学习内容:主成分分析、PCA算法
源源不断的饼干动力,又开始新的饼干笔记搬运大法
一、PCA的概念
PCA(Principal Component Analysis),即主成分分析方法,是一种使用最广泛的数据降维算法(非监督的机器学习方法),其最主要的用途在于降维,通过分析取主成分显出最大的个别差异。也可以用来削减回归分析的聚类分析中变量的数目
多变量之间可能存在相关性,从而增加了问题分析的复杂性;需要找到一种合理的方法,在减少需要分析的指标的同时,尽量减少原指标包含信息的损失。可以考虑将关系紧密的变量变成尽可能少的新变量,使这些新变量是两两不相关的,那么就可以用较少的综合指标分别代表存在于各个变量中的各类信息。主成分分析与因子分析就属于这类降维算法。
二、PCA的思想
将n维特征映射到k维上,这k维是全新的正交特征也被称为主成分,是在原有n维特征的基础上重新构造出来的k维特征。拥有更高的可区分度,同时还保留着部分映射之前的空间信息。如何找到让样本间距最大的轴?
PCA求梯度
四、PCA代码实现
1.数据准备
import numpy as np
import matplotlib.pyplot as plt
X = np.empty([100,2])#100行2列
X[:,0]= np.random.uniform(0.,100.,size=100)#100个0~100的均匀分布点
X[:,1]= 0.75 * X[:,0] + 3. + np.random.normal(0.,10.,size = 100)
plt.scatter(X[:,0],X[:,1])
plt.show()
2.样本均值归0
def demean(X):
# axis = 0 按列计算均值,即每个属性的均值,1则是计算行的均值
return (X - np.mean(X,axis=0))
X_demean = demean(X)
# 注意看数据分布没变,但是坐标已经以原点为中心了
plt.scatter(X_demean[:, 0], X_demean[:, 1])
plt.show()
3.定义目标函数
def f(w,X):
return np.sum((X.dot(w)**2))/len(X)
def df_math(w,X):
return X.T.dot(X.dot(w))*2./len(X)
4.验证梯度求解
def df_debug(w, X, epsilon=0.0001):
# 先创建一个与参数组等长的向量
res = np.empty(len(w))
# 对于每个梯度,求值
for i in range(len(w)):
w_1 = w.copy()
w_1[i] += epsilon
w_2 = w.copy()
w_2[i] -= epsilon
res[i] = (f(w_1, X) - f(w_2, X)) / (2 * epsilon)
return res
5.w单位向量
def direction(w):
return w / np.linalg.norm(w)
6.梯度上升
# 梯度上升法代码
def gradient_ascent(df, X, initial_w, eta, n_iters=1e4, epsilon=1e-8):
w = direction(initial_w)
cur_iter = 0
while cur_iter < n_iters:
gradient = df_math(w,X)
last_w = w
w = last_w + eta * gradient
w = direction(w) # 将w转换成单位向量
if (abs(f(w,X) - f(last_w,X)) < epsilon):
break
cur_iter += 1
return w
线性回归中,通常将特征系数θ的值设为全部为0的向量。但在主成分分析中w的初始值不能为0!!! 这是因为如果将w=0带入梯度求导的公式中,也是每次求梯度得到的都是没有任何方向的0。所以要设置一组随机数。
7.设置初始值w
initial_w = np.random.random(X.shape[1])
eta = 0.001
w = gradient_ascent(df_debug, X_demean, initial_w, eta)
w
8.可视化w
plt.scatter(X_demean[:,0],X_demean[:,1])
plt.plot([0,w[0]*30],[0,w[1]*30], color='red')
plt.show()
五、求前n个主分析
六、求第二主分析的实现
X_new = X - X.dot(w).reshape(-1,1) * w
plt.scatter(X_new[:,0], X2[:,1])
plt.show()
所有数据把第一主成分的分量去掉,得到的就是与第一主成分的分量垂直的向量。
由于整个数据只有两个维度,第一个维度去掉之后,剩下的第二维度就是所有的内容了。因此样本在第二维度上的分布完全在一条直线上,不再有其他方向上分布的方差。
w_new = gradient_ascent(df_math, X_new, initial_w, eta)
# 输出:
array([-0.64320916, 0.76569052])
w和wnew彼此之间相互垂直,点乘为0.
def first_n_component(n, X, eta=0.001, n_iters=1e4, epsilon=1e-8):
X_pca = X.copy()
X_pca = demean(X_pca)
res = []
for i in range(n):
initial_w = np.random.random(X_pca.shape[1])
w = gradient_ascent(df_math, X_pca, initial_w, eta)
res.append(w)
X_pca = X_pca - X_pca.dot(w).reshape(-1, 1) * w
return res
- 我们使用python对求主成分的思想进行了实现。首先求解了主成分的梯度表达式,然后通过梯度上升法来求得分量。在求解的时候有两个需要注意的地方。一是要在每次计算前对分量进行处理,使其变为模长为1的单位向量。再一个就主成分分析中的初始值不能为0。
- 在二维数据中求得第一主成分分量就够了,对于高维数据需要先将数据集在第一个主成分上的分量去掉,然后在没有第一个主成分的基础上再寻找第二个主成分,依次类推,求出前n个主成分
#######################################################################
@ 2019.12.29 木居居士的机器学习小组 第九周 打卡
安利公益监督学习组织 - 【公众号】数据科学家联盟
https://mp.weixin.qq.com/s/1WWmbLZucz9vIp-4tKKQ5Q
感谢木东大佬、饼干大佬、南头大佬、星空妹砸、Desitiny、DD的无私付出,抱拳ing~