機器學習——數據清洗和特征選擇


一、缺省值填充

  1.  老版本用Imputer

import numpy as np
from sklearn.preprocessing import Imputer

X = [
    [2, 2, 4, 1],
    [np.nan, 3, 4, 4],
    [1, 1, 1, np.nan],
    [2, 2, np.nan, 3]
]

# missing_values(缺失值),strategy(策略,默認平均值),axis(選擇行列,0為列,1為行)
imp1 = Imputer(missing_values='NaN', strategy='mean', axis=0) # 缺省值選擇空,策略為平均數,
imp2 = Imputer(missing_values='NaN', strategy='mean', axis=1) 
print(imp1.fit_transform(X)) 
print(imp2.fit_transform(X))
[[2.         2. 4. 1. ] 
[1.66666667 3. 4. 4. ]
[1. 1. 1. 2.66666667]
[2. 2. 3. 3. ]]
[[2. 2. 4. 1. ]
[3.66666667 3. 4. 4. ]
[1. 1. 1. 1. ]
[2. 2. 2.33333333 3. ]]

  2. 新版本用  SimpleImputer

 1 import numpy as np
 2 from sklearn.preprocessing import Imputer
 3 from sklearn.impute import SimpleImputer
 4 
 5 X = [
 6     [2, 2, 4, 1],
 7     [np.nan, 3, 4, 4],
 8     [1, 1, 1, np.nan],
 9     [2, 2, np.nan, 3]
10 ]
11 # 參數詳解可見,暫未發現選擇行操作
12 # http://scikit-learn.org/dev/modules/generated/sklearn.impute.SimpleImputer.html
13 imp1 = SimpleImputer(missing_values='NaN', strategy='mean')
14 print(imp1.fit_transform(X))

  [[2. 2. 4. 1. ]
   [1.66666667 3. 4. 4. ]
   [1. 1. 1. 2.66666667]
   [2. 2. 3. 3. ]]

二、編碼

  1.  啞編碼(獨熱編碼)

# 獨熱編碼
import numpy as np
from sklearn.preprocessing import OneHotEncoder
from sklearn.feature_extraction import DictVectorizer,FeatureHasher

enc = OneHotEncoder()
enc.fit([[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]])
a=np.array([[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]])
print(a)
# 基於列進行編碼,打印有多少種值
print(enc.n_values_)

# 把0放到第一列[0,1]比對,把1放到第二列[0,1,2]比對,把3放到第三列[0,1,2,3]比對
print(enc.transform([[0, 1, 3]]).toarray())
[[0 0 3]
 [1 1 0]
 [0 2 1]
 [1 0 2]]
[2 3 4]

[[1. 0. 0. 1. 0. 0. 0. 0. 1.]]

  2.  標簽編碼

# 標簽編碼
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
le.fit_transform([1,5,6,100,67])

print('編碼結果是:', le.transform([1,1,100,67,5]))

print(le.fit(["paris", "paris", "tokyo", "amsterdam"]))
print(list(le.classes_))
print(le.transform(["tokyo", "tokyo", "paris"]))
print(list(le.inverse_transform([2, 2, 1])))   # 逆過程
編碼結果是: [0 0 4 3 1]
LabelEncoder()
['amsterdam', 'paris', 'tokyo']
[2 2 1]
['tokyo', 'tokyo', 'paris']

  3.  將特征值映射列表轉換為向量

from sklearn.feature_extraction import DictVectorizer
dv = DictVectorizer(sparse=False)
D = [{'foo':1, 'bar':2}, {'foa':3, 'baz': 2}]
X = dv.fit_transform(D)
print (X)
print (dv.get_feature_names())
print (dv.transform({'foo':4, 'unseen':3,'baz':10}))
[[2. 0. 0. 1.] [0. 2. 3. 0.]] ['bar', 'baz', 'foa', 'foo'] [[ 0. 10. 0. 4.]]

  4.  hash轉換

from sklearn.feature_extraction import FeatureHasher
h = FeatureHasher(n_features=10,non_negative=True)  # n_features:多少個特征,non_negative:是不是正數
D = [{'dog': 1, 'cat':2, 'elephant':4},{'dog': 2, 'run': 5}]
f = h.fit_transform(D)
print(f.toarray())
[[0. 0. 4. 1. 0. 0. 0. 0. 0. 2.]
 [0. 0. 0. 2. 5. 0. 0. 0. 0. 0.]]

三、二值化

import numpy as np
from sklearn.preprocessing import Binarizer
arr = np.array([
    [1.5, 1.3, 1.9],
    [0.5, 0.5, 1.6],
    [1.1, 2.1, 0.2]
])
binarizer = Binarizer(threshold=1.0).fit_transform(arr)
print(binarizer)
[[1. 1. 1.]
 [0. 0. 1.]
 [1. 1. 0.]]

四、標准化

'''作用:去均值和方差歸一化。且是針對每一個特征維度來做的,而不是針對樣本。 【注:】 並不是所有的標准化都能給estimator帶來好處。 
(x-x.mean())/x.std()
本方法要求原始數據的分布可以近似為高斯分布,否則歸一化的效果會變得很糟糕;
應用場景:在分類、聚類算法中,需要使用距離來度量相似性的時候、或者使用PCA技術進行降維的時候'''
from sklearn.preprocessing import StandardScaler
import pandas as pd

X = [
    [1, 2, 3, 2],
    [7, 8, 9, 2.01],
    [4, 8, 2, 2.01],
    [9, 5, 2, 1.99],
    [7, 5, 3, 1.99],
    [1, 4, 9, 2]
]
ss = StandardScaler(with_mean=True, with_std=True)
ss.fit(X)
print(ss.mean_)
print(ss.n_samples_seen_)
print(ss.scale_)
print(ss.transform(X))

y = pd.DataFrame(X)
z = y.apply(lambda x:(x - x.mean())/x.std())
print(z)

w = y.apply(lambda x:(x - x.mean())/x.std(ddof=0)) #  修正因子,做標准差是padas默認無偏差估計
print(w)

[4.83333333 5.33333333 4.66666667 2. ]
6
[3.07769755 2.13437475 3.09120617 0.00816497]
[[-1.24551983 -1.56173762 -0.53916387 0. ]
[ 0.70398947 1.2493901 1.40182605 1.22474487]
[-0.27076518 1.2493901 -0.86266219 1.22474487]
[ 1.3538259 -0.15617376 -0.86266219 -1.22474487]
[ 0.70398947 -0.15617376 -0.53916387 -1.22474487]
[-1.24551983 -0.62469505 1.40182605 0. ]]
0 1 2 3
0 -1.136999 -1.425665 -0.492187 0.000000
1 0.642652 1.140532 1.279686 1.118034
2 -0.247174 1.140532 -0.787499 1.118034
3 1.235868 -0.142566 -0.787499 -1.118034
4 0.642652 -0.142566 -0.492187 -1.118034
5 -1.136999 -0.570266 1.279686 0.000000
0 1 2 3
0 -1.245520 -1.561738 -0.539164 0.000000
1 0.703989 1.249390 1.401826 1.224745
2 -0.270765 1.249390 -0.862662 1.224745
3 1.353826 -0.156174 -0.862662 -1.224745
4 0.703989 -0.156174 -0.539164 -1.224745
5 -1.245520 -0.624695 1.401826 0.000000

五、區間縮放

  適用比較適用在數值比較集中的情況

  缺陷:如果max和min不穩定,很容易使得歸一化結果不穩定,使得后續使用效果也不穩定。實際使用中可以用經驗常量來替代max和min。

  應用場景:在不涉及距離度量、協方差計算、數據不符合正太分布的時候,可以使用第一種方法或其他歸一化方法(不包括Z-score方法)。比如圖像處理中,將RGB圖像轉換為灰度圖像后將其值限定在[0 255]的范圍

# 區間縮放
import numpy as np
from sklearn.preprocessing import MinMaxScaler
X = np.array([
    [1, -1, 2, 3],
    [2, 0, 0, 3],
    [0, 1, -1, 3]
], dtype=np.float64)
scaler = MinMaxScaler(feature_range=(1, 3))  # 指定區間范圍
print(scaler.fit_transform(X))
print(scaler.data_max_)
print(scaler.data_min_)
print(scaler.data_range_)

# 計算公式
X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
print(X_std)
#X_scaled = X_std * (max - min) + min
X_scaled = X_std * (5 - 1) + 1
print(X_scaled)
X_scaled[np.isnan(X_scaled)]=1.
print(X_scaled)

[[2. 1. 3. 1. ]
[3. 2. 1.66666667 1. ]
[1. 3. 1. 1. ]]
[2. 1. 2. 3.]
[ 0. -1. -1. 3.]
[2. 2. 3. 0.]

[  [0.5        0.         1.                nan]

  [1.         0.5        0.33333333        nan]

  [0. 1. 0. nan]]
[  [3. 1. 5. nan]
  [5. 3. 2.33333333 nan]
  [1. 5. 1. nan]]
[  [3. 1. 5. 1. ]
  [5. 3. 2.33333333 1. ]
  [1. 5. 1. 1. ]]

六、歸一化

import numpy as np
from sklearn.preprocessing import Normalizer

X = np.array([
    [1, -1, 2],
    [2, 0, 0],
    [0, 1, -1]
], dtype=np.float64)
normalizer1 = Normalizer(norm='max')  # 每個值除以最大值
normalizer2 = Normalizer(norm='l2')   # 每個值l2正則
normalizer3 = Normalizer(norm='l1')   # 每個值l1正則
normalizer1.fit(X)
normalizer2.fit(X)
normalizer3.fit(X)
print (normalizer1.transform(X))
print ("----------------------------------")
print (normalizer2.transform(X))
print ("----------------------------------")
print (normalizer3.transform(X))

print(1/np.sqrt(6))
print(1/np.sqrt((X[0]**2).sum()))  # 對應原始除以對應正則因子,1/np.sqrt((X[0]**2.sum()))

[[ 0.5 -0.5 1. ]
[ 1. 0. 0. ]
[ 0. 1. -1. ]]
----------------------------------
[[ 0.40824829 -0.40824829 0.81649658]
[ 1. 0. 0. ]
[ 0. 0.70710678 -0.70710678]]
----------------------------------
[[ 0.25 -0.25 0.5 ]
[ 1. 0. 0. ]
[ 0. 0.5 -0.5 ]]
0.4082482904638631
0.4082482904638631

七、多項式轉換

import numpy as np
from sklearn.preprocessing import PolynomialFeatures
X = np.arange(6).reshape(3,2)
print(X)

poly1 = PolynomialFeatures(2)  # 2表示2次方,(x_1 + x_2)^2
poly1.fit(X)
print(poly1)
print(poly1.transform(X)) #X 的特征已經從 (X_1, X_2) 轉換為 (1, X_1, X_2, X_1^2, X_1X_2, X_2^2)

poly2 = PolynomialFeatures(interaction_only=True)  # 去掉平方項
poly2.fit(X)
print(poly2)
print(poly2.transform(X))  #X 的特征已經從 (X_1, X_2) 轉換為 (1, X_1, X_2,X_1X_2)

poly3 = PolynomialFeatures(include_bias=False)  # 去掉截距項,即第一列
poly3.fit(X)
print(poly3)
print(poly3.transform(X))

[[0 1]
[2 3]
[4 5]]
PolynomialFeatures(degree=2, include_bias=True, interaction_only=False)
[[ 1. 0. 1. 0. 0. 1.]
[ 1. 2. 3. 4. 6. 9.]
[ 1. 4. 5. 16. 20. 25.]]
PolynomialFeatures(degree=2, include_bias=True, interaction_only=True)
[[ 1. 0. 1. 0.]
[ 1. 2. 3. 6.]
[ 1. 4. 5. 20.]]
PolynomialFeatures(degree=2, include_bias=False, interaction_only=False)
[[ 0. 1. 0. 0. 1.]
[ 2. 3. 4. 6. 9.]
[ 4. 5. 16. 20. 25.]]

 八、特征選擇

import numpy as np
from sklearn.feature_selection import VarianceThreshold,SelectKBest  # VarianceThreshold:異常方差較低的特征,SelectKBest:選擇最好的特征
from sklearn.feature_selection import chi2  # 卡方驗證

X = np.array([
    [0, 2, 0, 3],
    [0, 1, 4, 3],
    [0.1, 1, 1, 3]
], dtype=np.float64)
Y = np.array([1,2,1])
print(X.std(axis=0))

variance = VarianceThreshold(threshold=0.1) ##設置方差的閾值為0.1
print(variance)
variance.fit(X)
print(variance.transform(X)) #選擇方差大於0.1的特征

sk2 = SelectKBest(chi2, k=2) #選擇相關性最高的前2個特征
sk2.fit(X, Y)
print(sk2)
print(sk2.scores_)
print(sk2.transform(X))

[0.04714045 0.47140452 1.69967317 0. ]
VarianceThreshold(threshold=0.1)
[[2. 0.]
[1. 4.]
[1. 1.]]
SelectKBest(k=2, score_func=<function chi2 at 0x000001775F143BF8>)
[0.05 0.125 4.9 0. ]
[[2. 0.]
[1. 4.]
[1. 1.]]

九、異常數據處理

import numpy as np
import matplotlib as mpl
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import BaggingRegressor

# 防止中文亂碼
mpl.rcParams['font.sans-serif'] = [u'simHei']
mpl.rcParams['axes.unicode_minus'] = False

# 設置在jupyter中matplotlib的顯示情況
# %matplotlib tk

## 文件存儲路徑
path1 = "C0904.csv"
path2 = "C0911.csv"
filename = "X12CO2"  # 列的名字

# subplots與figure函數參數解釋說明以及簡單的使用腳本實例
# https://blog.csdn.net/henni_719/article/details/77479912

### 原始數據讀取
plt.figure(figsize=(10, 6), facecolor='w')  # figsize:每英寸的寬度和高度,facecolor:背景色, 此處白色。如果不提供,默認值:figure.facecolor。
plt.subplot(121)  # 分成1x2(一行二列),占用第一個,即第一行第一列的子圖
data = pd.read_csv(path1, header=0)  # 讀取數據
x = data[filename].values  # 取X12CO2列的值

plt.plot(x, 'r-', lw=1, label=u'C0904')  # x:傳入y軸的值,r-:紅色,lw:線寬, label:線的標簽名
plt.title(u'實際數據0904', fontsize=18)  # 表格的標題,fontsize:字體大小
plt.legend(loc='upper right')  # loc:圖的位置,右上
plt.xlim(0, 80000)  # x坐標最大值和最小值
plt.grid(b=True)    #  是否顯示網格

plt.subplot(122)   # 分成1x2(一行二列),占用第二個,即第一行第二列的子圖
data = pd.read_csv(path2, header=0)
x = data[filename].values
plt.plot(x, 'r-', lw=1, label=u'C0911')
plt.title(u'實際數據0911', fontsize=18)
plt.legend(loc='upper right')
plt.xlim(0, 80000)
plt.grid(b=True)

plt.tight_layout(2, rect=(0, 0, 1, 0.95))  #2:圖邊和子圖邊的距離,rect: 將其設置為一個矩形,默認(0,0,1,1)
plt.suptitle(u'如何找到下圖中的異常值', fontsize=20)
plt.show()



### 異常數據處理
data = pd.read_csv(path2, header=0)
x = data[filename].values

width = 300
delta = 5
eps = 0.02
N = len(x)
p = []
# 異常值存儲
abnormal = []
for i in np.arange(0, N, delta):  # [0,5,10,...]
    s = x[i:i+width]
    ## 獲取max-min的差值
    min_s = np.min(s)
    ptp = np.ptp(s)  # 求最大值和最小值的差
    ptp_min = ptp / min_s
    p.append(ptp_min)
    ## 如果差值大於給定的閾值認為是存在異常值的區間
    if ptp_min > eps:
        abnormal.append(range(i, i+width))

## 獲得異常的數據x值
abnormal = np.array(abnormal)  # 將列表轉換為Arrray對象
abnormal = abnormal.flatten()  # 把數組降到一維
abnormal = np.unique(abnormal)  # 去重

#plt.plot(p, lw=1)
#plt.grid(b=True)
#plt.show()

plt.figure(figsize=(18, 7), facecolor='w')
plt.subplot(131)
plt.plot(x, 'r-', lw=1, label=u'原始數據')
plt.title(u'實際數據', fontsize=18)
plt.legend(loc='upper right')
plt.xlim(0, 80000)
plt.grid(b=True)

plt.subplot(132)
t = np.arange(N)  # X的長度
plt.plot(t, x, 'r-', lw=1, label=u'原始數據')  # t為x值的序列,x為y值的序列
plt.plot(abnormal, x[abnormal], 'go', markeredgecolor='g', ms=3, label=u'異常值')  # g:表示為綠色,go:綠色圓圈
plt.legend(loc='upper right')
plt.title(u'異常數據檢測', fontsize=18)
plt.xlim(0, 80000)
plt.grid(b=True)

# 預測
plt.subplot(133)
select = np.ones(N, dtype=np.bool)  # N是形狀
select[abnormal] = False
print(select)
t = np.arange(N)
## 決策樹
dtr = DecisionTreeRegressor(criterion='mse', max_depth=10)  # criterion是決策樹模型,max_depth是深度
br = BaggingRegressor(dtr, n_estimators=10, max_samples=0.3) # 把樹模型丟到 集成學習器中,n_estimators:10個弱學習器,max_samples: 每個弱學習器選擇30%的樣本訓練
## 模型訓練

#我們不知道t的shape屬性是多少,
#但是想讓t變成只有一列,行數不知道多少,
#通過`t.reshape(-1,1)`,Numpy自動計算出行數

br.fit(t[select].reshape(-1, 1), x[select])
## 模型預測得出結果
y = br.predict(np.arange(N).reshape(-1, 1))
y[select] = x[select]
plt.plot(x, 'g--', lw=1, label=u'原始值')    # 原始值
plt.plot(y, 'r-', lw=1, label=u'校正值')     # 校正值
plt.legend(loc='upper right')
plt.title(u'異常值校正', fontsize=18)
plt.xlim(0, 80000)
plt.grid(b=True)

plt.tight_layout(1.5, rect=(0, 0, 1, 0.95))
plt.suptitle(u'異常值檢測與校正', fontsize=22)
plt.show()

 十、車輛數據預處理

# 車輛數據預處理
import numpy as np
import matplotlib as mpl
import pandas as pd
from sklearn.preprocessing import OneHotEncoder

mpl.rcParams['font.sans-serif'] = [u'simHei']
mpl.rcParams['axes.unicode_minus'] = False

# 設置在jupyter中matplotlib的顯示情況
#%matplotlib tk

path = "car.data"
data = pd.read_csv(path, header=None)
#
# for i in range(7):
#     #print (i, np.unique(data[i]))
#     print(data[i])

### 原始數據
print(data.head(10))

### 字符串轉換為序列id(數字)
X = data.apply(lambda x: pd.Categorical(x).codes)
print(X.head(10))

### 進行啞編碼操作
enc = OneHotEncoder()
X = enc.fit_transform(X)
print(enc.n_values_)


### 轉換后數據
# print X.toarray()
print(pd.DataFrame(X.toarray()).head(5))

[4 4 4 3 3 3 4]

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM