求数据的第一主成分

(在notebook中)

将包加载好,再创建出一个虚拟的测试用例,生成的X有两个特征,特征一为0到100之间随机分布,共一百个样本,对于特征二,其和特征一有一个基本的线性关系(为什么要有一个基本的线性关系?是因为含有一个基本的线性关系,这样对数据降维的效果会更加的明显)

  import numpy as np
import matplotlib.pyplot as plt
X = np.empty((100,2))
X[:,0] = np.random.uniform(0. ,100. , size=100)
X[:,1] = 0.75 * X[:,0] + 3. + np.random.normal(0. ,10. ,size=100)

绘制一下生成的样例

  plt.scatter(X[:,0],X[:,1])

图像如下

具体操作

那么我们就开始进行数据的降维的具体操作

首先我们先进行demean的操作,我们设置一个函数为demean,传来一个X(矩阵),返回均值归0以后所得到的矩阵,具体计算可以使用X减去X的均值即可,需要注意的是,X代表一个矩阵,每一行代表一个样本,那么操作实际上就是每一个样本中的每一个特征都要减去这个特征所对应的均值,所以X减去的应该是个向量(每一个特征所对应的均值,也就是在行方向上去一个均值),其就是每一列的均值,这样就可以得到均值归0以后的样本了

  def demean(X):
return X - np.mean(X,axis=0)

那么我们测试一下这个函数

  X_demean = demean(X)

然后绘制一下这个图

  plt.scatter(X_demean[:,0],X_demean[:,1])

图像如下

可以看出来整体分布是个之前一样的,不过从坐标轴可以看出来,(0,0)大概在中心位置,现在对于这些数据来说,在两个方向上的均值都为0

那么我们可以验证一下是不是这样的

使用np.mean(X_demean[:,0])看一下对于第0维度来说均值是多少,结果如下

使用np.mean(X_demean[:,1])看一下对于第1维度来说均值是多少,结果如下

我们可以看出来,这两个值都是很小的,十分接近0,可以说这两个均值是为0的

使用梯度上升法来求解我们数据的主成分

那么做完均值归零以后,我们就要开始使用梯度上升法来求解我们数据的主成分

求解过程和梯度下降法非常的像

首先我们先设置一下求解目标函数的函数f,传上w和x,只要将X点乘上w,再进行平方和以后除以样本数即可

  def f(w,X):
return np.sum((X.dot(w)**2))/len(X)

我们将求解目标函数对应的梯度的方法设为df_mean(其实应该是叫df_math,打快了没注意),其就是计算的公式的实现,即x的转置点乘上x点乘w乘2再除以样本数

  def df_mean(w,X):
return X.T.dot(X.dot(w))*2. / len(X)

为了验证我们的这个是正确的,使用这个df_debug这个函数,和线性下降法一样,使两个点之间连成的直线不断的靠近应得的直线,使其斜率相当,注意的是,这里的epsilon取值比较小,是因为在PCA的梯度上升法中,w是一个方向向量,其模为1,所以w的每一个维度其实都很小,那么为了适应,相应的epsilon也要小一些

  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

那么下面就开始梯度上升法的过程

每一次循环中先计算一下梯度,然后记录一下上一次的w是多少,之后计算一下使用梯度上升法后得到的新的w,之后就对新的w和旧的w进行计算,看一下两次对应的增加的值有没有超过给定的值,还没有超过就继续循环,否则的话,我们就直接break回去,返回最终的w

需要注意的是,w本来是个方向向量,其模应该为1,从之前推导的公式的条件也可以看出来,需要w的模为1,但是在计算过程中,很可能会让w的模不为1,虽然也可以使用,但是会使得整个计算的过程很不顺畅,且还要将eta的值变得特得特别小,这样会导致程序的效率非常的低

所以每次我们需要对w进行一下将其模变为1的操作,这里使用direction函数将其化成一个只表示方向的单位向量,只要返回w除以w对应的模(求向量的模可以使用np.linalg.norm(w))就可以,这样我们在使用的时候首先就要将initial_w转换成单位向量,在每求到一次新的w之后相应的也调用一下这个函数来将模变成1,这样就完成了使用梯度上升法求解PCA的代码

  def direction(w):
return w / np.linalg.norm(w) 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(w, X)
last_w = w
w = w + eta * gradient
w = direction(w)
if (abs(f(w,X) - f(last_w,X)) < epsilon):
break cur_iter += 1 return w

我们想要调用这个函数,还需要注意,我们调用的时候是需要初始化一个w的值,但是这个初始化的值是不可以为0向量的,因为对于这个目标函数来说,w等于0本身就是一个极值点,只不过这个极值点是最小值点,其梯度值也为0,所以带入0是不可以的,因此我们开始的时候需要随机化一个向量,在向量中对应的随机的元素个数就是X这个矩阵的列数,也就是样本的特征数

  initial_w = np.random.random(X.shape[1])
initial_w

结果如下

我们设置eta为0.001

  eta=0.001

还有一个注意点,对于PCA问题,不能使用StandardScaler来标准化数据,这是为什么呢?因为对于PCA问题来说,本身就是求一个轴,使样本映射以后的方差最大,但是一旦对样本进行标准化了,将样本的方差打散以后会使样本的方差为1,这就使得方差的最大值不存在,就会求不出来PCA真正想要得到的结果了

我们先使用df_debug来求一下对应的轴

  gradient_ascent(df_debug,X_demean,initial_w,eta)

结果如下

然后可以使用df_mean来求一下

  gradient_ascent(df_mean,X_demean,initial_w,eta)

结果如下

可以看出来结果是一样的,这就说明了我们的结果是正确的

然后我们可视化一下,看一下这个轴对应的方向是怎么个方向,先将原始的数据绘制出来,然后绘制轴对应的方向,方法是对于x和y,首先绘制(0,0)这个点,然后绘制一下w这个点,即w[0]和w[1]对应的点,但是由于w很小,正常显示可能看不清,所以对其乘上一个系数,最后是其颜色为红色

  w = gradient_ascent(df_mean,X_demean,initial_w,eta)

  plt.scatter(X_demean[:,0],X_demean[:,1])
plt.plot([0,w[0]*30],[0,w[1]*30],color='r')

图像如下

相应的这个轴就是一个主成分,在这里使我们所求出来的第一个主成分,因此我们也称其为第一主成分

极端情况

我们使用一下极端的结果来试一下,还是使用原来的虚假样例,但是不添加噪音

  X2 = np.empty((100,2))
X2[:,0] = np.random.uniform(0. ,100. , size=100)
X2[:,1] = 0.75 * X2[:,0] + 3.

绘制出图像

  plt.scatter(X2[:,0],X2[:,1])

图像如下

可以发现其完全在一条直线上,不过依然是分布在一个二维的平面上

然后我们开始求解问题,首先进行demean操作,然后调用gradient_ascent函数进行计算并存在w2中

  X2_demean = demean(X2)
w2 = gradient_ascent(df_mean,X2_demean,initial_w,eta)

绘制图像

  plt.scatter(X2_demean[:,0],X2_demean[:,1])
plt.plot([0,w2[0]*30],[0,w2[1]*30],color='r')

图像如下

这个轴和这些点是重合的,且我们可以得出gradient_ascent(df_mean,X2_demean,initial_w,eta)为0趋近于0.8和趋近于0.6组成的,对应的我们的系数0.75

经过这两个方面可知是算法正确的

【笔记】求数据的对应主成分PCA(第一主成分)的更多相关文章

  1. 【笔记】求数据前n个主成分以及对高维数据映射为低维数据

    求数据前n个主成分并进行高维数据映射为低维数据的操作 求数据前n个主成分 先前的将多个样本映射到一个轴上以求使其降维的操作,其中的样本点本身是二维的样本点,将其映射到新的轴上以后,还不是一维的数据,对 ...

  2. MATLAB实例:PCA(主成成分分析)详解

    MATLAB实例:PCA(主成成分分析)详解 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 1. 主成成分分析 2. MATLAB解释 详细信息请看: ...

  3. 机器学习 —— 基础整理(四)特征提取之线性方法:主成分分析PCA、独立成分分析ICA、线性判别分析LDA

    本文简单整理了以下内容: (一)维数灾难 (二)特征提取--线性方法 1. 主成分分析PCA 2. 独立成分分析ICA 3. 线性判别分析LDA (一)维数灾难(Curse of dimensiona ...

  4. 【JDBC】向数据表插入数据时,自动获取生成的主键

    数据表设计时,一般都会有一个主键(Key)(自己指定),有时也可以使用联合主键: 有许多数据库提供了隐藏列为表中的每行记录分配一个唯一键值(如:rowid): 当我们没有指定哪一列作为主键key时,数 ...

  5. Windows phone 8 学习笔记(2) 数据文件操作

    原文:Windows phone 8 学习笔记(2) 数据文件操作 Windows phone 8 应用用于数据文件存储访问的位置仅仅限于安装文件夹.本地文件夹(独立存储空间).媒体库和SD卡四个地方 ...

  6. Hibernate学习笔记(三)Hibernate生成表单ID主键生成策略

    一. Xml方式 <id>标签必须配置在<class>标签内第一个位置.由一个字段构成主键,如果是复杂主键<composite-id>标签 被映射的类必须定义对应数 ...

  7. #学习笔记#JSP数据交互

    #学习笔记#JSP数据交互 数据库的使用方式:   当用户在第一个页面的查询框输入查询语句点提交的时候我们是用什么样的方式完成这个查询的? 答:我们通过在第一个页面提交表单的形式,真正的数据库查询时在 ...

  8. ArcGIS案例学习笔记_3_2_CAD数据导入建库

    ArcGIS案例学习笔记_3_2_CAD数据导入建库 计划时间:第3天下午 内容:CAD数据导入,建库和管理 目的:生成地块多边形,连接属性,管理 问题:CAD存在拓扑错误,标注位置偏移 教程:pdf ...

  9. GIS案例学习笔记-CAD数据分层导入现有模板实例教程

    GIS案例学习笔记-CAD数据分层导入现有模板实例教程 联系方式:谢老师,135-4855-4328,xiexiaokui#qq.com 1. 原始数据: CAD数据 目标模板 2. 任务:分5个图层 ...

随机推荐

  1. mysql被收购 用mariadb (转)

    ~]# systemctl start mysql.service 要启动MySQL数据库是却是这样的提示 Failed to start mysqld.service: Unit not found ...

  2. 淘宝的sign参数js逆向

    前言:现在网站都有很强的反爬机制,都是非常常见的是用js前端加密参数,所以不得不去分析和逆向js混淆后的代码 一. 打开天猫或淘宝,shift+ctrl+F12全局搜索sign参数. 这里发现很多地方 ...

  3. buu 红帽杯 XX

    一.拖入ida,静态分析 __int64 __fastcall sub_7FF65D4511A0(__int64 a1, __int64 a2) { signed __int64 v2; // rbx ...

  4. STM32笔记一

    1.脉冲宽度调制是(PWM):用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量.通信到功率控制与变换的许多领域中.一般用于直流电机调速. 2.外部中断:外部中断是单片机实 ...

  5. MySQL | Xtrabackup 安装

    rpm方式安装 # xtrabackup 2.4.8 安装包 wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup- ...

  6. C语言:#error命令,阻止程序编译

    #error 指令用于在编译期间产生错误信息,并阻止程序的编译,其形式如下: #error error_message 例如,我们的程序针对 Linux 编写,不保证兼容 Windows,那么可以这样 ...

  7. ES6 数值类型常用方法

    ES6 数值类型常用方法 <script type="text/javascript"> // Number常用方法 /* Number.isFinite() 用来检查 ...

  8. ArcGis Server安装与使用

    ArcGis Server安装 下载ArcGisServer 双击Setup.exe,然后一直下一步. 安装完成后,点击完成,弹出如下界面: 选择第三个选项,然选择[.ecp]后缀名的授权文件. 然后 ...

  9. Selenium环境搭建 - Mac电脑

    一. JDK安装 1.1.官网下载1.8版本 可参考以下链接步骤: 'https://blog.csdn.net/u014801367/article/details/86288078' 1.2.jd ...

  10. fastjson 1.2.24 反序列化导致任意命令执行漏洞

    漏洞检测 区分 Fastjson 和 Jackson {"name":"S","age":21} 和 {"name":& ...