协方差理解,PCA以及奇异值分解(SVD)
生活随笔
收集整理的這篇文章主要介紹了
协方差理解,PCA以及奇异值分解(SVD)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一.PCA
PCA通過正交變換將一組由線性相關變量表示的數據轉換為少數幾個由線性無關變量表示的數據,這幾個線性無關的變量就是主成分。PCA通過將高維數據維度減少到少數幾個維度,本質上屬于一種數據降維方法,也可以用來探索數據的內在結構。?
可看出如果兩個隨機變量的分布相似,它們的協方差很大。?
?
?
import numpy as npclass PCA():# 計算協方差矩陣def calculate_covariance_matrix(self, X):m = X.shape[0]# 數據標準化X = X - np.mean(X, axis=0)#(x1 - Ex1) (x2 - Ex2)return 1 / m * np.matmul(X.T, X)def compute_feature(self, X, n_components):# 計算協方差矩陣covariance_matrix = self.calculate_covariance_matrix(X)print('==covariance_matrix:', covariance_matrix.shape)# 計算協方差矩陣的特征值和對應特征向量eigenvalues, eigenvectors = np.linalg.eig(covariance_matrix)print('=eigenvectors.shape:', eigenvectors.shape)# 對特征值排序idx = eigenvalues.argsort()[::-1]# 取最大的前n_component組eigenvectors = eigenvectors[:, idx]eigenvectors = eigenvectors[:, :n_components]# Y=PX轉換return np.matmul(X, eigenvectors)#兩個樣本 一個樣本有三維 X = np.array([[4, 1, 3],[2, 2, 4]]) print('X:', X) pca = PCA() Y = pca.compute_feature(X, 2)#降到2維 print('Y:', Y) import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import load_digits from sklearn.decomposition import PCA from mpl_toolkits.mplot3d import Axes3Ddef plot_digits(images, y, max_n=10):"""顯示手寫數字的圖像"""# 設置圖像尺寸fig = plt.figure(figsize=(2. * n_col, 2.26 * n_row))i = 0while i < max_n and i < images.shape[0]:p = fig.add_subplot(n_row, n_col, i + 1, xticks=[], yticks=[])p.imshow(images[i], cmap=plt.cm.bone, interpolation='nearest')# 添加標簽p.text(0, -1, str(y[i]))i = i + 1plt.show()# 顯示8*8數字 # plot_digits(digits.images, digits.target, max_n=10)def plot_pca_scatter_three(digits, X_pca, y_digits, class_nums):"""主成分顯示"""##顯示3Dfig = plt.figure()ax = fig.add_subplot(111, projection='3d')for i in range(len(class_nums)):# print('==y_digits == i:', y_digits == i)print(X_pca[:, 0][y_digits == i].shape)print(X_pca[:, 1][y_digits == i].shape)print(X_pca[:, 2][y_digits == i].shape)ax.scatter(X_pca[:, 0][y_digits == i], X_pca[:, 1][y_digits == i], X_pca[:, 2][y_digits == i], label = class_nums[i])plt.legend(digits.target_names)ax.set_xlabel('First Principal Component')ax.set_ylabel('Second Principal Component')ax.set_zlabel('Third Principal Component')plt.savefig('./three.jpg')plt.show()def plot_pca_scatter_two(digits, X_pca, y_digits, class_nums):# 顯示2Dfor i in range(len(class_nums)):px = X_pca[:, 0][y_digits == i]py = X_pca[:, 1][y_digits == i]plt.scatter(px, py, label=class_nums[i])plt.legend(digits.target_names)plt.xlabel('First Principal Component')plt.ylabel('Second Principal Component')plt.savefig('./two.jpg')plt.show()def pca_aysis_two_components():digits = load_digits()X_digits, y_digits = digits.data, digits.target# n_row, n_col = 2, 5print('=X_digits.shape:', X_digits.shape)print('==y_digits:', y_digits[:10])print(len(y_digits))class_nums = [i for i in range(10)]n_components = 2 # 取前2個主成分pca = PCA(n_components=n_components)# fit_transform表示做完訓練以后并進行轉換X_pca = pca.fit_transform(X_digits)print('==X_pca.shape:', X_pca.shape)plot_pca_scatter_two(digits, X_pca, y_digits, class_nums)def pca_aysis_three_components():digits = load_digits()X_digits, y_digits = digits.data, digits.targetprint('=X_digits.shape:', X_digits.shape)print('==y_digits:', y_digits[:10])print(len(y_digits))class_nums = [i for i in range(10)]n_components = 3 # 取前2個主成分pca = PCA(n_components=n_components)# fit_transform表示做完訓練以后并進行轉換X_pca = pca.fit_transform(X_digits)print('==X_pca.shape:', X_pca.shape)plot_pca_scatter_three(digits, X_pca, y_digits, class_nums)if __name__ == '__main__':# pca_aysis_two_components()pca_aysis_three_components()可視化二維的時候:
?
可視化三維的時候:
二.SVD
numpy案例
A = np.array([[4, 1, 3],[2, 2, 4]]) print('A:\n', A)# 對其進行SVD分解 s是對角矩陣的值 u, s, vt = np.linalg.svd(A, full_matrices=True) print('u.shape, s.shape, vt.shape:', u.shape, s.shape, vt.shape) res = np.dot(u*s, vt[:2, :]) print('res:', res) #U UT=I print('np.dot(u, u.T):\n', np.dot(u, u.T)) #v vT=I print('np.dot(vt, vt.T):\n', np.dot(vt, vt.T))將SVD用于圖像的壓縮算法。其原理就是保存像素矩陣的前k個奇異值,并在此基礎上做圖像恢復。由SVD的原理我們可以知道,在SVD分解中越靠前的奇異值越重要,代表的信息含量越大。?
import cv2 import numpy as np import os from tqdm import tqdm# 定義恢復函數,由分解后的矩陣恢復到原矩陣 def restore(u, s, v, K):'''u:左奇異矩陣 u uT=Iv:右奇異矩陣 v vT=Is:奇異值矩陣 對角矩陣K:奇異值個數'''m, n = len(u), len(v)a = np.zeros((m, n))for k in range(K):uk = u[:, k].reshape(m, 1)vk = v[k].reshape(1, n)# 前k個奇異值的加總a += np.dot(uk * s[k], vk)a = a.clip(0, 255)return np.rint(a).astype('uint8')img = cv2.imread("./111.png") print('==img.shape:', img.shape) h,w,_ = img.shape # 對RGB圖像進行奇異值分解 u_b, s_b, v_b = np.linalg.svd(img[:, :, 0]) u_g, s_g, v_g = np.linalg.svd(img[:, :, 1]) u_r, s_r, v_r = np.linalg.svd(img[:, :, 2])print('==u_b.shape, s_b.shape, v_b.shape:', u_b.shape, s_b.shape, v_b.shape) B = np.dot(u_b * s_b, v_b[:h, :]) print('B:', B.shape)G = np.dot(u_g * s_g, v_g[:h, :]) print('G:', G.shape)R = np.dot(u_r * s_r, v_r[:h, :]) print('R:', R.shape)# # 使用前短邊個奇異值 K = min(img.shape[:2]) new_img = cv2.merge([B, G, R]) cv2.imwrite('./test_svd.jpg', new_img)# # 恢復圖像 ouput_path = './svd' os.makedirs(ouput_path, exist_ok=True) for k in tqdm(range(1, K + 1)):B = restore(u_b, s_b, v_b, k)R = restore(u_r, s_r, v_r, k)G = restore(u_g, s_g, v_g, k)new_img = cv2.merge([B, G, R])cv2.imwrite(os.path.join(ouput_path, '{}.jpg'.format(k)), new_img)總結
以上是生活随笔為你收集整理的协方差理解,PCA以及奇异值分解(SVD)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: seaborn的一些画图
- 下一篇: 常用的编码