1. 程式人生 > >機器學習實戰:智慧製造質量預測

機器學習實戰:智慧製造質量預測

一、資料清洗

注意:pandas函式使用後一般是不對原表起作用的,要重新賦值
對dataframe來說,bool運算any()、all(),預設沿axis=0反向,即沿著列
初步清洗後從8209列到3074列

1.初步清洗

去除重複列,注意可能會跨幾十列重合的,需要遍歷同一個工序。
去除全0、NAN。
去除單一值列,或者單一值配NAN或0的二值列。

import pandas as pd
from collections import Counter


data = pd.read_excel("train.xlsx")
# names = data.columns
# tools = [name for name in names if "t" in name or "T" in name]
data = data.fillna(0) dataSet = data.drop(['ID', 'TOOL_ID', 'Tool', 'TOOL_ID (#1)', 'TOOL_ID (#2)', 'TOOL_ID (#3)', 'Tool (#1)', 'Tool (#2)', 'tool', 'tool (#1)', 'TOOL', 'TOOL (#1)', 'Tool (#3)', 'TOOL (#2)', 'Y'], axis=1) drop_columns = [] columns = dataSet.columns for
name in columns: arr = [num for num in dataSet[name]] if arr[0] > 10 ** 12: drop_columns.append(name) continue counts = Counter(arr) if len(counts.keys()) == 1: drop_columns.append(name) if 0 in counts.keys(): if counts[0] >= 200 or len(counts.keys(
)) == 2: drop_columns.append(name) data = data.drop(drop_columns, axis=1) data = data.T data = data.drop_duplicates(keep="first") data = data.T print(len(data.columns)) data.to_excel("cleaned.xlsx")

2.時間處理

真是醉了,這麼多資料還有時間!!!單純的時間戳是沒有意義的,我們需要找一個基準時間做時間差!!!
但是基準時間不知道找哪個,可以定位2017.1.1,0:00,注意時間有9位、14位和16位的。。。

程式碼不貼了,基本重複操作,取一下差值。

3.均值填0

然後填充0真的很頭大,因為工序工具的不同整體就有很大的差異。所以要按照工序分成13張sheet表,然後讀取,一張張填充,由於pandas寫excel會覆蓋(解決方法正在研究),為省事我直接生成13張excel了。有個很坑的點,有些工序索引竟然是數字,這個時候索引會崩了,loc好像可以解決(官方建議使用loc和iloc,前者對標籤,後者對順序)。這就需要excel採取點手段,我是前後加了雙引號。

做好心理準備!!!我最長的一個表跑了快十分鐘, 真心累!!!
import pandas as pd
import time

sheets_name = ["t2", "t3", "t4", "t5",  "t7",  "t9", "t10", "t11", "t13"]

for name in sheets_name:
    start = time.time()
    dataSet = pd.read_excel("groups.xlsx", sheet_name=name, index_col=name)
    length = len(dataSet.columns)
    index_set = set(list(dataSet.index))
    print(name)
    drop_columns = []
    for i in range(1, length):
        for index in index_set:
            arr = dataSet.ix[index, i]
            arr_zeros = 0
            arr_length = len(arr)
            for num in arr:
                if num == 0:
                    arr_zeros += 1
            if arr_zeros >= arr_length * 0.5:
                drop_columns.append(dataSet.columns[i])
                break
            else:
                arr_mean = sum(arr)/(arr_length - arr_zeros)
                for j in range(500):
                    if dataSet.ix[j, i] == 0 and dataSet.index[j] == index:
                        dataSet.ix[j, i] = arr_mean

    dataSet = dataSet.drop(drop_columns, axis=1)
    dataSet.to_excel(name + ".xlsx", index=False)
    print(time.time()-start)


二、特徵工程

將13張小表整合在一張大表上,第一列ID,最後一列y,中間按工序順序遞增。最後是有3449維特徵。

有幾種思路:
1.考慮基於pearson相關係數,即pearson(X,Y),限定一個閾值,篩選特徵。此外還有spearman相關係數(基於秩)、最大資訊係數(MIC,非線性)可以考慮。
2.直接將資料交給模型,我們根據輸出的係數進行篩選,再進行訓練。
3.遞迴特徵消除
4.設定一個threshold,對特徵進行過濾

1、pearson相關性分析

這是單變數特徵選擇,去相關係數前100的特徵進行訓練。將新資料儲存到excel可以給其他模型使用。

import pandas as pd
import matplotlib.pyplot as plt
from scipy.stats import pearsonr
import numpy as np

dataSet = pd.read_excel("data.xlsx")
columns = dataSet.columns
labels = dataSet.ix[:, -1].values
X = dataSet.ix[:, :-1].values


def pearson_coef(X, y):
    coefs = []
    length = len(columns)
    for i in range(length-1):
        arr = X.ix[:, i]
        coef = pearsonr(arr, y)
        coefs.append((coef[0], columns[i]))
    coefs_Max2Min = sorted(coefs, key=lambda x: abs(x[0]), reverse=True)
    MAX100 = coefs_Max2Min[: 100]
    # 100th is 0.2079
    coefs_MAX100 = [abs(item[0]) for item in MAX100]
    names = [item[1] for item in MAX100]
    fig, ax = plt.subplots(figsize=(25, 6))
    index = range(30)
    ax.bar(index, (np.array(coefs_MAX100[: 30]) - 0.2)*100, width=0.4)
    plt.xticks(index, names[: 30])
    plt.xlabel("features")
    plt.ylabel("coefs")
    plt.title("Pearson correlation anlysis")
    plt.show()
    return names


names = pearson_coef(dataSet, labels)
new_data = dataSet.ix[:, names]
new_data.to_excel("new.xlsx")

2、移除低方差的特徵

關於這個點我比較糾結。我們拿到的特徵量綱差距很大,最大有十幾個數量級。如果對資料標準化,方差將恆為1,歸一化感覺也不太合適。

可以嘗試設定閾值,將(方差/均值)小的去了,目的在於把資料變化很小的資料去了。

from sklearn.feature_selection import VarianceThreshold

threshold = .8 * (1-.8)
selector = VarianceThreshold(threshold)
selector.fit_transform(X)
# 得到過濾好的資料, 過濾掉列方差小於threshold的特徵

3、selectKbest, PCA降維分析

1.在selectKbest裡,可以指定標準,如卡方檢測chi2,或者自己寫的函式。

2、先進行歸一化再PCA,否則特徵值會非常大。不過降維效果不好,雖說降200維,能解釋94.5%的方差,但是特徵值變化太過平坦了,從第一個開始下降的很緩慢,之後套到其它模型效果更差了。我覺得可能是因為工業資料資料會存在一定關聯性,對原特徵進行組合可能會丟失資訊(猜的。。)

4、遞迴特徵消除RFE

遞迴嘛,就是每次訓練都提取最好的幾個特徵,然後利用剩下的特徵繼續訓練,繼續提取,直到模型不行的時候停止。
使用sklearn.feature_selection

5、基於模型篩選

from sklearn.feature_selection import SelectFromModel

xgb = XGBRegressor()
xgb.fit(X_train, y_train)

new_xgb = SelectFromModel(xgb, threshold=threshold, prefit=True)
sel_Xtrain = new_xgb.transform(X_train)
# 要對原來的資料進行變換,因為被篩選過了。
sel_xgb = XGBRegressor()
sel_xgb.fit(sel_Xtrain, y_train)

最後選擇1和5方式進行建模


三、建立模型

在瞭解了GBDT、Adaboost、Xgboost這幾個整合學習模型後,只想說數學NB!
簡單的線性模型考慮,Ridge、Lasso、elastic搞起啊,這兩個我有一篇blog專門寫過。

1.Lasso、Ridge

from sklearn.linear_model import Lasso, LassoCV, LassoLarsCV
from sklearn.linear_model import RidgeCV
import pandas as pd
from sklearn.metrics import r2_score, mean_squared_error
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import cross_val_predict
import matplotlib.pyplot as plt


dataSet = pd.read_excel("new2.xlsx")
columns = dataSet.columns
y = dataSet.ix[:, -1].values
X = dataSet.ix[:, :-1].values
X = StandardScaler().fit_transform(X=X)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=2)


lasso = Lasso(alpha=0.0001)
# lasso.fit(X_train, y_train)
# print(lasso.alpha_)
coefs = sorted(abs(lasso.coef_), reverse=True)
plt.figure("feature importance", figsize=(18, 6))
plt.bar(range(30), coefs[: 30])

# y_pred = lasso.predict(X_test)
y_pred = cross_val_predict(lasso, X, y, cv=5)
print("R2:", r2_score(y, y_pred))
print("MSE:", mean_squared_error(y, y_pred))

plt.figure(figsize=(18, 6))
plt.plot(y)
plt.plot(y_pred)
plt.show()

最後只有25維資料有權重,可以使用 selectfrommodel 對特徵進行提取,然後再使用Lasso。跑出來最好的單個lasso模型是alpha=0.007669
在這裡插入圖片描述
最後是使用交叉驗證輸出MSE=0.03199,感覺差的挺多。
在這裡插入圖片描述
Ridge迴歸跑出來alpha=10.0,MSE=0.034, 懲罰係數感覺有點大了。

2、XGboost+基於模型篩選

from xgboost import XGBRegressor
from xgboost import plot_importance
import pandas as pd
from sklearn.feature_selection import SelectFromModel
from sklearn.metrics import r2_score, mean_squared_error
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestRegressor
import matplotlib.pyplot as plt

# dataSet = pd.read_excel("data.xlsx")
dataSet = pd.read_excel("new2.xlsx")
columns = dataSet.columns
y = dataSet.ix[:, -1].values
X = dataSet.ix[:, :-1].values
X = StandardScaler().fit_transform(X=X)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=2)

xgb = XGBRegressor()
xgb.fit(X_train, y_train)

y_pred = xgb.predict(X_test)
# imps = sorted(xgb.feature_importances_, reverse=True)
# threshold = imps[30]
# new_xgb = SelectFromModel(xgb, threshold=threshold, prefit=True)
# fig, ax = plt.subplots(figsize=(20, 10))
# plot_importance(xgb, ax=ax, height=0.3, max_num_features=30)
# plt.show()
#
# sel_Xtrain = new_xgb.transform(X_train)
# sel_xgb = XGBRegressor()
# sel_xgb.fit(sel_Xtrain, y_train)
#
# sel_Xtest = new_xgb.transform(X_test)
# y_pred = sel_xgb.predict(sel_Xtest)

print("R2:", r2_score(y_test, y_pred))
print("MSE:", mean_squared_error(y_test, y_pred))

plt.plot(y_test)
plt.plot(y_pred)
plt.show()

先試了下全量特徵xgb,跑出來MSE=0.038
然後篩選特徵重新訓練,主要是調參,這個得多試,沒什麼經驗,跑出來是MSE=0.032

3、SVR+遞迴特徵消除

from sklearn.svm import SVR
import pandas as pd
from sklearn.feature_selection import RFE
import matplotlib.pyplot as plt
from sklearn.metrics import r2_score, mean_squared_error
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler


dataSet = pd.read_excel("new.xlsx")
columns = dataSet.columns
y = dataSet.ix[:, -1].values
X = dataSet.ix[:, :-1].values
X = StandardScaler().fit_transform(X=X)

svr = SVR()
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=22)
svr.fit(X_train, y_train)
y_pred = svr.predict(X_test)
print("R2:", r2_score(y_test, y_pred))
print("MSE:", mean_squared_error(y_test, y_pred))
plt.plot(y_test)
plt.plot(y_pred)
plt.show()

在這裡插入圖片描述
這個是用100維資料跑的,SVR跑出來MSE=0.027
對比發現,自己篩選過得比全量特徵跑會更加陡峭。
底下是全量特徵跑的。
在這裡插入圖片描述

期間嘗試還了RandomForest、Adaboost、GBDT等模型,限於篇幅,不再展示了。

四、模型評估

1、Lasso和Ridge迴歸都屬於線性迴歸的變種,增加了懲罰項,都可以解決樣本數量少於特徵數的情況。經過實驗證明,事先通過相關性篩選100特徵效果會更好。Lasso可以更顯著地突出重要特徵,大部分系數被懲罰為0。Lasso效果稍好於Ridge。
2、xgboost、Adaboost屬於boosting家族,RandomForest屬於整合學習。xgboost使用全量特徵訓練效果更好。限於調參,xgboost的效能沒能很好的發揮出來。
3、基於遞迴特徵消除的SVR效果最好,訓練資料全特徵,最小MSE達到0.026。


五、小結

可以改進的地方:
  • 有些資料0值可能是有實際意義的,為了方便全部填充了。這個可能需要手工看了,如果一列中有正有負而且0出現跟工具無關,可以考慮保留了。
  • 嘗試特徵構造。因為最近挺忙的,所以很多想法還沒有實踐。特徵構造非常值得一試,比如單特徵error、雙特徵的運算,可以探索工序間的內在聯絡。
  • 可以嘗試模型融合,權值調整。
感想:

做題時,在資料處理上花費了很大功夫,遇到了很多坑,都一點一點解決了。在套模型的時候沒出什麼bug,比較順利。在訓練模型前,學習了各種迴歸模型原理、特點、優勢劣勢,部分模型進行了推導。對特徵工程也有了一定見解,個人認為特徵工程對大資料分析應該是最關鍵的,決定了模型的上限。溫習和加強了sklearn,pandas,numpy,scipy,matplotlib等庫的使用。


參考資料
1.特徵工程:
https://www.jianshu.com/p/1c4ec02dd33f
2.交叉驗證:
https://blog.csdn.net/JasonDing1354/article/details/50562513
https://blog.csdn.net/xiaodongxiexie/article/details/71915259
3.Lasso、Ridge原理:
https://www.cnblogs.com/pinard/p/6018889.html