數(shù)據(jù)清洗和特征選擇:主成分分析

主成分分析:Principal Component Analysis.PCA

PCA就是數(shù)據(jù)降維嘹叫,最重要的能力就是數(shù)據(jù)可視化(高維數(shù)據(jù))

一個二維數(shù)據(jù)诈乒,我們可以在這個圖中找到一根直線罩扇,使得所有的數(shù)據(jù)點在這根直線上的投影差異化最大(其實就是方差最大),很顯然,在A喂饥,B消约,C三條線中,B是最符合的

PCA的本質(zhì)就是找一些相互正交的投影方向员帮,使得數(shù)據(jù)在這些投影方向上的方差最大(找新的一組正交基)或粮。計算原始數(shù)據(jù)在這些正交基上投影的方差,方差越大捞高,就說明在對應(yīng)正交基上包含了更多的信息量氯材。
原始數(shù)據(jù)協(xié)方差矩陣的特征值越大,對應(yīng)的方差越大硝岗,在對應(yīng)的特征向量上投影的信息量就越大氢哮,就是主成分。反之特征值小型檀,數(shù)據(jù)在這些特征向量上投影的信息量很小冗尤,可以將小特征值對應(yīng)方向的數(shù)據(jù)刪除,從而達(dá)到了降維的目的胀溺。
我們可以選擇最大的n個特征值裂七,將數(shù)據(jù)降到n維,做個歸一化然后看這幾個特征值的權(quán)重仓坞,可以是超過80%或者95%背零,具體大小看業(yè)務(wù)的要求。

PCA的主要邏輯

* 去除平均值
* 計算協(xié)方差矩陣
* 計算協(xié)方差矩陣的特征值和特征向量
* 將特征值從大到小排序
* 保留最大的N個特征向量
* 將數(shù)據(jù)轉(zhuǎn)換到上述N個特征向量構(gòu)建的新空間中

教材實例(一):某工廠半導(dǎo)體特征數(shù)據(jù)

《ML in Action》p246扯躺,

數(shù)據(jù)源

# -*- coding:utf-8 -*-
from numpy import *

#格式化數(shù)據(jù)函數(shù)
def loadDataSet(filename, delim='\t'):
    fr = open(filename)
    stringArr = [line.strip().split(delim) for line in fr.readlines()]
    datArr = [map(float, line) for line in stringArr]
    return mat(datArr)

def pca(dataMat, topNfeat=999999):
    meanVals = mean(dataMat)
    # meanVals = mean(dataMat, axis=0)
    # axis =0 說明按列求均值,否則是按行
    meanRemoved = dataMat - meanVals #去均值
    covMat = cov(meanRemoved, rowvar=0) #協(xié)方差矩陣
    # rowvar=0很重要蝎困,表明每一行是一個樣本录语,否則numpy認(rèn)為整個數(shù)據(jù)是一個樣本
    eigVals,eigVects = linalg.eig(mat(covMat))
    # numpy內(nèi)建函數(shù),一次性求出特征值和特征向量
    eigValInd = argsort(eigVals)
    eigValInd = eigValInd[:-(topNfeat+1):-1]
    redEigVects = eigVects[:,eigValInd]
    # 對特征值從小到大排序
    lowDDataMat = meanRemoved * redEigVects
    # 將數(shù)據(jù)集投影到新的空間禾乘,結(jié)果是一個低維數(shù)據(jù)
    reconMat = (lowDDataMat * redEigVects.T) + meanVals
    return lowDDataMat, reconMat

# 缺失值處理
def replaceNanWithMean():
    datMat = loadDataSet('secom.data', ' ')
    numFeat = shape(datMat)[1]
    for i in range(numFeat):
        meanVal = mean(datMat[nonzero(~isnan(datMat[:,i].A))[0],i])
        datMat[nonzero(isnan(datMat[:,i].A))[0],i] = meanVal
    return datMat

if __name__ == '__main__':
    dataMat = replaceNanWithMean()
    meanVals = mean(dataMat, axis=0)
    meanRemoved = dataMat - meanVals
    covMat = cov(meanRemoved, rowvar=0)
    eigVals, eigVects = linalg.eig(mat(covMat))

當(dāng)我們試著把eigVals打印出來以后(由于結(jié)果太冗長就不再打印出來)澎埠,會發(fā)現(xiàn)前30個特征值就占了99%以上的權(quán)重,如果這符合業(yè)務(wù)要求的話始藕,那么我們就成功地將一個590維數(shù)據(jù)降到了30維蒲稳。

也可以寫成權(quán)重百分比版本:

def pca(dataMat,percentage=0.99):
    newData,meanVal=zeroMean(dataMat)
    covMat=np.cov(newData,rowvar=0)    #求協(xié)方差矩陣,return ndarray;若rowvar非0伍派,一列代表一個樣本江耀,為0,一行代表一個樣本
    eigVals,eigVects=np.linalg.eig(np.mat(covMat))#求特征值和特征向量,特征向量是按列放的诉植,即一列代表一個特征向量
    n=percentage2n(eigVals,percentage)                 #要達(dá)到percent的方差百分比祥国,需要前n個特征向量
    eigValIndice=np.argsort(eigVals)            #對特征值從小到大排序
    n_eigValIndice=eigValIndice[-1:-(n+1):-1]   #最大的n個特征值的下標(biāo)
    n_eigVect=eigVects[:,n_eigValIndice]        #最大的n個特征值對應(yīng)的特征向量
    lowDDataMat=newData*n_eigVect               #低維特征空間的數(shù)據(jù)
    reconMat=(lowDDataMat*n_eigVect.T)+meanVal  #重構(gòu)數(shù)據(jù)
    return lowDDataMat,reconMat

教材實例(二):鳶尾花數(shù)據(jù) Iris

PCA經(jīng)典數(shù)據(jù),數(shù)據(jù)源
利用sklearn中現(xiàn)有的PCA工具。

Data Preview:
5.1,3.5,1.4,0.2,Iris-setosa
4.9,3.0,1.4,0.2,Iris-setosa
5.5,2.3,4.0,1.3,Iris-versicolor
...
Attribute Information:
   1. sepal length in cm
   2. sepal width in cm
   3. petal length in cm
   4. petal width in cm
   5. class: 
      -- Iris Setosa
      -- Iris Versicolour
      -- Iris Virginica

代碼如下:

# -*- coding:utf-8 -*-

import pandas as pd
import numpy as np
from sklearn.decomposition import PCA
from sklearn.feature_selection import SelectKBest, SelectPercentile, chi2
from sklearn.linear_model import LogisticRegressionCV
from sklearn import metrics
from sklearn.model_selection import train_test_split
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures


def extend(a, b):
    return 1.05*a-0.05*b, 1.05*b-0.05*a

if __name__ == '__main__':
    pca = True
    pd.set_option('display.width', 200)
    data = pd.read_csv('iris.data', header=None)
    # columns = np.array(['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'type'])
    columns = np.array([u'花萼長度', u'花萼寬度', u'花瓣長度', u'花瓣寬度', u'類型'])
    data.rename(columns=dict(zip(np.arange(5), columns)), inplace=True)

    data[u'類型'] = pd.Categorical(data[u'類型']).codes 
    #pd的類型變量功能
    print data.head(5)

    x = data[columns[:-1]]
    y = data[columns[-1]]

sklearn.PCA說明

參數(shù):

  • n_components: 主成分個數(shù)舌稀。
    賦值int啊犬,比如n_components=1覆糟,將把原始數(shù)據(jù)降到一個維度。
    賦值string咒林,比如n_components='mle'睡腿,將自動選取特征個數(shù)n,使得滿足所要求的方差百分比嫉到。
    默認(rèn)為None何恶,只求特征值惜辑,不做降維處理疫赎。
  • copy:bool盛撑,True或者False抵卫,缺省時默認(rèn)為True。表示是否在運行算法時胎撇,將原始訓(xùn)練數(shù)據(jù)復(fù)制一份介粘。若為True,在原始數(shù)據(jù)的副本上進行運算晚树;若為False姻采,則運行PCA算法后原始訓(xùn)練數(shù)據(jù)的值會改。
  • whiten: bool爵憎,缺省時默認(rèn)為False白化慨亲,使得每個特征具有相同的方差。白化

屬性:

  • components_ :返回具有最大方差的成分宝鼓。
  • explained_variance_ratio_:返回 所保留的n個成分各自的方差百分比刑棵。
  • n_components_:返回所保留的成分個數(shù)n。
  • mean_:
  • noise_variance_:

方法:

  • fit(X,y=None)
    fit()可以說是scikit-learn中通用的方法愚铡,每個需要訓(xùn)練的算法都會有fit()方法铐望,它其實就是算法中的“訓(xùn)練”這一步驟。因為PCA是無監(jiān)督學(xué)習(xí)算法,此處y自然等于None正蛙。fit(X)督弓,表示用數(shù)據(jù)X來訓(xùn)練PCA模型。
    函數(shù)返回值:調(diào)用fit方法的對象本身乒验。比如pca.fit(X)愚隧,表示用X對pca這個對象進行訓(xùn)練。
  • fit_transform(X)
    用X來訓(xùn)練PCA模型锻全,同時返回降維后的數(shù)據(jù)狂塘。
    newX=pca.fit_transform(X),newX就是降維后的數(shù)據(jù)鳄厌。
  • inverse_transform()
    將降維后的數(shù)據(jù)轉(zhuǎn)換成原始數(shù)據(jù)荞胡,X=pca.inverse_transform(newX)
  • transform(X)
    將數(shù)據(jù)X轉(zhuǎn)換成降維后的數(shù)據(jù)。當(dāng)模型訓(xùn)練好后了嚎,對于新輸入的數(shù)據(jù)泪漂,都可以用transform方法來降維。
  • 此外歪泳,還有g(shù)et_covariance()萝勤、get_precision()、get_params(deep=True)呐伞、score(X, y=None)等方法敌卓。
    if pca:
        pca = PCA(n_components=2, whiten=True, random_state=0)
        x = pca.fit_transform(x)
        print '各方向方差:', pca.explained_variance_
        print '方差所占比例:', pca.explained_variance_ratio_
        x1_label, x2_label = u'組分1', u'組分2'
        title = u'鳶尾花數(shù)據(jù)PCA降維'
    else:
        fs = SelectKBest(chi2, k=2)
        # fs = SelectPercentile(chi2, percentile=60)
        fs.fit(x, y)
        idx = fs.get_support(indices=True)
        print 'fs.get_support() = ', idx
        x = x[idx]
        x = x.values    # 為下面使用方便,DataFrame轉(zhuǎn)換成ndarray
        x1_label, x2_label = columns[idx]
        title = u'鳶尾花數(shù)據(jù)特征選擇'
    print x[:5]
    cm_light = mpl.colors.ListedColormap(['#77E0A0', '#FF8080', '#A0A0FF'])
    cm_dark = mpl.colors.ListedColormap(['g', 'r', 'b'])
    mpl.rcParams['font.sans-serif'] = u'SimHei'
    mpl.rcParams['axes.unicode_minus'] = False
    plt.figure(facecolor='w')
    plt.scatter(x[:, 0], x[:, 1], s=30, c=y, marker='o', cmap=cm_dark)
    plt.grid(b=True, ls=':')
    plt.xlabel(x1_label, fontsize=14)
    plt.ylabel(x2_label, fontsize=14)
    plt.title(title, fontsize=18)
    # plt.savefig('1.png')
    plt.show()

    x, x_test, y, y_test = train_test_split(x, y, train_size=0.7)
    model = Pipeline([
        ('poly', PolynomialFeatures(degree=2, include_bias=True)),
        ('lr', LogisticRegressionCV(Cs=np.logspace(-3, 4, 8), cv=5, fit_intercept=False))
    ])
    model.fit(x, y)
    print '最優(yōu)參數(shù):', model.get_params('lr')['lr'].C_
    y_hat = model.predict(x)
    print '訓(xùn)練集精確度:', metrics.accuracy_score(y, y_hat)
    y_test_hat = model.predict(x_test)
    print '測試集精確度:', metrics.accuracy_score(y_test, y_test_hat)

    N, M = 500, 500     # 橫縱各采樣多少個值
    x1_min, x1_max = extend(x[:, 0].min(), x[:, 0].max())   # 第0列的范圍
    x2_min, x2_max = extend(x[:, 1].min(), x[:, 1].max())   # 第1列的范圍
    t1 = np.linspace(x1_min, x1_max, N)
    t2 = np.linspace(x2_min, x2_max, M)
    x1, x2 = np.meshgrid(t1, t2)                    # 生成網(wǎng)格采樣點
    x_show = np.stack((x1.flat, x2.flat), axis=1)   # 測試點
    y_hat = model.predict(x_show)  # 預(yù)測值
    y_hat = y_hat.reshape(x1.shape)  # 使之與輸入的形狀相同
    plt.figure(facecolor='w')
    plt.pcolormesh(x1, x2, y_hat, cmap=cm_light)  # 預(yù)測值的顯示
    plt.scatter(x[:, 0], x[:, 1], s=30, c=y, edgecolors='k', cmap=cm_dark)  # 樣本的顯示
    plt.xlabel(x1_label, fontsize=14)
    plt.ylabel(x2_label, fontsize=14)
    plt.xlim(x1_min, x1_max)
    plt.ylim(x2_min, x2_max)
    plt.grid(b=True, ls=':')
    patchs = [mpatches.Patch(color='#77E0A0', label='Iris-setosa'),
              mpatches.Patch(color='#FF8080', label='Iris-versicolor'),
              mpatches.Patch(color='#A0A0FF', label='Iris-virginica')]
    plt.legend(handles=patchs, fancybox=True, framealpha=0.8, loc='lower right')
    plt.title(u'鳶尾花Logistic回歸分類效果', fontsize=17)
    # plt.savefig('2.png')
    plt.show()

最后要注意的是伶氢,PCA同獨立成分分析等方法一樣趟径,是不假設(shè)樣本處于何種具體分布的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末癣防,一起剝皮案震驚了整個濱河市蜗巧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌劣砍,老刑警劉巖惧蛹,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扇救,死亡現(xiàn)場離奇詭異刑枝,居然都是意外死亡,警方通過查閱死者的電腦和手機迅腔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門装畅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人沧烈,你說我怎么就攤上這事掠兄。” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵蚂夕,是天一觀的道長迅诬。 經(jīng)常有香客問我,道長婿牍,這世上最難降的妖魔是什么侈贷? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮等脂,結(jié)果婚禮上俏蛮,老公的妹妹穿的比我還像新娘。我一直安慰自己上遥,他們只是感情好搏屑,可當(dāng)我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著粉楚,像睡著了一般辣恋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上解幼,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天抑党,我揣著相機與錄音,去河邊找鬼撵摆。 笑死底靠,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的特铝。 我是一名探鬼主播暑中,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼鲫剿!你這毒婦竟也來了鳄逾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤灵莲,失蹤者是張志新(化名)和其女友劉穎雕凹,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體政冻,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡枚抵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了明场。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片汽摹。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖苦锨,靈堂內(nèi)的尸體忽然破棺而出逼泣,到底是詐尸還是另有隱情趴泌,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布拉庶,位于F島的核電站嗜憔,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏氏仗。R本人自食惡果不足惜痹筛,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望廓鞠。 院中可真熱鬧帚稠,春花似錦、人聲如沸床佳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽砌们。三九已至杆麸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間浪感,已是汗流浹背昔头。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留影兽,地道東北人揭斧。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像峻堰,于是被迫代替她去往敵國和親讹开。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)自:主成分分析 - xiaoyu714543065的專欄 - 博客頻道 - CSDN.NET 問題...
    horu閱讀 1,186評論 1 3
  • 文章主要參考于大神城東(部分認(rèn)為有問題的地方進行了修改) 1. 特征工程是什么捐名? 數(shù)據(jù)和特征決定了機器學(xué)習(xí)的上限旦万,...
    jockerMe閱讀 1,710評論 0 11
  • 在現(xiàn)實生活中很多機器學(xué)習(xí)問題有上千維,甚至上萬維特征镶蹋,這不僅影響了訓(xùn)練速度成艘,通常還很難找到比較好的解。這樣的問題成...
    wong11閱讀 61,339評論 0 36
  • Dataset transformations| 數(shù)據(jù)轉(zhuǎn)換 Combining estimators|組合學(xué)習(xí)器 ...
    houhzize閱讀 4,321評論 0 4
  • 前言 PCA是一種無參數(shù)的數(shù)據(jù)降維方法贺归,在機器學(xué)習(xí)中很常用淆两,這篇文章主要從三個角度來說明PCA是怎么降維的分別是方...
    WZFish0408閱讀 51,435評論 6 36