目录
前言:
实现原理:
第一部分:
实现代码:
应用-压缩图像
scikit-learn实现
Principal component analysis(主成分分析)
应用:
实现的练习代码:
前言:
将实现K-means聚类,并使用它来压缩图像。 我们将从一个简单的2D数据集开始,以了解K-means是如何工作的,然后我们将其应用于图像压缩。 我们还将对主成分分析进行实验,并了解如何使用它来找到面部图像的低维表示。
实现原理:
我们将实施和应用K-means到一个简单的二维数据集,以获得一些直观的工作原理。 K-means是一个迭代的,无监督的聚类算法,将类似的实例组合成簇。 该算法通过猜测每个簇的初始聚类中心开始,然后重复将实例分配给最近的簇,并重新计算该簇的聚类中心。
我们要实现的第一部分是找到数据中每个实例最接近的聚类中心的函数。
第一部分:
我们要实现的第一部分是找到数据中每个实例最接近的聚类中心的函数。
让我们来测试这个函数,以确保它的工作正常。 我们将使用练习中提供的测试用例。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sb
from scipy.io import loadmat
def find_closest_centroids(X, centroids):
m = X.shape[0]
k = centroids.shape[0]
idx = np.zeros(m)
for i in range(m):
min_dist = 1000000
for j in range(k):
dist = np.sum((X[i,:] - centroids[j,:]) ** 2)
if dist < min_dist:
min_dist = dist
idx[i] =j
return idx
data = loadmat('data/ex7data2.mat')
X = data['X']
initial_centroids = initial_centroids = np.array([[3,3],[6,2],[8,5]])
idx = find_closest_centroids(X,initial_centroids)
print(idx[0:3])
输出与文本中的预期值匹配
(记住我们的数组是从零开始索引的,而不是从一开始索引的,所以值比练习中的值低一个)。
接下来,我们需要一个函数来计算簇的聚类中心。 聚类中心只是当前分配给簇的所有样本的平均值。
data2 = pd.DataFrame(data.get('X'),columns=['X1','X2'])
print(data2.head())
sb.set(context="notebook",style="white")
sb.lmplot('X1','X2',data=data2, fit_reg=False)
plt.show()
def compute_centroids(X,idx,k):
m, n =X.shape
centroids = np.zeros((k,n))
for i in range(k):
indices = np.where(idx == i)
centroids[i,:] = (np.sum(X[indices,:],
axis=1)/len(indices[0])).ravel()
return centroids
print(compute_centroids(X,idx,3))
输出:
[[2.42830111 3.15792418]
[5.81350331 2.63365645]
[7.11938687 3.6166844 ]]
此输出也符合练习中的预期值。
下一部分涉及实际运行该算法的一些迭代次数和可视化结果。 这个步骤是由于并不复杂,我将从头开始构建它。 为了运行算法,我们只需要在将样本分配给最近的簇并重新计算簇的聚类中心。
实现代码:
def run_k_means(X,initial_centroids,max_iters):
m, n =X.shape
k = initial_centroids.shape[0]
idx = np.zeros(m)
centroids = initial_centroids
for i in range(max_iters):
idx = find_closest_centroids(X,centroids)
centroids = compute_centroids(X,idx,k)
return idx, centroids
idx, centroids = run_k_means(X,initial_centroids,10)
cluster1 = X[np.where(idx ==0)[0],:]
cluster2 = X[np.where(idx ==1)[0],:]
cluster3 = X[np.where(idx ==2)[0],:]
fig, ax =plt.subplots(figsize=(12,8))
ax.scatter(cluster1[:,0],cluster1[:,1],s=30,color='r',label='Cluster 1')
ax.scatter(cluster2[:,0],cluster2[:,1],s=30,color='g',label='Cluster 2')
ax.scatter(cluster3[:,0],cluster3[:,1],s=30,color='b',label='Cluster 3')
ax.legend()
plt.show()
我们跳过的一个步骤是初始化聚类中心的过程。 这可以影响算法的收敛。 我们的任务是创建一个选择随机样本并将其用作初始聚类中心的函数。
初始化聚类中心的过程
# 我们跳过的一个步骤是初始化聚类中心的过程。 这可以影响算法的收敛。 我们的任务是创建一个选择随机样本并将其用作初始聚类中心的函数。
def init_centroids(X,k):
m, n =X.shape
centroids = np.zeros((k,n))
idx = np.random.randint(0, m, k)
for i in range(k):
centroids[i,:] = X[idx[i],:]
return centroids
init_centroids(X,3)
应用-压缩图像
我们的下一个任务是将K-means应用于图像压缩。 从下面的演示可以看到,我们可以使用聚类来找到最具代表性的少数颜色,并使用聚类分配将原始的24位颜色映射到较低维的颜色空间。
下面是我们要压缩的图像。
from IPython.display import Image
Image(filename='data/bird_small.png')
# The raw pixel data has been pre-loaded for us so let's pull it in.
image_date = loadmat('data/bird_small.mat')
A = image_date['A']
print(A.shape)
导入图片的同时,我们也导入原始像素数据已经为我们预先加载好了,让我们把它拉进来
# The raw pixel data has been pre-loaded for us so let's pull it in.
image_date = loadmat('data/bird_small.mat')
A = image_date['A']
print(A.shape)
A = A / 255
X = np.reshape(A,(A.shape[0] * A.shape[1],A.shape[2]))
print(X.shape)
# 初始化 聚类的质心位置
initial_centroids = init_centroids(X,16)
# 运行算法
idx, centroids = run_k_means(X,initial_centroids,10)
# 获得最近一次最靠近质心的
idx = find_closest_centroids(X,centroids)
# 将每个像素映射到行心中去
X_recovered = centroids[idx.astype(int),:]
print(X_recovered.shape)
# 重新塑造原来的尺寸
X_recovered = np.reshape(X_recovered,(A.shape[0],A.shape[1],A.shape[2]))
print(X_recovered.shape)
plt.imshow(X_recovered)
plt.show()
得出图片
您可以看到我们对图像进行了压缩,但图像的主要特征仍然存在。 这就是K-means。
scikit-learn实现
下面我们来用scikit-learn来实现K-means。
from skimage import io
pic = io.imread('data/bird_small.png') / 255.
io.imshow(pic)
plt.show()
# 序列化数据
data =pic.reshape(128*128, 3)
print(data.shape)
from sklearn.cluster import KMeans #导入kMean包
model = KMeans(n_clusters=16, n_init=100, n_jobs=-1)
model.fit(data)
KMeans(algorithm='auto',copy_x=True,init='K-means++',max_iter=300,
n_clusters=16,n_init=100,n_jobs=-1,precompute_distances='auto',
random_state=None,tol=0.0001,verbose=0)
centroids = model.cluster_centers_
print(centroids.shape)
C = model.predict(data)
print(C.shape)
compressed_pic = centroids[C].reshape((128,126,3))
fig, ax = plt.subplots(1, 2)
ax[0].imshow(pic)
ax[1].imshow(compressed_pic)
plt.show()
Principal component analysis(主成分分析)
PCA是在数据集中找到“主成分”或最大方差方向的线性变换。 它可以用于降维。 在本练习中,我们首先负责实现PCA并将其应用于一个简单的二维数据集,以了解它是如何工作的。 我们从加载和可视化数据集开始。
def pca(X):
# 规范化的特性
X = (X - X.mean()) / X.std()
#计算协方差矩阵
X = np.matrix(X)
cov =(X.T * X) / X.shape[0]
# 应用在SVD
U,S,V =np.linalg.svd(cov)
return U,S,V
U,S,V = pca(X)
print(U,S,V)
现在我们有主成分(矩阵U),我们可以用这些来将原始数据投影到一个较低维的空间中。 对于这个任务,我们将实现一个计算投影并且仅选择顶部K个分量的函数,有效地减少了维数。
def project_data(X,U,k):
U_reduced = U[:,:k]
return np.dot(X,U_reduced)
Z = project_data(X,U,1)
print(Z)
def recover_data(Z,U,k):
U_reduced = U[:,:k]
return np.dot(Z,U_reduced.T)
X_recovered = recover_data(Z,U,1)
print(X_recovered)
请注意,第一主成分的投影轴基本上是数据集中的对角线。 当我们将数据减少到一个维度时,我们失去了该对角线周围的变化,所以在我们的再现中,一切都沿着该对角线。
应用:
最后一个任务是将PCA应用于脸部图像。 通过使用相同的降维技术,我们可以使用比原始图像少得多的数据来捕获图像的“本质”。
练习代码包括一个将渲染数据集中的前100张脸的函数。 而不是尝试在这里重新生成,您可以在练习文本中查看他们的样子。 我们至少可以很容易地渲染一个图像。
faces = loadmat('data/ex7faces.mat')
X = faces['X']
def plot_n_image(X,n):
#绘制前n幅图像,n必须是平方数
pic_size = int(np.sqrt(X.shape[1]))
grid_size = int(np.sqrt(n))
first_n_images = X[:n,:]
fig, ax_array = plt.subplots(nrows=grid_size, ncols=grid_size,
sharey=True, sharex=True, figsize=(8, 8))
for r in range(grid_size):
for c in range(grid_size):
ax_array[r, c].imshow(first_n_images[grid_size* r+c].
reshape((pic_size,pic_size)))
plt.xticks(np.array([]))
plt.yticks(np.array([]))
face = np.reshape(X[3,:],(32, 32))
plt.imshow(face)
plt.show()
看起来很糟糕。
这些只有32 x 32灰度的图像(它也是侧面渲染,但我们现在可以忽略)。
我们的下一步是在面数据集上运行PCA,并取得前100个主要特征。
U, S, V =pca(X)
Z = project_data(X,U,100)
X_recovered = recover_data(Z,U,100)
face = np.reshape(X_recovered[3,:],(32,32))
plt.imshow(face)
plt.show()
虽然没有将纬度缩小10倍,但是某些细节已经省了,但是我们还是可以得到大致的图像
实现的练习代码:
def find_closest_centroids(X, centroids):
m = X.shape[0]
k = centroids.shape[0]
idx = np.zeros(m)
for i in range(m):
min_dist = 1000000
for j in range(k):
dist = np.sum((X[i,:] - centroids[j,:]) ** 2)
if dist < min_dist:
min_dist = dist
idx[i] =j
return idx
data = loadmat('data/ex7data2.mat')
X = data['X']
initial_centroids = initial_centroids = np.array([[3,3],[6,2],[8,5]])
idx = find_closest_centroids(X,initial_centroids)
print(idx[0:3])
data2 = pd.DataFrame(data.get('X'),columns=['X1','X2'])
print(data2.head())
sb.set(context="notebook",style="white")
sb.lmplot('X1','X2',data=data2, fit_reg=False)
# plt.show()
def compute_centroids(X,idx,k):
m, n =X.shape
centroids = np.zeros((k,n))
for i in range(k):
indices = np.where(idx == i)
centroids[i,:] = (np.sum(X[indices,:],
axis=1)/len(indices[0])).ravel()
return centroids
print(compute_centroids(X,idx,3))
def run_k_means(X,initial_centroids,max_iters):
m, n =X.shape
k = initial_centroids.shape[0]
idx = np.zeros(m)
centroids = initial_centroids
for i in range(max_iters):
idx = find_closest_centroids(X,centroids)
centroids = compute_centroids(X,idx,k)
return idx, centroids
idx, centroids = run_k_means(X,initial_centroids,10)
cluster1 = X[np.where(idx ==0)[0],:]
cluster2 = X[np.where(idx ==1)[0],:]
cluster3 = X[np.where(idx ==2)[0],:]
fig, ax =plt.subplots(figsize=(12,8))
ax.scatter(cluster1[:,0],cluster1[:,1],s=30,color='r',label='Cluster 1')
ax.scatter(cluster2[:,0],cluster2[:,1],s=30,color='g',label='Cluster 2')
ax.scatter(cluster3[:,0],cluster3[:,1],s=30,color='b',label='Cluster 3')
ax.legend()
# plt.show()
# 我们跳过的一个步骤是初始化聚类中心的过程。 这可以影响算法的收敛。 我们的任务是创建一个选择随机样本并将其用作初始聚类中心的函数。
def init_centroids(X,k):
m, n =X.shape
centroids = np.zeros((k,n))
idx = np.random.randint(0, m, k)
for i in range(k):
centroids[i,:] = X[idx[i],:]
return centroids
init_centroids(X,3)
from IPython.display import Image
Image(filename='data/bird_small.png')
# The raw pixel data has been pre-loaded for us so let's pull it in.
image_date = loadmat('data/bird_small.mat')
A = image_date['A']
print(A.shape)
A = A / 255
X = np.reshape(A,(A.shape[0] * A.shape[1],A.shape[2]))
print(X.shape)
# 初始化 聚类的质心位置
initial_centroids = init_centroids(X,16)
# 运行算法
idx, centroids = run_k_means(X,initial_centroids,10)
# 获得最近一次最靠近质心的
idx = find_closest_centroids(X,centroids)
# 将每个像素映射到行心中去
X_recovered = centroids[idx.astype(int),:]
print(X_recovered.shape)
# 重新塑造原来的尺寸
X_recovered = np.reshape(X_recovered,(A.shape[0],A.shape[1],A.shape[2]))
print(X_recovered.shape)
plt.imshow(X_recovered)
# plt.show()
#使用scikit-lrarn来实现
from skimage import io
pic = io.imread('data/bird_small.png') / 255.
# io.imshow(pic)
# plt.show()
# 序列化数据
data =pic.reshape(128*128, 3)
print(data.shape)
from sklearn.cluster import KMeans #导入kMean包
model = KMeans(n_clusters=16, n_init=100, n_jobs=-1)
model.fit(data)
KMeans(algorithm='auto',copy_x=True,init='K-means++',max_iter=300,
n_clusters=16,n_init=100,n_jobs=-1,precompute_distances='auto',
random_state=None,tol=0.0001,verbose=0)
centroids = model.cluster_centers_
print(centroids.shape)
C = model.predict(data)
print(C.shape)
compressed_pic = centroids[C].reshape((128,128,3))
fig, ax = plt.subplots(1, 2)
# ax[0].imshow(pic)
# ax[1].imshow(compressed_pic)
# plt.show()
data = loadmat('data/ex7data1.mat')
print(data)
X = data['X']
fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(X[:,0],X[:,1])
plt.show()
#PCA的算法相当简单。 在确保数据被归一化之后,输出仅仅是原始数据的协方差矩阵的奇异值分
def pca(X):
# 规范化的特性
X = (X - X.mean()) / X.std()
#计算协方差矩阵
X = np.matrix(X)
cov =(X.T * X) / X.shape[0]
# 应用在SVD
U,S,V =np.linalg.svd(cov)
return U,S,V
U,S,V = pca(X)
print(U,S,V)
def project_data(X,U,k):
U_reduced = U[:,:k]
return np.dot(X,U_reduced)
Z = project_data(X,U,1)
print(Z)
def recover_data(Z,U,k):
U_reduced = U[:,:k]
return np.dot(Z,U_reduced.T)
X_recovered = recover_data(Z,U,1)
print(X_recovered)
faces = loadmat('data/ex7faces.mat')
X = faces['X']
def plot_n_image(X,n):
#绘制前n幅图像,n必须是平方数
pic_size = int(np.sqrt(X.shape[1]))
grid_size = int(np.sqrt(n))
first_n_images = X[:n,:]
fig, ax_array = plt.subplots(nrows=grid_size, ncols=grid_size,
sharey=True, sharex=True, figsize=(8, 8))
for r in range(grid_size):
for c in range(grid_size):
ax_array[r, c].imshow(first_n_images[grid_size* r+c].
reshape((pic_size,pic_size)))
plt.xticks(np.array([]))
plt.yticks(np.array([]))
face = np.reshape(X[3,:],(32, 32))
# plt.imshow(face)
# plt.show()
U, S, V =pca(X)
Z = project_data(X,U,100)
X_recovered = recover_data(Z,U,100)
face = np.reshape(X_recovered[3,:],(32,32))
plt.imshow(face)
plt.show()