python非数值型数据_Python机器学习实战:如何处理非数值特征
機器學習實戰(zhàn):這里沒有艱深晦澀的數(shù)學理論,我們將用簡單的案例和大量的示例代碼,向大家介紹機器學習的核心概念。我們的目標是教會大家用Python構(gòu)建機器學習模型,解決現(xiàn)實世界的難題。
本文來自《數(shù)據(jù)黑客》,登錄官網(wǎng)可精彩資訊和文章。數(shù)據(jù)黑客 - 專注金融大數(shù)據(jù)的內(nèi)容聚合和數(shù)據(jù)聚合平臺?finquanthub.com
機器學習模型要求輸入為數(shù)值變量,特征必須是大小為(n_samples, n_features)的數(shù)值矩陣,目標是(n_samples, 1)的數(shù)值向量。但現(xiàn)實世界的數(shù)據(jù)集有可能包含非數(shù)值數(shù)據(jù),例如分類變量,文本數(shù)據(jù)和圖像。
這時候需要進行數(shù)據(jù)預處理(data preprocessing),即采用一些技巧將非數(shù)值變量轉(zhuǎn)換為數(shù)值變量。
1. 分類變量
分類變量通常分為兩種:有序和無序。有序:類別可以相互比較,有大小之分,可以直接轉(zhuǎn)化為數(shù)值變量。假設代表收入的變量'income'有3個類別,'low','medium','high',分別代表低收入,中等收入,高收入,類別是可以直接比較的,并且可以排序,'low' < 'medium' < 'high'。
無序:類別不可以比較,需要引入虛擬變量(dummy variable),常用編碼技術是獨熱編碼(one-hot encoding)。例如代表性別的變量'gender'有兩個類別,'male'和'female',但'male' < 'female'的關系并不成立。
將分類變量轉(zhuǎn)化為數(shù)值變量有兩種常用方法:標簽編碼和獨熱編碼。
1.1 標簽編碼
標簽編碼(label encoding): 將分類變量的類別編碼為數(shù)字。
用sklearn.preprocessing.LabelEncoder實現(xiàn),將包含k個類別的分類變量編碼為$0,1,2,...(k-1)$
標簽編碼一般不用于特征,而是用于目標變量。
假設一個代表性別的特征'gender',包含兩個類別:'male','female'。標簽編碼將類別編碼為整數(shù),0代表男性,1代表女性。但這不符合模型背后的假設,因為機器學習模型認為數(shù)據(jù)有算數(shù)含義,例如0 < 1,這意味著男性 < 女性,但這種關系不成立。一般會使用獨熱編碼處理分類特征,標簽編碼僅用于分類目標。
接下來說明如何使用標簽編碼,假設目標變量代表股票價格趨勢,有3種可能的類別,'up','down','range'.
from sklearn.preprocessing import LabelEncoder
# 目標變量
y = ["up", "up", "down", "range", "up", "down", "range", "range", "down"]
# 創(chuàng)建LabelEncoder對象
le = LabelEncoder()
# 擬合數(shù)據(jù)
le.fit(y)
# 查看包含哪些類別
print("classes: ", le.classes_)
# 編碼為數(shù)字
print("encoded labels: ", le.transform(y))
# 調(diào)用inverse_transform實現(xiàn)反向操作
print("inverse encoding: ", le.inverse_transform([0, 1, 2]))
classes: ['down' 'range' 'up']
encoded labels: [2 2 0 1 2 0 1 1 0]
inverse encoding: ['down' 'range' 'up']
1.2 獨熱編碼
獨熱編碼(one hot encoding): 將包含m個類別的分類變量轉(zhuǎn)化為$n*m$的二元矩陣,n是觀測值數(shù)量,m是類別數(shù)量。
假設分類變量'car_type',表示汽車類型,包含類別(BMW, Tesla, Audi),獨熱編碼將產(chǎn)生下圖的結(jié)果,每一個類別都成為一個新的變量/特征,1表示觀測值包含該類別,0表示不包含。
sklearn提供OneHotEncoder類實現(xiàn)獨熱編碼。
import numpy as np
import pandas as pd
from sklearn.preprocessing import OneHotEncoder
# 分類特征
car_types = np.array(["BMW", "Tesla", "Audi", "BMW", "Audi"])
# 創(chuàng)建編碼器
oe = OneHotEncoder()
# OneHotEncoder要求輸入為二維數(shù)組,用reshape重排結(jié)構(gòu)
oe.fit(car_types.reshape(-1, 1))
# 查看類別
print("classes: ", oe.categories_)
# 調(diào)用transform獲得編碼結(jié)果
# transform默認返回稀疏矩陣,當分類變量包含很多類別時非常有用,進一步調(diào)用toarray可獲得熟悉的numpy二維數(shù)組
# 創(chuàng)建OneHotEncoder實例時,如果設置sparse=False,調(diào)用transform會得到二維數(shù)組
encoded_labels = oe.transform(car_types.reshape(-1, 1)).toarray()
print(encoded_labels)
# 用數(shù)據(jù)框展現(xiàn)最終的結(jié)果,便于理解
encoded_labels_df = pd.DataFrame(encoded_labels, columns=oe.categories_)
print(encoded_labels_df)
classes: [array(['Audi', 'BMW', 'Tesla'], dtype='
[[0. 1. 0.]
[0. 0. 1.]
[1. 0. 0.]
[0. 1. 0.]
[1. 0. 0.]]
Audi BMW Tesla
0 0.0 1.0 0.0
1 0.0 0.0 1.0
2 1.0 0.0 0.0
3 0.0 1.0 0.0
4 1.0 0.0 0.0
調(diào)用pd.get_dummies實現(xiàn)獨熱編碼,這比sklearn的接口更方便,因為它允許我們直接操作數(shù)據(jù)框。
pd.get_dummies默認將數(shù)據(jù)類型為'object'的變量視為分類變量,也可以提供要編碼的變量名稱。
import pandas as pd
car_types = pd.DataFrame({"car_type": ["BMW", "Tesla", "Audi", "BMW", "Audi"]})
print(car_types)
car_types_encoded = pd.get_dummies(car_types)
print(car_types_encoded)
car_type
0 BMW
1 Tesla
2 Audi
3 BMW
4 Audi
car_type_Audi car_type_BMW car_type_Tesla
0 0 1 0
1 0 0 1
2 1 0 0
3 0 1 0
4 1 0 0
1.3 虛擬變量陷阱
獨熱編碼會引入K個新特征,分別表示分類變量的K個類別。但如果我們使用回歸模型,則不能這么做,因為這會導致多重共線性。
首先我們要理解兩個新的概念:虛擬變量陷阱和多重共線性。
虛擬變量陷阱:在回歸模型中,虛擬變量(dummy variable)用于表示分類變量的類別,通常用1和0表示。例如性別變量'gender'有兩個類別,分別是男性和女性,那么可以引入一個虛擬變量D,如果觀測值是男性記為1,否則記為0。如果分類變量有$k$個類別,引入$(k-1)$個虛擬變量,有一個類別作為基準組/參照組。如果引入$k$個虛擬變量,會導致多重共線性。
多重共線性:如果1個自變量可以表示為其它自變量的線性組合,就是完全多重共線性,無法估計回歸方程的斜率系數(shù)。簡單理解就是預測變量(特征)之間高度相關。
假設變量$X$有3個類別,引入3個虛擬變量$X_a, X_b, X_c$,每個變量的取值都是1或0,則必然滿足以下關系:$X_a + X_b + X_c = 1$,那么任何一個變量都可以表示為其余兩個虛擬變量的線性組合,結(jié)果就是完全多重共線性。
使用OneHotEncoder創(chuàng)建(k-1)個虛擬變量。
car_types = np.array(["BMW", "Tesla", "Audi", "BMW", "Audi"])
# 將第一個類別作為參照組
oe = OneHotEncoder(drop="first")
# 擬合數(shù)據(jù)
oe.fit(car_types.reshape(-1, 1))
# 編碼
encoded_labels = oe.transform(car_types.reshape(-1, 1)).toarray()
# 查看剔除的特征
# oe.categories_保存了所有的類別,包括剔除的類別
# oe.drop_idx_保存了categories_中被剔除類別的索引
features_drop = oe.categories_[0][oe.drop_idx_.astype(int)]
features_retain = np.delete(oe.categories_[0], oe.drop_idx_.astype(int))
print("features drop: ", features_drop)
print("features retain: ", features_retain)
# 查看結(jié)果
encoded_labels_df = pd.DataFrame(encoded_labels, columns=features_retain)
encoded_labels_df["class"] = car_types
print(encoded_labels_df)
features drop: ['Audi']
features retain: ['BMW' 'Tesla']
BMW Tesla class
0 1.0 0.0BMW
1 0.0 1.0 Tesla
2 0.0 0.0 Audi
3 1.0 0.0 BMW
4 0.0 0.0 Audi
使用pd.get_dummies創(chuàng)建(k-1)個虛擬變量。
car_types = pd.DataFrame({"car_type": ["BMW", "Tesla", "Audi", "BMW", "Audi"]})
# drop_first=True: 將第一個類別作為參照組
car_types_encode = pd.get_dummies(car_types, drop_first=True)
# 查看結(jié)果
car_types_join = pd.concat([car_types, car_types_encode], axis=1)
print(car_types_join)
car_type car_type_BMW car_type_Tesla
0 BMW 1 0
1 Tesla 0 1
2 Audi 0 0
3 BMW 1 0
4 Audi 0 0
2. 文本數(shù)據(jù)
有時候模型的輸入是文本數(shù)據(jù),例如新聞,社交媒體發(fā)言等,需要把文本轉(zhuǎn)化為數(shù)值矩陣。
常用處理方法有兩種:單詞統(tǒng)計(word counts): 統(tǒng)計每個單詞出現(xiàn)的次數(shù)。
TF-IDF(Term Frequency-Inverse Document Frequency): 統(tǒng)計單詞出現(xiàn)的“頻率”。
單詞統(tǒng)計法的缺陷是當單詞出現(xiàn)次數(shù)較多,模型會賦予更多的權重,Tfidf可以規(guī)避這個缺陷。
2.1 word counts
行代表觀測值,列(特征)是所有文檔中出現(xiàn)過的單詞,特征值表示單詞在當前文檔中出現(xiàn)的次數(shù)。
from sklearn.feature_extraction.text import CountVectorizer
import pandas as pd
# 準備3個觀測值,文本變量
sample = ['problem of evil',
'evil queen',
'horizon problem']
# 創(chuàng)建Vectorizer對象,調(diào)用fit_transform方法,返回稀疏矩陣(sparse matrix)
vec = CountVectorizer()
X = vec.fit_transform(sample)
# 將結(jié)果轉(zhuǎn)化為數(shù)據(jù)框,以更直觀的方式顯示結(jié)果
df = pd.DataFrame(X.toarray(), columns=vec.get_feature_names())
df["text"] = sample
df
2.2 Tfidf
行代表觀測值,列(特征)是所有文檔出現(xiàn)過的單詞,分數(shù)是文檔中詞的頻率乘以所有文檔的逆頻率,分數(shù)越高顯示單詞在當前文檔中使用越多,而在其它文檔中使用得越少。
from sklearn.feature_extraction.text import TfidfVectorizer
vec = TfidfVectorizer()
X = vec.fit_transform(sample)
df = pd.DataFrame(X.toarray(), columns=vec.get_feature_names())
df["text"] = sample
df
數(shù)據(jù)黑客 - 專注金融大數(shù)據(jù)的內(nèi)容聚合和數(shù)據(jù)聚合平臺?finquanthub.com
我們聚合全網(wǎng)最優(yōu)秀的資訊和教程:金融大數(shù)據(jù)
機器學習/深度學習
量化交易
數(shù)據(jù)工程
編程語言,Python,R,Julia,Scala,SQL
我們提供開源數(shù)據(jù)接口:下載國內(nèi)和國外海量金融數(shù)據(jù)
API接口,將數(shù)據(jù)整合到您的平臺
總結(jié)
以上是生活随笔為你收集整理的python非数值型数据_Python机器学习实战:如何处理非数值特征的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vivos1pro上市时间
- 下一篇: python 过滤相似图片_求教 pyt