天天看點

SparkML機器學習之特征工程(二)特征轉化(Binarizer、StandardScaler、MaxAbsScaler、Normalizer、N-gram、Tokenizer等)特征轉化

為什麼要轉化資料呢,就是要讓它成為有效的特征,因為原始資料是很多髒資料無用資料的。常用的方法是标準化,歸一化,特征的離散化等等。比如我輸入的資料是句子,我得把它切分為一個個單詞進行分析,這就是一種轉化。

假設淘寶現在有個需求,我得根據年齡來進行物品推薦,把50以上的人分為老年,50以下分為非老年人,那麼我們根據二值化可以很簡單的把50以上的定為1,50以下的定為0。這樣就友善我們後續的推薦了。Binarizer就是根據門檻值進行二值化,大于門檻值的為1.0,小于等于門檻值的為0.0

輸出結果:

現在淘寶的需求變了,他們覺得把人分為50以上和50以下太不精準了,應該分為20歲以下,20-30歲,30-40歲,36-50歲,50以上,那麼就得用到數值離散化的處理方法了。離散化就是把特征進行适當的離散處理,比如上面所說的年齡是個連續的特征,但是我把它分為不同的年齡階段就是把它離散化了,這樣更利于我們分析使用者行為進行精準推薦。Bucketizer能友善的将一堆資料分成不同的區間。

有時候我們不想給定分類标準,可以讓spark自動給我們分箱。

對于同一個特征,不同的樣本中的取值可能會相差非常大,一些異常小或異常大的資料會誤導模型的正确訓練;另外,如果資料的分布很分散也會影響訓練結果。以上兩種方式都展現在方差會非常大。此時,我們可以将特征中的值進行标準差标準化,即轉換為均值為0,方差為1的正态分布。如果特征非常稀疏,并且有大量的0(現實應用中很多特征都具有這個特點),Z-score 标準化的過程幾乎就是一個除0的過程,結果不可預料。是以在訓練模型之前,一定要對特征的資料分布進行探索,并考慮是否有必要将資料進行标準化。基于特征值的均值(mean)和标準差(standard deviation)進行資料的标準化。它的計算公式為:标準化資料=(原資料-均值)/标準差。标準化後的變量值圍繞0上下波動,大于0說明高于平均水準,小于0說明低于平均水準。

為什麼資料需要歸一化?以房價預測為案例,房價(y)通常與離市中心距離(x1)、面積(x2)、樓層(x3)有關,設y=ax1+bx2+cx3,那麼abc就是我們需要重點解決的參數。但是有個問題,面積一般數值是比較大的,100平甚至更多,而距離一般都是幾公裡而已,b參數隻要一點變化都能對房價産生巨大影響,而a的變化對房價的影響相對就小很多了。顯然這會影響最終的準确性,畢竟距離可是個非常大的影響因素啊。 是以, 需要使用特征的歸一化, 取值跨度大的特征資料, 我們濃縮一下, 跨度小的括展一下, 使得他們的跨度盡量統一。

歸一化就是将所有特征值都等比地縮小到0-1或者-1到1之間的區間内。其目的是為了使特征都在相同的規模中。

運作結果:

運作結果為:

為什麼要有正則化?就是為了防止過拟合。來看一下正則化是怎麼計算的:

輸出結果為:

N-Gram認為語言中每個單詞隻與其前面長度 N-1 的上下文有關。主要分為bigram和trigram,bigram假設下一個詞的出現依賴它前面的一個詞,trigram假設下一個詞的出現依賴它前面的兩個詞。在SparkML中用NGram類實作,setN(2)為bigram,setN(3)為trigram。

有時候要對特征值進行一些多項式的轉化,比如平方啊,三次方啊等等,那就用到了PolynomialExpansion。

當我們的輸入資料為文本(句子)的時候,我們會想把他們切分為單詞再進行資料處理,這時候就要用到Tokenizer類了。

我們都很喜歡sql語句,簡單好用又熟悉,那麼Spark ML很人性化的為我們提供了SQLTransformer類,使得我們能用我們熟悉的SQL來做特征轉化。它支援SparkSql中的所有select選擇語句,sum(),count(),group by,order by等等都可以用!形如"SELECT ...FROM __THIS__"。'__THIS__'代表輸入資料的基礎表。