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