机器学习入门算法笔记(未完成)

本文详细介绍了PCA(主成分分析)及其使用梯度上升法求解的过程,包括数据的主成分计算、降噪和高维数据映射。通过实例展示了PCA在MNIST数据集上的应用,以及如何使用scikit-learn库实现PCA。此外,还讨论了PCA在人脸识别和数据降噪中的作用。
摘要由CSDN通过智能技术生成

机器学习入门算法笔记

第七章 PCA与梯度上升法

7-1 什么是PCA

一个非监督的机器学习算法 主要用于数据降维 通过降维可以发现便于人类理解的特征 应用于可视化 去噪
PCA是一种较为常用的降维技术,PCA的思想是将维特征映射到维上,这维是全新的正交特征。这维特征称为主元,是重新构造出来的维特征。在PCA中,数据从原来的坐标系转换到新的坐标系下,新的坐标系的选择与数据本身是密切相关的。第一个新坐标轴选择的是原始数据中方差最大的方向,第二个新坐标轴选择和第一个坐标轴正交且具有最大方差的方向。该过程一直重复,重复次数为原始数据中特征的数目。大部分方差都包含在最前面的几个新坐标轴中。因此,可以忽略余下的坐标轴,即对数据进行降维处理

7-2 使用梯度上升法求解PCA问题

在这里插入图片描述
首先我们要找到一个让样本间距最大的轴 我们使用方差来定义样本的间距 使方差最大 进而求出方向轴w(w1,w2)
var(x)=1/m * ∑ 1 m \sum _1^m 1m(xi-x的均值)**2

1/m*(np.sum(x-np.mean(x))**2)

将样例均值归0 得到 var(x)=1/m * ∑ 1 m \sum _1^m 1m(xi)**2


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7-3 求数据的主成分

使用梯度上升法实现PCA

import numpy as np
import matplotlib.pyplot as plt
#创建一个2列 100个样本的空数据
X = np.empty((100, 2))
#在数据第一列中随机生成0-100的随机数
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])
#显示
plt.show()

在这里插入图片描述

去掉每一个数据的均值

def demean(X):
    return X - np.mean(X, axis=0)
X_demean = demean(X)
plt.scatter(X_demean[:,0], X_demean[:,1])
plt.show()

梯度上升法(求第一个主成分坐标)

#价值函数
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)
#用来验证价值函数求导是否正确
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
#创建单位向量
def direction(w):
    return w / np.linalg.norm(w)
#计算出w是多少
def gradient_ascent(df, X, initial_w, eta, n_iters = 1e4, epsilon=1e-8):
    初始的w值
    w = direction(initial_w) 
    cur_iter = 0
    #循环1e4次
    while cur_iter < n_iters:
        #求导
        gradient = df(w, X)
        #记录w值
        last_w = w
        #每次循环w的值向正方向梯度上升一点
        w = w + eta * gradient
        w = direction(w) # 注意1:每次求一个单位方向
        #当前一个w值和上一个值接近于0 循环结束
        if(abs(f(w, X) - f(last_w, X)) < epsilon):
            break
            
        cur_iter += 1

    return w
    #测试代码
    initial_w = np.random.random(X.shape[1]) # 注意2:不能用0向量开始
    eta = 0.001
    gradient_ascent(df_debug, X_demean, initial_w, eta)
    gradient_ascent(df_math, X_demean, initial_w, eta)

7-4 求数据的前n个主成分

求第二个主成分

initial_w = np.random.random(X.shape[1])
eta = 0.01
#求出第一个主成分
w = gradient_ascent(df_math,X_demean, initial_w, eta)
#创建一个和x同样维度的
X2 = np.empty(X.shape)
# 遍历x 使每个元素减去第一主成分的
for i in range(len(X)):
    X2[i] = X[i] - X[i].dot(w) * w
plt.scatter(X2[:,0], X2[:,1])
plt.show()

在这里插入图片描述

用向量的方式运算也是一样结果

X2 = X - X.dot(w).reshape(-1, 1) * w

求第三个主成分 也是根据求第二主成分方法一样 以此类推

集成一个降维方法

# n代表求前n个主成分
def first_n_components(n, X, eta=0.01, 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 = first_component(X_pca, initial_w, eta)
        res.append(w)
        
        X_pca = X_pca - X_pca.dot(w).reshape(-1, 1) * w
        
    return res

7-5 高维数据映射为低维数据

在这里插入图片描述
在这里插入图片描述

import numpy as np

class PCA:

    def __init__(self, n_components):
        """初始化PCA"""
        assert n_components >= 1, "n_components must be valid"
        self.n_components = n_components
        self.components_ = None

    def fit(self, X, eta=0.01, n_iters=1e4):
        """获得数据集X的前n个主成分"""
        assert self.n_components <= X.shape[1], \
            "n_components must not be greater than the feature number of X"

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

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

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

        def direction(w):
            return w / np.linalg.norm(w)

        def first_component(X, initial_w, eta=0.01, 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

        X_pca = demean(X)
        self.components_ = np.empty(shape=(self.n_components, X.shape[1]))
        for i in range(self.n_components):
            initial_w = np.random.random(X_pca.shape[1])
            w = first_component(X_pca, initial_w, eta, n_iters)
            self.components_[i,:] = w

            X_pca = X_pca - X_pca.dot(w).reshape(-1, 1) * w

        return self

    def transform(self, X):
        """将给定的X,映射到各个主成分分量中"""
        assert X.shape[1] == self.components_.shape[1]
        return X.dot(self.components_.T)

    def inverse_transform(self, X):
        """将给定的X,反向映射回原来的特征空间"""
        assert X.shape[1] == self.components_.shape[0]
        return X.dot(self.components_)

    def __repr__(self):
        return "PCA(n_components=%d)" % self.n_components

#测试代码
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)

pca = PCA(n_components=1)
pca.fit(X)
X_reduction = pca.transform(X)
X_restore = pca.inverse_transform(X_reduction)
plt.scatter(X[:,0], X[:,1], color='b', alpha=0.5)
plt.scatter(X_restore[:,0], X_restore[:,1], color='r', alpha=0.5)
plt.show()

在这里插入图片描述

7-6 scikit-learn中的PCA

#引入sklearn pca
from sklearn.decomposition import PCA
#构建函数 主成分为一
pca = PCA(n_components=1)
#传递数据
pca.fit(X)
pca.components_ #求出主成分向量坐标 array([[-0.76676934, -0.64192272]])
# 转换对应的坐标的值
X_reduction = pca.transform(X)
#转回来
X_restore = pca.inverse_transform(X_reduction)
plt.scatter(X[:,0], X[:,1], color='b', alpha=0.5)
plt.scatter(X_restore[:,0], X_restore[:,1], color='r', alpha=0.5)
plt.show()

在这里插入图片描述

7-7 试手MNIST数据集

import numpy as np 

# from sklearn.datasets import fetch_mldata
# mnist = fetch_mldata('MNIST original')
# 在最新版的 sklearn 中,fetch_mldata 被弃用,改为使用 fetch_openml 获得 MNIST 数据集
# 具体见如下代码,后续代码无需改变

from sklearn.datasets import fetch_openml
 
#准备数据
mnist = fetch_openml('mnist_784')
# 把数据集分为测试和训练
X, y = mnist['data'], mnist['target']
X_train = np.array(X[:60000], dtype=float)
y_train = np.array(y[:60000], dtype=float)
X_test = np.array(X[60000:], dtype=float)
y_test = np.array(y[60000:], dtype=float)

# 使用Knn算法 在没有降维的情况下跑数据用了 11分钟 准确率0.9688
from sklearn.neighbors import KNeighborsClassifier
knn_clf = KNeighborsClassifier()
knn_clf.fit(X_train, y_train)
knn_clf.score(X_test, y_test)
#使用pca降维
from sklearn.decomposition import PCA 
# 保准准确率0.9
pca = PCA(0.90)
pca.fit(X_train)
X_train_reduction = pca.transform(X_train)
X_test_reduction = pca.transform(X_test)
X_train_reduction.shape # 可以看出降到 (60000, 87) 87维
knn_clf = KNeighborsClassifier()
knn_clf.fit(X_train_reduction, y_train)
knn_clf.score(X_test_reduction, y_test)

上面可以看出 整个过程用了1分钟 准确率比上次还高 降维去除了噪音,有可能准确率更高!

7-8 使用PCA对数据进行降噪

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, 5, size=100)
plt.scatter(X[:,0], X[:,1])
plt.show()

在这里插入图片描述

from sklearn.decomposition import PCA
pca = PCA(n_components=1)
pca.fit(X)
X_reduction = pca.transform(X)
X_restore = pca.inverse_transform(X_reduction)
plt.scatter(X_restore[:,0], X_restore[:,1])
plt.show()

在这里插入图片描述

降维的过程可以理解成是去噪。
手写识别的例子


7-9 人脸识别与特征脸

补充代码1: 可视化三维数据的PCA过程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值