1. 程式人生 > >python資料預處理之缺失值簡單處理,特徵選擇

python資料預處理之缺失值簡單處理,特徵選擇

我們在進行模型訓練時,不可避免的會遇到某些特徵出現空值的情況,下面整理了幾種填充空值的方法

1. 用固定值填充

對於特徵值缺失的一種常見的方法就是可以用固定值來填充,例如0,9999, -9999, 例如下面對灰度分這個特徵缺失值全部填充為-99

data['灰度分'] = data['灰度分'].fillna('-99')

2. 用均值填充

對於數值型的特徵,其缺失值也可以用未缺失資料的均值填充,下面對灰度分這個特徵缺失值進行均值填充

data['灰度分'] = data['灰度分'].fillna(data['灰度分'].mean()))

3. 用眾數填充

與均值類似,可以用未缺失資料的眾數來填充缺失值

data['灰度分'] = data['灰度分'].fillna(data['灰度分'].mode()))

4. 用上下資料進行填充

用前一個數據進行填充

data['灰度分'] = data['灰度分'].fillna(method='pad')

用後一個數據進行填充

data['灰度分'] = data['灰度分'].fillna(method='bfill')

5. 用插值法填充

data['灰度分'] = data['灰度分'].interpolate()

6. 用KNN進行填充

from fancyimpute import BiScaler, KNN, NuclearNormMinimization, SoftImpute
dataset = KNN(k=3).complete(dataset)

書籍:《python machine learning》

推薦kaggel 上大神的資料預處理文章:

https://www.kaggle.com/pmarcelino/comprehensive-data-exploration-with-python

自己之前也學習過這篇文章對一些程式碼進行了註釋,博文如下:

https://blog.csdn.net/Amy_mm/article/details/79538083

本文是學習《python machine learning》第四章的學習記錄~~~

本文資料預處理原始碼git 地址:https://github.com/xuman-Amy/preprocessing

本文資料預處理主要步驟:

(1)刪除和估算缺失值 (removing and imputing missing values)

(2)獲取分類資料 (Getting  categorical data into shape for machine learning)

(3)為模型構建選擇相關特徵 (Selecting relevant features for the module construction) 【建立CSV資料集】

    #build a csv dataset     import numpy as np     import pandas as pd     from io import StringIO     import sys     #資料不要打空格,IO流會讀入空格     csv_data = \     '''A,B,C,D     1.0,2.0,3.0,4.0     5.0,6.0,,8.0     10.0,11.0,12.0,     '''     df = pd.read_csv(StringIO(csv_data))

如圖,有兩個空值~ 【統計空值情況】

    #using isnull() function to check NaN value     df.isnull().sum()

【訪問陣列元素】

在放入sklearn的預估器之前,可以通過value屬性訪問numpy陣列的底層資料

【消除缺失值 dropna() 函式】

一個最簡單的處理缺失值的方法就是直接刪掉相關的特徵值(一列資料)或者相關的樣本(一行資料)。

利用dropna()函式實現。

dropna( axis = 0 /1 )引數axis表示軸選擇,axis=0 代表行,axis=1 代表列。

df.dropna(axis = 1)

df.dropna(axis = 0)

dropna( how = all) how引數選擇刪除行列資料(any / all)

df.dropna(how = 'all')

dropna(thresh = int) 刪除值少於int個數的值

df.dropna(thresh = 4)

dropna( subset = [' '])  刪除指定列中有空值的一行資料(整個樣本)

df.dropna(subset = ['C'])

刪除C列中有空值的那一行資料

雖然直接刪除很是簡單啦~但是天下沒有免費的午餐,直接刪除會帶來很多弊端。比如樣本值刪除太多導致不能進行可靠預測;或者特徵值刪除太多(列資料),可能失去很多有價值的資訊。

所以下面介紹一個更為通用的缺失值處理技巧——插值技術。我們可以根據樣本集中的其他資料,運用不同的插值技術,來估計 樣本的缺失值。 【插值】interpolation techniques 【imputing missing values】

比較常用的一種估值是平均值估計(mean imputation)。可以直接使用sklearn庫中的imputer類實現。

class sklearn.preprocessing .Imputer

(missing_values = 'NaN', strategy = 'mean', axis = 0, verbose = 0, copy = True)

參考:http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.Imputer.html

引數說明:

missing_values : int或者'NaN',預設NaN(string型別)

strategy:預設mean。平均值填補。

可選項: mean(平均值)

              median(中位數)

              most_frequent(眾數)

axis: 指定軸向。axis= 0,列向(預設);axis= 1,行向。

verbose : int 預設值為0

copy:預設True,建立資料集的副本。

          False:在任何合適的地方都可能進行插值。

以下四種情況,即使copy設為False,也會進行建立副本:

                    1. X不是浮點型陣列

                    2.X是稀疏矩陣,且missing_values= 0

                    3.axis=0,X被編碼為CSR矩陣(Compressed Sparse Row 行壓縮)

                    4.axis=1,X被編碼為CSC矩陣(Copressed Sparse Column 列壓縮)

    #mean imputation     #axis = 0,表示列向,採用每一列的平均值填補空值           from sklearn.preprocessing import Imputer     imr = Imputer(missing_values = 'NaN', strategy = 'mean', axis = 0 )     imr = imr.fit(df.values)     imputed_data = imr.transform(df.values)     imputed_data

【處理分類資料】

handling categorical data

分類資料一般分為nominal(名詞性,不可排序)和ordinal(可排序資料)

 【建立分類資料集】

    #create categorical dataset     import pandas as pd     df = pd.DataFrame([         ['green', 'M', 10.1, 'class1'],         ['red', 'L', 13.5, 'class2'],         ['blue', 'XL', 15.3, 'class1']     ])     df.columns = ['color', 'size', 'price', 'classlabel']     df

nominal data : color

ordinal data : size

numerical data : price

 【對映可排序特徵】

為確保學習演算法能夠正確識別可排序特徵值,需要將分類資料轉換為數值型資料。

    #converting categorical string values into integers     size_mapping = {         'XL': 3,         'L' : 2,         'M' : 1}     df['size'] = df['size'].map(size_mapping)     df

也可以反向映射回分類值

    #reverse mapping     inv_size_mapping = {         v : k for k ,v in size_mapping.items()     }     df['size'] = df['size'].map(inv_size_mapping)     df

【編碼分類標籤】

Encoding class label

    import numpy as n     class_mapping = {label : idx for idx, label in enumerate(np.unique(df['classlabel']))}     class_mapping

利用上述class_mapping將classlabel轉換為integer

    df['classlabel'] = df['classlabel'].map(class_mapping)     df

同樣可以轉換回去

    inv_class_mapping = {v : k for k, v in class_mapping.items()}     df['classlabel'] = df['classlabel'].map(inv_class_mapping)     df

也可以直接呼叫sklearn庫中的LabelEncoder 類進行類標籤轉換

    #直接採用sklearn庫中的LabelEncoder進行編碼     from sklearn.preprocessing import LabelEncoder     class_le = LabelEncoder()     y = class_le.fit_transform(df['classlabel'].values)     y

利用inverse_transform轉換回去

class_le.inverse_transform(y)

【one-hot encoding for nominal features】

get_doommies()

使用one-hot編碼時,容易引起共線性問題,在使用其他演算法時容易出現bug,例如矩陣的求逆。

為避免這種問題,降低變數間的相關性,可以簡單的刪除one-hot編碼陣列中特徵值的第一列,這樣也不會丟失重要資訊。

例如刪除color_blue這一列,如果color_red=0,color_green=0,則可以判斷color_blue=1.

pd.get_dummies(df[['size','color','price']],drop_first = True)

刪除color_blue這一列,令drop_firt=True即可

    #為避免共線性問題,降低變數間的相關性,刪除one-hot陣列中特徵值的第一列     pd.get_dummies(df[['size','color','price']],drop_first = True)

【資料特徵選擇】

利用wine dataset 學習特徵選擇,以及L1,L2Z正則化資料。

【讀資料】

    # read wine dataset     df_wine = pd.read_csv("G:\Machine Learning\python machine learning\python machine learning code\code\ch04\wine.data")     df_wine.columns = ['Class label', 'Alcohol', 'Malic acid', 'Ash',                        'Alcalinity of ash', 'Magnesium', 'Total phenols',                        'Flavanoids', 'Nonflavanoid phenols', 'Proanthocyanins',                        'Color intensity', 'Hue', 'OD280/OD315 of diluted wines',                        'Proline']           print('Class labels', np.unique(df_wine['Class label']))     df_wine.head()

【劃分資料 ——訓練集和測試集】

    #seperate train and test data     from sklearn.model_selection import train_test_split     X,y = df_wine.iloc[:,1:].values,df_wine.iloc[:,0].values     X_train, X_test, y_train, y_test = \                     train_test_split(X,                                      y,                                      test_size = 0.3,                                      random_state = 0,                                      stratify = y)

【feature scaling】

特徵縮放在資料預處理中是及其重要的一步,除了決策樹和隨機森林中不需要特徵縮放,其餘大部分學習和優化演算法都需要特徵縮放,保證所有特徵在同一範圍內。

兩個進行特徵縮放的方法:normalization(規範化) and standardization(標準化)

Normalization:將資料重新規範到範圍[0,1]之間,是min-max縮放中的一種。

計算公式:

 sklearn.preprocessing.MinMaxScaler 實現

    #sklearn normalization     from sklearn.preprocessing import MinMaxScaler     mms = MinMaxScaler()     X_train_norm = mms.fit_transform(X_train)     X_test_norm = mms.transform(X_test)

Standardization:將資料標準化為均值為0 方差為1

計算公式:

sklearn.preprocessing. StandardScaler實現

    #sklearn standardization     from sklearn.preprocessing import StandardScaler     stdsc = StandardScaler()     X_train_std = stdsc.fit_transform(X_train)     X_test_std = stdsc.transform(X_test)

只需要在訓練集上使用fit函式,然後使用這些引數去標準化測試集或者其他新的資料集。這樣就可以使得所有標準化後的資料在同一scale上,是課相互比較的資料集。

【避免過擬合的方法】

(1)收集儘可能多的訓練資料

(2)通過正則化引入對於模型負責度的懲罰係數

(3)選擇引數較少的簡單模型

(4)降級資料維度

方法(1)一般不太可行

本文講述通過特徵選擇實現的正則化和降低緯度的方法使得模型簡單化。

【L1 L2正則化】

L1正則化通常會生成稀疏特徵向量,大部分特徵值為0。

如果資料集是高維度且有很多不相關的特徵值,尤其是當不相關的維度多於樣本時,L1是很好的選擇。

sklearn 實現L1 L2

    # sklearn實現L1     from sklearn.linear_model import LogisticRegression     lr = LogisticRegression(penalty = 'l1', C = 1.0)     lr.fit(X_train_std,y_train)     print('Training accuracy:', lr.score(X_train_std, y_train))

SBS(Sequential Backward Selection) 序列後向選擇

從特徵全集開始,每次從特徵集中刪除一個特徵x,使得刪除特徵x後評價函式值達到最優。

演算法:定義一個判別函式J,目的是是J最小化

(1)初始化 k=d,d是資料集的維數

(2)選擇使得判別函式最大的特徵,

(3)從特徵集中刪除特徵

(4)如果k達到了期望值,結束;否則返回(2)

    #SBS select features     from sklearn.base import clone     from itertools import combinations     import numpy as np     from sklearn.metrics import accuracy_score     from sklearn.model_selection import train_test_split     class SBS():         def __init__(self,                      estimator, #評估器 比如LR,KNN                      k_features, #想要的特徵個數                      scoring = accuracy_score,#對模型的預測評分                      test_size=0.25,                      random_state=1):                          self.scoring = scoring             self.estimator = clone(estimator)             self.k_features = k_features             self.test_size = test_size             self.random_state = random_state                      def fit(self, X, y):             #seperete train data and test data             X_train, X_test, y_train, y_test = train_test_split(X, y,                                                                 test_size = self.test_size,                                                                 random_state = self.random_state)             # dimension             dim = X_train.shape[1]             self.indices_ = tuple(range(dim))             self.subsets_ = [self.indices_] #特徵子集             score = self._calc_score(X_train, y_train, X_test, y_test, self.indices_)             self.scores_ = [score]                                       while dim > self.k_features:                 scores = [] #分數                 subsets = [] #子集                                  for p in combinations(self.indices_, r = dim - 1):                                          score = self._calc_score(X_train,                                              y_train,                                              X_test,                                              y_test,                                              p)                                          print(p, score)                                          scores.append(score)                     subsets.append(p)                                  best = np.argmax(scores)                 self.indices_ = subsets[best]                 self.subsets_.append(self.indices_)                 dim -= 1                                  self.scores_.append(scores[best])             self.k_score_ = self.scores_[-1]             return self                  def transform(self, X):             return X[:, self.indices_]               def _calc_score(self, X_train, y_train, X_test, y_test, indices):             self.estimator.fit(X_train[:, indices], y_train)             y_pred = self.estimator.predict(X_test[:, indices])             score = self.scoring(y_test, y_pred)             return score

    import matplotlib.pyplot as plt     from sklearn.neighbors import KNeighborsClassifier           knn = KNeighborsClassifier(n_neighbors=5)           # selecting features     sbs = SBS(knn, k_features=1)     sbs.fit(X_train_std, y_train)           # plotting performance of feature subsets     k_feat = [len(k) for k in sbs.subsets_]           plt.plot(k_feat, sbs.scores_, marker='o')     plt.ylim([0.7, 1.02])     plt.ylabel('Accuracy')     plt.xlabel('Number of features')     plt.grid()     plt.tight_layout()     # plt.savefig('images/04_08.png', dpi=300)     plt.show()

【隨機森林評估特徵值的重要性】

    #隨機森林選擇特徵值     from sklearn.ensemble import RandomForestClassifier           feat_labels = df_wine.columns[1:]     forest = RandomForestClassifier(n_estimators=500, random_state=1)           forest.fit(X_train, y_train)     #     importances = forest.feature_importances_           indices = np.argsort(importances)[::-1]           for f in range(X_train.shape[1]):         print("%2d) %-*s %f" % (f + 1, 30,                                 feat_labels[indices[f]],                                 importances[indices[f]]))           plt.title('Feature Importance')     plt.bar(range(X_train.shape[1]),             importances[indices],             align='center')           plt.xticks(range(X_train.shape[1]),                feat_labels[indices], rotation=90)     plt.xlim([-1, X_train.shape[1]])     plt.tight_layout()     plt.show()

【SelectFromModel 實現特徵提取】

    #SelectFromModel     from sklearn.feature_selection import SelectFromModel     sfm = SelectFromModel(forest, threshold = 0.1, prefit = True) #threshold閾值     X_selected = sfm.transform(X_train)     print('Number of samples that meet this criterion:',X_selected.shape[0]

    for f in range(X_selected.shape[1]):         print("%2d) %-*s %f" % (f + 1, 30,                  #%-*s ,其中*表示輸出string間隔                                 feat_labels[indices[f]],                                 importances[indices[f]]))

想對作者說點什麼? 利用Python Pandas進行資料預處理-資料清洗

4.9萬

資料缺失、檢測和過濾異常值、移除重複資料 資料缺失 資料缺失在大部分資料分析應用中都很常見,Pandas使用浮點值NaN表示浮點和非浮點陣列中的缺失資料,他只是一個便於被檢測出來的資料而已。from... 來自: YEN_CSDN的部落格 python資料預處理 缺失值,指標統計 -