fork了别人的项目,自己重新填写,我的代码如下

https://gitee.com/fakerlove/machine-learning/tree/master/code

代码原链接

文章目录

  • 7. 吴恩达机器学习课程-作业7-Kmeans and PCA
    • 7.1 k-means
      • 7.1.1 题目介绍
      • 7.1.2 算法流程
      • 7.1.3 实现k-means
      • 7.1.4 测试
    • 7.2 图像压缩与k-均值
    • 7.3 PCA
      • 7.3.1 题目介绍
      • 7.3.2 算法流程
      • 7.3.3 代码
        • 1) 示例数据集
        • 2) 实现PCA
        • 3) 脸图像数据集

7. 吴恩达机器学习课程-作业7-Kmeans and PCA

在本练习中,您将实现K-means聚类算法和应用它来压缩图像。

在第二部分中,您将使用PCA,找到一个低维的人脸图像表示。

在开始编程练习之前,我们强烈建议大家先看视频课程,并完成相关课程的复习题的话题。

要开始练习,您需要下载启动器代码并将其内容解压缩到您希望完成的目录锻炼。

如果需要,使用Octave/MATLAB中的cd命令更改为这个目录,然后开始这个练习。你也可以在课程网站的“环境设置说明”中找到安装Octave/MATLAB的说明。

7.1 k-means

7.1.1 题目介绍

在本练习中,您将实现K-means算法并使用它图像压缩。

您将首先从一个示例2D数据集开始在本练习中,您将实现K-means算法并使用它图像压缩。您将首先从一个示例2D数据集开始将帮助您对K-means算法如何工作有一个直观的了解。

后你将使用K-means算法进行图像压缩一幅图像中出现的颜色的数量仅为那些颜色最多的在这幅图中很常见。你将使用ex7。M代表这部分练习。

7.1.2 算法流程

输入:nnn个样本的集合XXX

输出:样本集合的聚类C∗C^*C∗

  • 初始化,令t=0t=0t=0,随机选择kkk个样本点作为初始聚类中心

    m(0)=(m1(0),…,ml(0),…,mk(0))m^{(0)}=(m_1^{(0)},\dots,m_l^{(0)},\dots,m_k^{(0)})m(0)=(m1(0)​,…,ml(0)​,…,mk(0)​)

  • 对样本进行聚类,对固定的类中心m(t)=(m1(t),…,ml(t),…,mk(t))m^{(t)}=(m_1^{(t)},\dots,m_l^{(t)},\dots,m_k^{(t)})m(t)=(m1(t)​,…,ml(t)​,…,mk(t)​),其中mk(t)m_k^{(t)}mk(t)​为类ClC_lCl​的中心,

    计算每个样本到类中心的距离,将每个样本指派到与其最近的中心的类中,构成聚类结果C(t)C^(t)C(t)

  • 计算新的类中心,对聚类结果C(t)C^{(t)}C(t),计算当前各个类中的样本的均值,作为新的类中心

    m(t+1)=(m1(t+1),…,ml(t+1),…,mk(t+1))m^{(t+1)}=(m_1^{(t+1)},\dots,m_l^{(t+1)},\dots,m_k^{(t+1)})m(t+1)=(m1(t+1)​,…,ml(t+1)​,…,mk(t+1)​)

  • 如果迭代收敛或符合停止条件,输出C∗=C(t)C^*=C^{(t)}C∗=C(t),后者令t=t+1t=t+1t=t+1

7.1.3 实现k-means

首先需要实现,为每个点找到最近的簇中心,作为当前点的标签

C(i)=jthatminizizes∣∣x(i)−μj∣∣2C^{(i)}=j\ that \ minizizes \ ||x^{(i)}-\mu_j||^2C(i)=j that minizizes ∣∣x(i)−μj​∣∣2

import re
import scipy.io as sio
import numpy as np
import matplotlib.pyplot as plt
from time import *def find_closet_centroids(X, centroids):"""寻找所属簇,centroids重心的意思,意思就是这个点离所有的中心点最近:param X: ndarray,所有点:param centroids: ndarray,上一步计算出或初始化的簇中心:return: ndarray,每个点所属于的簇"""# 多加了一个0res = np.zeros((1,))for x in X:res = np.append(res, np.argmin(np.sqrt(np.sum((centroids - x) ** 2, axis=1))))# 返回结果时,去掉多加的一个0return res[1:]if __name__ == '__main__':begin_time = time()print("========程序开始============")data = sio.loadmat("data\\ex7data2.mat")X = np.array(data['X']) # (300,2)# 随机初始化中心店init_centroids = np.array([[3, 3], [6, 2], [8, 5]])idx = find_closet_centroids(X, init_centroids)print(idx[0:10]) # [0. 2. 1.]end_time = time()run_time = end_time - begin_timeprint("========程序结束============")print('该循环程序运行时间:', run_time)

接着实现第二个部分,重新计算簇中心

μl=1Ck∑i∈Ckx(i)\mu_l=\frac{1}{C_k}\sum_{i\in C_k}x^{(i)}μl​=Ck​1​∑i∈Ck​​x(i)

def compute_centroids(X, idx):"""计算新的簇中心:param X: ndarray,所有点:param idx: ndarray,每个点对应的簇号:return: ndarray,所有新簇中心"""# K是一共分成的类数K = int(np.max(idx)) + 1# m为X的行数m = X.shape[0]n = X.shape[-1]centroids = np.zeros((K, n))counts = np.zeros((K, n))for i in range(m):centroids[int(idx[i])] += X[i]counts[int(idx[i])] += 1centroids = centroids / countsreturn centroids

将这两步封装成一个完整的K-means算法,这里用到的随机初始化簇中心,在1.3实现,我直接先用一下,具体的函数看1.3。而且算法的迭代轮数可以指定一个很大的轮数保证计算完后算法收敛。我选择每次计算当前的目标值,当目标值不变时,算法收敛退出。
需要先实现损失函数

def cost(X, idx, centrodis):c = 0for i in range(len(X)):c += np.sum((X[i] - centrodis[int(idx[i])]) ** 2)c /= len(X)return c

定义聚类算法

def random_initialization(X, K):"""随机选择K组数据,作为簇中心:param X: ndarray,所有点:param K: int,聚类的类数:return: ndarray,簇中心"""res = np.zeros((1, X.shape[-1]))m = X.shape[0]rl = []while True:index = random.randint(0, m)if index not in rl:rl.append(index)if len(rl) >= K:breakfor index in rl:res = np.concatenate((res, X[index].reshape(1, -1)), axis=0)return res[1:]def k_means(X, K):"""k-means聚类算法,:param X: ndarray,所有的数据:param K: int,分成聚类的类数:return: tuple,(idx, centroids_all)idx,ndarray 为每个数据所属类标签centroids_all,[ndarray,...]计算过程中每轮的簇中心"""centroids = random_initialization(X, K)centroids_all = [centroids]idx = np.zeros((1,))last_c = -1now_c = -2# iterations = 200# for i in range(iterations):while now_c != last_c:  # 当收敛时结束算法,或者可以利用指定迭代轮数# 算出每个点所属簇类idx = find_closet_centroids(X, centroids)last_c = now_c# 计算损失函数now_c = cost(X, idx, centroids)# 根据重新规划后的簇类,重新规划簇类中心点centroids = compute_centroids(X, idx)# 记录训练过程中所有的中心点centroids_all.append(centroids)return idx, centroids_all

7.1.4 测试

    data = sio.loadmat("data\\ex7data2.mat")X = data['X']  # (300,2)idx, centroids_all = k_means(X, 3)

这里的聚类算中返回了每轮计算的簇中心,就是为了后面的可视化簇中心变化过程,画出聚类结果和簇中心的移动路线

def visualizing(X, idx, centroids_all):"""可视化聚类结果和簇中心的移动过程:param X: ndarray,所有的数据:param idx: ndarray,每个数据所属类标签:param centroids_all: [ndarray,...]计算过程中每轮的簇中心:return: None"""plt.scatter(X[..., 0], X[..., 1], c=idx)xx = []yy = []for c in centroids_all:xx.append(c[..., 0])yy.append(c[..., 1])plt.plot(xx, yy, 'rx--')plt.show()

所有代码

import random
import re
import scipy.io as sio
import numpy as np
import matplotlib.pyplot as plt
from time import *def find_closet_centroids(X, centroids):"""寻找所属簇,centroids重心的意思,意思就是这个点离所有的中心点最近:param X: ndarray,所有点:param centroids: ndarray,上一步计算出或初始化的簇中心:return: ndarray,每个点所属于的簇"""# 多加了一个0res = np.zeros((1,))for x in X:res = np.append(res, np.argmin(np.sqrt(np.sum((centroids - x) ** 2, axis=1))))# 返回结果时,去掉多加的一个0return res[1:]def compute_centroids(X, idx):"""计算新的簇中心:param X: ndarray,所有点:param idx: ndarray,每个点对应的簇号:return: ndarray,所有新簇中心"""# K是一共分成的类数K = int(np.max(idx)) + 1# m为X的行数m = X.shape[0]n = X.shape[-1]centroids = np.zeros((K, n))counts = np.zeros((K, n))for i in range(m):centroids[int(idx[i])] += X[i]counts[int(idx[i])] += 1centroids = centroids / countsreturn centroidsdef cost(X, idx, centrodis):"""计算损失函数:param X::param idx::param centrodis::return:"""c = 0for i in range(len(X)):c += np.sum((X[i] - centrodis[int(idx[i])]) ** 2)c /= len(X)return cdef random_initialization(X, K):"""随机选择K组数据,作为簇中心:param X: ndarray,所有点:param K: int,聚类的类数:return: ndarray,簇中心"""res = np.zeros((1, X.shape[-1]))m = X.shape[0]rl = []while True:index = random.randint(0, m)if index not in rl:rl.append(index)if len(rl) >= K:breakfor index in rl:res = np.concatenate((res, X[index].reshape(1, -1)), axis=0)return res[1:]def k_means(X, K):"""k-means聚类算法,:param X: ndarray,所有的数据:param K: int,分成聚类的类数:return: tuple,(idx, centroids_all)idx,ndarray 为每个数据所属类标签centroids_all,[ndarray,...]计算过程中每轮的簇中心"""centroids = random_initialization(X, K)centroids_all = [centroids]idx = np.zeros((1,))last_c = -1now_c = -2# iterations = 200# for i in range(iterations):while now_c != last_c:  # 当收敛时结束算法,或者可以利用指定迭代轮数# 算出每个点所属簇类idx = find_closet_centroids(X, centroids)last_c = now_c# 计算损失函数now_c = cost(X, idx, centroids)# 根据重新规划后的簇类,重新规划簇类中心点centroids = compute_centroids(X, idx)# 记录训练过程中所有的中心点centroids_all.append(centroids)return idx, centroids_alldef visualizing(X, idx, centroids_all):"""可视化聚类结果和簇中心的移动过程:param X: ndarray,所有的数据:param idx: ndarray,每个数据所属类标签:param centroids_all: [ndarray,...]计算过程中每轮的簇中心:return: None"""plt.scatter(X[..., 0], X[..., 1], c=idx)xx = []yy = []for c in centroids_all:xx.append(c[..., 0])yy.append(c[..., 1])plt.plot(xx, yy, 'rx--')plt.show()if __name__ == '__main__':begin_time = time()print("========程序开始============")data = sio.loadmat("data\\ex7data2.mat")X = np.array(data['X'])  # (300,2)idx, centroids_all = k_means(X, 3)visualizing(X, idx, centroids_all)end_time = time()run_time = end_time - begin_timeprint("========程序结束============")print('该循环程序运行时间:', run_time)

7.2 图像压缩与k-均值

一般簇中心的初始化是从数据中随机选择K组

def random_initialization(X, K):"""随机选择K组数据,作为簇中心:param X: ndarray,所有点:param K: int,聚类的类数:return: ndarray,簇中心"""res = np.zeros((1, X.shape[-1]))m = X.shape[0]rl = []while True:index = random.randint(0, m)if index not in rl:rl.append(index)if len(rl) >= K:breakfor index in rl:res = np.concatenate((res, X[index].reshape(1, -1)), axis=0)return res[1:]

接下来将聚类算法用于图片压缩上,先讲一讲思路
图片都是由若干像素点构成的,每个像素点都有颜色,这个颜色一般是RGB编码,意思是所有颜色都可以通过Red,Green,Blue来表示,RGB编码下三种颜色每个通过一个8比特的整数来表示强度,因此一个像素点需要24bit来表示颜色。
图片上的每个像素点都需要使用24bit存储颜色,我们的压缩方法是,通过聚类将图片上的颜色分为16种,我们只存储这十六种颜色,每个像素点上只需要4比特存储对应颜色的序号,即可达到有损压缩图片的目的。

进行图片压缩,将rgb颜色作为聚类的点数据,每个颜色的表示是一个列表包含三个数。这里聚类结束后构造新的图片矩阵,不是很规范,应该是直接存储bit。

def compress(image, colors_num):"""压缩图片:param image: ndarray,原始图片:param colors_num: int,压缩后的颜色数量:return: (ndarray,ndarray),第一个每个像素点存储一个值,第二个为颜色矩阵"""# _代表3,d1和d2代表图片的长和宽d1, d2, _ = image.shape# 变成二维数组raw_image = image.reshape(d1 * d2, -1)  # 展开成二维数组print(raw_image.shape)#idx, centroids_all = k_means(raw_image, colors_num)# colors 表示最后一次的中心点colors = centroids_all[-1]# 构造压缩后的图片格式compressed_image = np.zeros((1, 1))for i in range(d1 * d2):compressed_image = np.concatenate((compressed_image, idx[i].reshape(1, -1)), axis=0)compressed_image = compressed_image[1:].reshape(d1, d2, -1)return compressed_image, colors

为了可视化效果,还需要将压缩后的图片格式转化为可以显示的标准格式

def compressed_format_to_normal_format(compressed_image, colors):"""将压缩后的图片转为正常可以显示的图片格式:param compressed_image: ndarray,压缩后的图片,存储颜色序号:param colors: ndarray,颜色列表:return: ndarray,正常的rgb格式图片"""d1, d2, _ = compressed_image.shapenormal_format_image = np.zeros((1, len(colors[0])))compressed_image = compressed_image.reshape(d1 * d2, -1)for i in range(d1 * d2):normal_format_image = np.concatenate((normal_format_image, colors[int(compressed_image[i][0])].reshape(1, -1)),axis=0)normal_format_image = normal_format_image[1:].reshape(d1, d2, -1)return normal_format_image

看一看效果

    image = plt.imread("data\\bird_small.png")  # (128,128,3)plt.subplot(1, 2, 1)plt.imshow(image)plt.axis('off')plt.title("raw image")plt.subplot(1, 2, 2)compressed_image, colors = compress(image, 16)print(compressed_image.shape, colors.shape)plt.imshow(compressed_format_to_normal_format(compressed_image, colors))plt.axis('off')plt.title("compressed image")plt.show()

运行时间有点长

========程序开始============
(128, 128, 3)
(16384, 3)
(128, 128, 1) (16, 3)
========程序结束============
该循环程序运行时间: 94.86905074119568

总代码如下

import random
import re
import scipy.io as sio
import numpy as np
import matplotlib.pyplot as plt
from time import *def find_closet_centroids(X, centroids):"""寻找所属簇,centroids重心的意思,意思就是这个点离所有的中心点最近:param X: ndarray,所有点:param centroids: ndarray,上一步计算出或初始化的簇中心:return: ndarray,每个点所属于的簇"""# 多加了一个0res = np.zeros((1,))for x in X:res = np.append(res, np.argmin(np.sqrt(np.sum((centroids - x) ** 2, axis=1))))# 返回结果时,去掉多加的一个0return res[1:]def compute_centroids(X, idx):"""计算新的簇中心:param X: ndarray,所有点:param idx: ndarray,每个点对应的簇号:return: ndarray,所有新簇中心"""# K是一共分成的类数K = int(np.max(idx)) + 1# m为X的行数m = X.shape[0]n = X.shape[-1]centroids = np.zeros((K, n))counts = np.zeros((K, n))for i in range(m):centroids[int(idx[i])] += X[i]counts[int(idx[i])] += 1centroids = centroids / countsreturn centroidsdef cost(X, idx, centrodis):"""计算损失函数:param X::param idx::param centrodis::return:"""c = 0for i in range(len(X)):c += np.sum((X[i] - centrodis[int(idx[i])]) ** 2)c /= len(X)return cdef random_initialization(X, K):"""随机选择K组数据,作为簇中心:param X: ndarray,所有点:param K: int,聚类的类数:return: ndarray,簇中心"""res = np.zeros((1, X.shape[-1]))m = X.shape[0]rl = []while True:index = random.randint(0, m)if index not in rl:rl.append(index)if len(rl) >= K:breakfor index in rl:res = np.concatenate((res, X[index].reshape(1, -1)), axis=0)return res[1:]def compress(image, colors_num):"""压缩图片:param image: ndarray,原始图片:param colors_num: int,压缩后的颜色数量:return: (ndarray,ndarray),第一个每个像素点存储一个值,第二个为颜色矩阵"""# _代表3,d1和d2代表图片的长和宽d1, d2, _ = image.shapeprint(image.shape)# 变成二维数组,# (a,b)# #改变维度为m行、d列 (-1表示列数自动计算,d= a*b /m )raw_image = image.reshape(d1 * d2, -1)  # 展开成二维数组print(raw_image.shape)#idx, centroids_all = k_means(raw_image, colors_num)# colors 表示最后一次的中心点colors = centroids_all[-1]# 构造压缩后的图片格式compressed_image = np.zeros((1, 1))for i in range(d1 * d2):compressed_image = np.concatenate((compressed_image, idx[i].reshape(1, -1)), axis=0)compressed_image = compressed_image[1:].reshape(d1, d2, -1)return compressed_image, colorsdef compressed_format_to_normal_format(compressed_image, colors):"""将压缩后的图片转为正常可以显示的图片格式:param compressed_image: ndarray,压缩后的图片,存储颜色序号:param colors: ndarray,颜色列表:return: ndarray,正常的rgb格式图片"""d1, d2, _ = compressed_image.shapenormal_format_image = np.zeros((1, len(colors[0])))compressed_image = compressed_image.reshape(d1 * d2, -1)for i in range(d1 * d2):normal_format_image = np.concatenate((normal_format_image, colors[int(compressed_image[i][0])].reshape(1, -1)),axis=0)normal_format_image = normal_format_image[1:].reshape(d1, d2, -1)return normal_format_imagedef k_means(X, K):"""k-means聚类算法,:param X: ndarray,所有的数据:param K: int,分成聚类的类数:return: tuple,(idx, centroids_all)idx,ndarray 为每个数据所属类标签centroids_all,[ndarray,...]计算过程中每轮的簇中心"""centroids = random_initialization(X, K)centroids_all = [centroids]idx = np.zeros((1,))last_c = -1now_c = -2# iterations = 200# for i in range(iterations):while now_c != last_c:  # 当收敛时结束算法,或者可以利用指定迭代轮数# 算出每个点所属簇类idx = find_closet_centroids(X, centroids)last_c = now_c# 计算损失函数now_c = cost(X, idx, centroids)# 根据重新规划后的簇类,重新规划簇类中心点centroids = compute_centroids(X, idx)# 记录训练过程中所有的中心点centroids_all.append(centroids)return idx, centroids_alldef visualizing(X, idx, centroids_all):"""可视化聚类结果和簇中心的移动过程:param X: ndarray,所有的数据:param idx: ndarray,每个数据所属类标签:param centroids_all: [ndarray,...]计算过程中每轮的簇中心:return: None"""plt.scatter(X[..., 0], X[..., 1], c=idx)xx = []yy = []for c in centroids_all:xx.append(c[..., 0])yy.append(c[..., 1])plt.plot(xx, yy, 'rx--')plt.show()if __name__ == '__main__':begin_time = time()print("========程序开始============")# data = sio.loadmat("data\\ex7data2.mat")# X = np.array(data['X'])  # (300,2)image = plt.imread("data\\bird_small.png")  # (128,128,3)plt.subplot(1, 2, 1)plt.imshow(image)plt.axis('off')plt.title("raw image")plt.subplot(1, 2, 2)compressed_image, colors = compress(image, 16)print(compressed_image.shape, colors.shape)plt.imshow(compressed_format_to_normal_format(compressed_image, colors))plt.axis('off')plt.title("compressed image")plt.show()end_time = time()run_time = end_time - begin_timeprint("========程序结束============")print('该循环程序运行时间:', run_time)

7.3 PCA

  • 主成分分析法是干什么用的?
    数据降维,话句话说就是将数据地特征数量变少,但又不是简单地删除特征。数据降维地目的可以是压缩数据,减少数据的存储空间,让算法提速;也可以是将数据降到二维或者三维进行可视化

  • 主成分分析法在做什么?
    上面说到主成分分析法用于数据降维,大概理解一下它怎么做的。

    现在我们数据维度为n,我想通过降维让数据变成k维。
    那么PCA做的就是对于n维空间的数据,寻找一个K维的“面”,让这些数据到这个“面”的距离最短,这个距离又叫做投影误差。
    找到这个“面”后,将n维空间的点投影到这个“面”,因此所有点都投影到了k维空间,因此可以特征数量变为了k。
    假设n=2,k=1,那么就是将二维平面上的点投影到一个向量上。假设n=3,k=2,那么就是将三维空间的点投影到一个平面上。

  • 主成分分析法具体怎么做呢?
    对于数据要从n维降到k维
    首先对数据进行feature scaling/mean normalization,也就是归一化
    其次计算协方差矩阵

    ∑=1mXTX\sum=\frac{1}{m}X^TX∑=m1​XTX

    接着计算sigma矩阵的“特征向量”,这里使用奇异值分解(single value decomposition)。

    [U,S,V]=svd(∑)[U,S,V]=svd(\sum)[U,S,V]=svd(∑)

    利用U计算新的特征,若要下降到K维,取U的前K列构成新矩阵

    Z=UreduceTXZ=U_{reduce}^TXZ=UreduceT​X

7.3.1 题目介绍

在本练习中,您将使用主成分分析(PCA)来执行降维。您将首先尝试一个2D示例数据集来获得关于PCA如何工作的直觉,然后将其用于更大的5000个人脸图像数据集。

7.3.2 算法流程

求解步骤

  • 去除平均值
  • 计算协方差矩阵
  • 计算协方差矩阵的特征值和特征向量
  • 将特征值排序
  • 保留前N个最大的特征值对应的特征向量
  • 将原始特征转换到上面得到的N个特征向量构建的新空间中(最后两步,实现了特征压缩)

7.3.3 代码

1) 示例数据集

    data = sio.loadmat("data\\ex7data1.mat")X = np.array(data['X'])  # (50,2)plt.scatter(X[..., 0], X[..., 1], marker='x', c='b')plt.show()

2) 实现PCA

实现PCA首先要做的就是对数据的处理进行归一化,注意这里的方差的计算,默认ddof为0,通常情况下是使用ddof=1,就是方差计算中最后除以m还是m-1的不同。

def data_preprocess(X):"""数据归一化:param X: ndarray,原始数据:return: (ndarray.ndarray,ndarray),处理后的数据,每个特征均值,每个特征方差"""mean = np.mean(X, axis=0)std = np.std(X, axis=0, ddof=1)  # 默认ddof=0, 这里一定要修改return (X - mean) / std, mean, std

numpy中有奇异值分解的功能,直接使用

def data_preprocess(X):"""数据归一化:param X: ndarray,原始数据:return: (ndarray.ndarray,ndarray),处理后的数据,每个特征均值,每个特征方差"""mean = np.mean(X, axis=0)std = np.std(X, axis=0, ddof=1)  # 默认ddof=0, 这里一定要修改return (X - mean) / std, mean, std

主成分分析降维,使用PCA进行降维

def project_data(X, U, K):"""数据降维:param X: ndarray,原始数据:param U: ndarray,奇异值分解后的U:param K: int,目标维度:return: ndarray,降维后的数据"""return X.dot(U[..., :K])

逆向思维,还可以进行降维后的升维

def reconstruct_data(Z, U, K):"""数据升维:param Z: ndarray,降维后的数据:param U: ndarray,奇异值分解后的U:param K: int,降维的维度:return: ndarray,原始数据"""return Z.dot(U[..., :K].T)

测试一下

    data = sio.loadmat("data\\ex7data1.mat")X = data['X']  # (50,2)normalized_X, _, _ = data_preprocess(X)u, _, _ = pca(normalized_X)  # (2,2)Z = project_data(normalized_X, u, 1)print(Z[0]) # [1.48127391]rec_X = reconstruct_data(Z, u, 1)print(rec_X[0]) # [-1.04741883 -1.04741883]

将这个投影可视化

    plt.scatter(normalized_X[..., 0], normalized_X[..., 1], marker='x', c='b', label='normalized x')plt.scatter(rec_X[..., 0], rec_X[..., 1], marker='x', c='r', label='reconstructed x')plt.title("Visualizing the projections")for i in range(len(normalized_X)):plt.plot([normalized_X[i][0], rec_X[i][0]], [normalized_X[i][1], rec_X[i][1]], 'k--')plt.xlim((-3, 2))plt.ylim((-3, 2))plt.legend()plt.show()

3) 脸图像数据集

将PCA应用到人类数据集上,当前的每张人脸图片为1024像素,因此为1024维。我们的目标是将数据降维到36像素,也就是36维。

使用PCA进行降维

    data = sio.loadmat("data\\ex7faces.mat")X = data['X']  # (5000,1024)nor_X, _, _ = data_preprocess(X)u, _, _ = pca(nor_X)Z = project_data(nor_X, u, 36)rec_X = reconstruct_data(Z, u, 36)

将前后的图片可视化对比一下,记得要想人脸位置为正向需要转置一下

def visualizing_images(X, d):"""可视化图片:param X: ndarray,图片:param d: int,一行展示多少张图片:return: None"""m = len(X)n = X.shape[-1]s = int(np.sqrt(n))for i in range(1, m + 1):plt.subplot(m / d, d, i)plt.axis('off')plt.imshow(X[i - 1].reshape(s, s).T, cmap='Greys_r')  # 要把脸摆正需要转置plt.show()

提取特征后

所有代码

import random
import re
import scipy.io as sio
import numpy as np
import matplotlib.pyplot as plt
from time import *def data_preprocess(X):"""数据归一化:param X: ndarray,原始数据:return: (ndarray.ndarray,ndarray),处理后的数据,每个特征均值,每个特征方差"""mean = np.mean(X, axis=0)std = np.std(X, axis=0, ddof=1)  # 默认ddof=0, 这里一定要修改return (X - mean) / std, mean, stddef pca(X):"""numpy中有奇异值分解的功能,直接使用:param X::return:"""sigma = X.T.dot(X) / len(X)  # (n,m)x(m,n) (n,n)u, s, v = np.linalg.svd(sigma)  # u(n,n) s(n,), v(n,n)return u, s, vdef project_data(X, U, K):"""数据降维:param X: ndarray,原始数据:param U: ndarray,奇异值分解后的U:param K: int,目标维度:return: ndarray,降维后的数据"""return X.dot(U[..., :K])def reconstruct_data(Z, U, K):"""数据升维:param Z: ndarray,降维后的数据:param U: ndarray,奇异值分解后的U:param K: int,降维的维度:return: ndarray,原始数据"""return Z.dot(U[..., :K].T)def visualizing_images(X, d):"""可视化图片:param X: ndarray,图片:param d: int,一行展示多少张图片:return: None"""m = len(X)n = X.shape[-1]s = int(np.sqrt(n))for i in range(1, m + 1):plt.subplot(m / d, d, i)plt.axis('off')plt.imshow(X[i - 1].reshape(s, s).T, cmap='Greys_r')  # 要把脸摆正需要转置plt.show()if __name__ == '__main__':begin_time = time()print("========程序开始============")data = sio.loadmat("data\\ex7faces.mat")X = data['X']  # (5000,1024)nor_X, _, _ = data_preprocess(X)u, _, _ = pca(nor_X)Z = project_data(nor_X, u, 36)rec_X = reconstruct_data(Z, u, 36)visualizing_images(X[:25], 5)visualizing_images(rec_X[:25], 5)end_time = time()run_time = end_time - begin_timeprint("========程序结束============")print('该循环程序运行时间:', run_time)

7. 吴恩达机器学习课程-作业7-Kmeans and PCA相关推荐

  1. 8. 吴恩达机器学习课程-作业8-异常检测和推荐系统

    fork了别人的项目,自己重新填写,我的代码如下 https://gitee.com/fakerlove/machine-learning/tree/master/code 代码原链接 文章目录 8. ...

  2. 6. 吴恩达机器学习课程-作业6-SVM

    fork了别人的项目,自己重新填写,我的代码如下 https://gitee.com/fakerlove/machine-learning/tree/master/code 代码原链接 文章目录 6. ...

  3. 5. 吴恩达机器学习课程-作业5-偏差和方差

    fork了别人的项目,自己重新填写,我的代码如下 https://gitee.com/fakerlove/machine-learning/tree/master/code 代码原链接 文章目录 5. ...

  4. 4. 吴恩达机器学习课程-作业4-神经网络学习

    fork了别人的项目,自己重新填写,我的代码如下 https://gitee.com/fakerlove/machine-learning/tree/master/code 代码原链接 文章目录 4. ...

  5. 3. 吴恩达机器学习课程-作业3-多分类和神经网络

    fork了别人的项目,自己重新填写,我的代码如下 https://gitee.com/fakerlove/machine-learning/tree/master/code 代码原链接 文章目录 3. ...

  6. 2.吴恩达机器学习课程-作业2-逻辑回归

    fork了别人的项目,自己重新填写,我的代码如下 https://gitee.com/fakerlove/machine-learning/tree/master/code 代码原链接 文章目录 2. ...

  7. 1. 吴恩达机器学习课程-作业1-线性回归

    fork了别人的项目,自己重新填写,我的代码如下 https://gitee.com/fakerlove/machine-learning/tree/master/code 代码原链接 文章目录 1. ...

  8. 吴恩达机器学习课程-作业1-线性回归(python实现)

    Machine Learning(Andrew) ex1-Linear Regression 椰汁学习笔记 最近刚学习完吴恩达机器学习的课程,现在开始复习和整理一下课程笔记和作业,我将陆续更新. Li ...

  9. 吴恩达机器学习课程作业(一)基于python实现 详细解析(上篇)

    @单变量线性回归 前言 斯坦福大学吴恩达老师的机器学习课程几乎是每位热爱人工智能领域同学的必修课.网上虽然有许多基于python实现的代码,但大多使用python交互模式解释器ipython实例讲解. ...

最新文章

  1. 互联网协议 — IPv4 — CIDR 网络地址表示法
  2. 用于软件包管理的21个Linux YUM命令 转载
  3. Queue:poll、offer、element、peek
  4. Java006-面向对象(继承)
  5. php时间戳防盗链,金山云-文档中心-设置时间戳+共享密钥防盗链
  6. Idea 创建简单的SpringBoot 父子项目
  7. 栈-迷宫求解路径问题
  8. 给 Android 研发的一些的建议
  9. 造车梦又要“窒息”了?贾跃亭被美国认定骗局,收到退市警告!FF回应了......
  10. Intel 386 and AMD x86-64 Options for GCC
  11. 计算机网络技术毕业生实习报告_计算机毕业实习报告8篇完美版
  12. 华为浏览器如何进入阅读模式_华为浏览器有阅读模式吗
  13. 谈谈心理学--那些令人叫绝的心理效应
  14. 苹果手机备份数据到电脑什么位置 iPhone备份到电脑上的东西在哪里
  15. FASTA序列格式说明
  16. 微信-H5界面跳转至公众号关注界面问题
  17. 【NOIP2015提高组Day1】斗地主
  18. 学术论文摘要写作技巧:
  19. 超级隐蔽的小说阅读器
  20. vmei-day04-Jcenter方式集成极光推送

热门文章

  1. linux 编译ffmpeg 支持x264, x265
  2. android之camera
  3. https和http有什么区别
  4. python微信库wxpy无法登录_使用wxpy这个基于python实现的微信工具库的一些常见问题...
  5. springboot传入json和文件_SpringBoot中文参考指南(2.1.6)29.1.13、CORS 支持
  6. python刷今日头条阅读量_教你如何提高今日头条号推荐量阅读量播放量
  7. c语言游戏角色建立,(c语言)游戏中由人物各种信息组成的结构体
  8. Java 核心 API 必须掌握的程度
  9. linux的文件解压命令,linux解压命令(linux解压文件命令)
  10. php中mysql_affected_rows()更新记录返回0_php中mysql_affected_rows()返回-1帶來的“陷阱” | 學步園...