終于把機(jī)器學(xué)習(xí)中的特征工程搞懂了?。?!
大家好,我是小寒
今天給大家分享一個(gè)機(jī)器學(xué)習(xí)中的關(guān)鍵概念,特征工程
特征工程是機(jī)器學(xué)習(xí)中的重要步驟之一,其目的是通過對(duì)原始數(shù)據(jù)進(jìn)行處理、變換或生成新的特征,以增強(qiáng)模型的學(xué)習(xí)能力和預(yù)測(cè)性能。
特征工程直接影響機(jī)器學(xué)習(xí)模型的表現(xiàn),因?yàn)槟P偷男Ч艽蟪潭壬先Q于輸入數(shù)據(jù)的質(zhì)量和特征的選擇。
下面,我們來分享10個(gè)常用的特征工程技術(shù)。
1.插補(bǔ)
插補(bǔ)是處理數(shù)據(jù)集中的缺失值的一種常用方法。
大多數(shù)機(jī)器學(xué)習(xí)算法無法直接處理缺失值,因此在特征工程中必須解決這個(gè)問題。
插補(bǔ)方法根據(jù)已有的數(shù)據(jù)推測(cè)或生成合理的替代值,以填補(bǔ)缺失的數(shù)據(jù)。
常見插補(bǔ)方法:
- 均值插補(bǔ),將缺失值用該特征的均值替代,適用于數(shù)值型數(shù)據(jù)。
- 中位數(shù)插補(bǔ),用中位數(shù)替代缺失值,適用于具有異常值的數(shù)值數(shù)據(jù),因?yàn)橹形粩?shù)對(duì)極端值不敏感。
- 眾數(shù)插補(bǔ),對(duì)于類別型數(shù)據(jù),使用該特征的眾數(shù)(最常出現(xiàn)的值)進(jìn)行插補(bǔ)。
- K近鄰插補(bǔ),基于 K 最近鄰算法,用與缺失值最近的 K 個(gè)相似樣本的平均值進(jìn)行插補(bǔ)。
- 插值,對(duì)時(shí)間序列或連續(xù)數(shù)據(jù),可以使用線性插值或多項(xiàng)式插值方法進(jìn)行插補(bǔ)。
優(yōu)缺點(diǎn)
- 插補(bǔ)可以讓數(shù)據(jù)集保持完整,但如果插補(bǔ)策略不當(dāng),可能會(huì)引入偏差或噪聲,影響模型的性能。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import gensim.downloader as api
from gensim.models import Word2Vec
from sklearn.pipeline import Pipeline
from sklearn.decomposition import PCA
from sklearn.datasets import load_iris
from sklearn.impute import SimpleImputer
from sklearn.compose import ColumnTransformer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.preprocessing import MinMaxScaler, StandardScaler
data = pd.DataFrame({
'doors': [2, np.nan, 2, np.nan, 4],
'topspeed': [100, np.nan, 150, 200, np.nan],
'model': ['Daihatsu', 'Toyota', 'Suzuki', 'BYD','Wuling']
})
doors_imputer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='constant', fill_value=0))
])
topspeed_imputer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median'))
])
pipeline = ColumnTransformer(
transformers=[
('doors_imputer', doors_imputer, ['doors']),
('topspeed_imputer', topspeed_imputer, ['topspeed'])
],
remainder='passthrough'
)
transformed = pipeline.fit_transform(data)
transformed_df = pd.DataFrame(transformed, columns=['doors', 'topspeed', 'model'])
圖片
2.分箱
分箱是將連續(xù)型數(shù)值特征離散化的過程,通過將數(shù)值范圍劃分為多個(gè)區(qū)間或“箱”,將原始數(shù)值轉(zhuǎn)換為離散的類別。
常見的分箱方法
- 等寬分箱,將數(shù)值區(qū)間按等寬度分成若干個(gè)區(qū)間,適合均勻分布的數(shù)據(jù)。
- 等頻分箱,將數(shù)值按頻數(shù)分箱,每個(gè)箱中的樣本數(shù)大致相同,適用于不均勻分布的數(shù)據(jù)。
- 自定義分箱,根據(jù)業(yè)務(wù)邏輯或數(shù)據(jù)特點(diǎn),自定義分箱的邊界。
應(yīng)用場(chǎng)景
- 在信用評(píng)分等領(lǐng)域,通過分箱處理連續(xù)型變量,可以減少數(shù)據(jù)的噪聲,增加模型的穩(wěn)健性。
np.random.seed(42)
data = pd.DataFrame({'age' : np.random.randint(0, 100, 100)})
data['category'] = pd.cut(data['age'], [0, 2, 11, 18, 65, 101], labels = ['infants', 'children', 'teenagers', 'adults', 'elders'])
print(data)
print(data['category'].value_counts())
data['category'].value_counts().plot(kind='bar')
圖片
3.對(duì)數(shù)變換
對(duì)數(shù)變換是一種數(shù)值轉(zhuǎn)換方法,用于處理數(shù)據(jù)中呈現(xiàn)偏態(tài)分布的特征,將其轉(zhuǎn)換為更接近正態(tài)分布的數(shù)據(jù)形式。
對(duì)數(shù)變換可以減小大值的影響,壓縮特征的數(shù)值范圍。
應(yīng)用場(chǎng)景
- 處理右偏分布的特征,如收入、價(jià)格等數(shù)據(jù)。
- 適用于減少數(shù)據(jù)中極大值的影響,避免模型對(duì)大值的過度關(guān)注。
rskew_data = np.random.exponential(scale=2, size=100)
log_data = np.log(rskew_data)
plt.title('Right Skewed Data')
plt.hist(rskew_data, bins=10)
plt.show()
plt.title('Log Transformed Data')
plt.hist(log_data, bins=20)
plt.show()
圖片
4.縮放
縮放是將特征的數(shù)值范圍轉(zhuǎn)換到某一固定區(qū)間內(nèi)的過程。
常見的縮放方法
- 標(biāo)準(zhǔn)化
將特征值縮放為均值為 0,標(biāo)準(zhǔn)差為1的標(biāo)準(zhǔn)正態(tài)分布。
公式為:
其中, 是均值, 是標(biāo)準(zhǔn)差。 - 歸一化
將特征縮放到 [0, 1] 范圍內(nèi)。
公式為:
應(yīng)用場(chǎng)景
- 縮放對(duì)于基于距離的算法(如KNN、SVM)和梯度下降優(yōu)化的算法特別重要,因?yàn)樘卣髦档某叨葧?huì)影響模型的性能。
data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).reshape(-1, 1)
scaler = MinMaxScaler()
minmax = scaler.fit_transform(data)
scaler = StandardScaler()
standard = scaler.fit_transform(data)
df = pd.DataFrame({'original':data.flatten(),'Min-Max Scaling':minmax.flatten(),'Standard Scaling':standard.flatten()})
df
圖片
5.獨(dú)熱編碼
獨(dú)熱編碼是一種將類別型變量轉(zhuǎn)換為二進(jìn)制特征的編碼方式。
每個(gè)類別值被轉(zhuǎn)換為一個(gè)獨(dú)立的二進(jìn)制特征,這些特征值為0或1,表示該樣本是否屬于對(duì)應(yīng)的類別。
舉例
對(duì)于類別型特征 “顏色” = {紅,藍(lán),綠},獨(dú)熱編碼會(huì)將其轉(zhuǎn)換為三個(gè)新特征
- 紅:1, 0, 0
- 藍(lán):0, 1, 0
- 綠:0, 0, 1
應(yīng)用場(chǎng)景
- 獨(dú)熱編碼適用于無序的類別型數(shù)據(jù),如國家、城市、產(chǎn)品種類等。
- 適用于不具備自然排序關(guān)系的特征。
優(yōu)缺點(diǎn)
- 優(yōu)點(diǎn):可以避免類別之間的錯(cuò)誤關(guān)系,適合沒有順序的分類變量。
- 缺點(diǎn):當(dāng)類別數(shù)過多時(shí),會(huì)導(dǎo)致維度爆炸
data = pd.DataFrame({'models':['toyota','ferrari','byd','lamborghini','honda','tesla'],
'speed':['slow','fast','medium','fast','slow','medium']})
data = pd.concat([data, pd.get_dummies(data['speed'], prefix='speed')],axis=1)
data
圖片
6.目標(biāo)編碼
目標(biāo)編碼是一種處理類別型變量的編碼方式,通過用該類別與目標(biāo)變量的統(tǒng)計(jì)信息(如均值、概率)來替代類別值。
通常用于高基數(shù)的類別變量,避免獨(dú)熱編碼導(dǎo)致維度過高的問題。
舉例
假設(shè)目標(biāo)是二分類問題,對(duì)于類別型特征“城市”,可以用每個(gè)城市對(duì)應(yīng)的目標(biāo)變量均值來替換原始的類別值。
例如,城市A的目標(biāo)變量均值為0.7,城市B的均值為0.3,城市C的均值為0.5。
應(yīng)用場(chǎng)景
- 適用于高基數(shù)類別型變量(如用戶ID、產(chǎn)品ID等),特別是在類別與目標(biāo)變量有顯著關(guān)系時(shí)。
注意事項(xiàng)
- 為了避免數(shù)據(jù)泄露(即使用目標(biāo)值信息),需要對(duì)訓(xùn)練集和測(cè)試集分別進(jìn)行編碼,或者使用交叉驗(yàn)證技術(shù)。
fruits = ['banana','apple','durian','durian','apple','banana']
price = [120,100,110,150,140,160]
data = pd.DataFrame({
'fruit': fruits,
'price': price
})
data['encoded_fruits'] = data.groupby('fruit')['price'].transform('mean')
data
圖片
7.主成分分析
PCA 是一種線性降維方法,通過將高維數(shù)據(jù)投影到一個(gè)低維空間,同時(shí)盡量保留原始數(shù)據(jù)的方差信息。
PCA 通過計(jì)算數(shù)據(jù)的協(xié)方差矩陣,找到數(shù)據(jù)的主成分(特征向量),然后選擇前幾個(gè)主成分作為新的特征。
步驟
- 標(biāo)準(zhǔn)化數(shù)據(jù)。
- 計(jì)算協(xié)方差矩陣。
- 計(jì)算協(xié)方差矩陣的特征值和特征向量。
- 根據(jù)特征值大小選擇前K個(gè)特征向量作為主成分。
- 將原始數(shù)據(jù)投影到新的主成分上。
應(yīng)用場(chǎng)景
- PCA常用于高維數(shù)據(jù)集的降維,如圖像、基因數(shù)據(jù),目的是減少特征數(shù)量,降低計(jì)算復(fù)雜度,同時(shí)保留最重要的信息。
iris_data = load_iris()
features = iris_data.data
targets = iris_data.target
pca = PCA(n_compnotallow=2)
pca_features = pca.fit_transform(features)
for point in set(targets):
plt.scatter(pca_features[targets == point, 0], pca_features[targets == point,1], label=iris_data.target_names[point])
plt.xlabel('PCA Component 1')
plt.ylabel('PCA Component 2')
plt.title('PCA on Iris Dataset')
plt.legend()
plt.show()
圖片
8.特征聚合
特征聚合是一種通過聚合現(xiàn)有特征來生成新特征的技術(shù)。
聚合可以通過多種方式實(shí)現(xiàn),如計(jì)算平均值、總和、最大值、最小值等。
特征聚合特別適合處理時(shí)間序列數(shù)據(jù)或分組數(shù)據(jù)。
應(yīng)用場(chǎng)景
- 在時(shí)間序列數(shù)據(jù)中,可以對(duì)某一特征在多個(gè)時(shí)間窗口上計(jì)算統(tǒng)計(jì)量,如移動(dòng)平均、累計(jì)總和等。
- 在分組數(shù)據(jù)中,可以對(duì)每個(gè)用戶的購買記錄進(jìn)行聚合,生成新的特征(如總購買金額、平均購買頻率等)。
quarter = ['Q1','Q2','Q3','Q4']
car_sales = [10000,9850,13000,20000]
motorbike_sales = [14000,18000,9000,11000]
sparepart_sales = [5000, 7000,3000, 10000]
data = pd.DataFrame({'car':car_sales,
'motorbike':motorbike_sales,
'sparepart':sparepart_sales}, index=quarter)
data['avg_sales'] = data[['car','motorbike','sparepart']].mean(axis=1).astype(int)
data['total_sales'] = data[['car','motorbike','sparepart']].sum(axis=1).astype(int)
data
圖片
9.TF-IDF
TF-IDF 是一種衡量文本中詞匯重要性的特征工程技術(shù),廣泛應(yīng)用于自然語言處理(NLP)任務(wù)。
它通過計(jì)算詞頻(TF)和逆文檔頻率(IDF)來評(píng)估某個(gè)詞在文本中的重要性:
- 詞頻(TF),某個(gè)詞在文檔中出現(xiàn)的頻率。
- 逆文檔頻率(IDF),表示詞在所有文檔中出現(xiàn)的稀有程度,常見詞會(huì)被削弱。
TF-IDF 公式:
其中 N 是文檔總數(shù), 是詞 t 出現(xiàn)在多少個(gè)文檔中的次數(shù)。
texts = ["I eat rice with eggs.",
"I also love to eat fried rice. Rice is the most delicious food in the world"]
vectorizer = TfidfVectorizer()
tfidfmatrix = vectorizer.fit_transform(texts)
features = vectorizer.get_feature_names_out()
data = pd.DataFrame(tfidfmatrix.toarray(), columns=features)
print("TF-IDF matrix")
data
圖片
10.文本嵌入
文本嵌入是將文本數(shù)據(jù)轉(zhuǎn)化為數(shù)值向量的技術(shù),目的是將語義信息保留在低維向量空間中,使其能夠被機(jī)器學(xué)習(xí)模型處理。
常見的文本嵌入方法有:
- Word2Vec,將詞映射為向量,類似語義的詞會(huì)在向量空間中更接近。
- GloVe,基于共現(xiàn)矩陣生成詞向量,保持詞語之間的全局關(guān)系。
- BERT,上下文感知的詞向量模型,能夠捕捉詞在不同上下文中的含義。
文本嵌入可以捕捉文本中的語義信息,使模型能夠理解文本間的關(guān)系。
corpus = api.load('text8')
model = Word2Vec(corpus)
dog = model.wv['dog']
print("Embedding vector for 'dog':\n", dog)
圖片