iT邦幫忙

2021 iThome 鐵人賽

DAY 14
2
AI & Data

學資料科學的小孩不會變壞- 從入門到實戰全攻略系列 第 14

DAY14 挑選合適的模型進行訓練

機器學習可以分成監督式學習與非監督式學習,這部分我們在第四天有稍微提到過,這邊就不多做說明了,今天我們將介紹這兩類的問題分別適合用什麼模型來做處理。


一、監督式學習

分類問題

1.羅吉斯回歸(Logistic Regression):

羅吉斯回歸是一種分類演算法,其原理為找到一條線將資料盡可能的區隔出來,可以處理二元分類的問題。

  • 優點:可解釋力強;訓練速度快;可獲得A類跟B類的機率。
  • 缺點:處理非線性數據時較麻煩,需對特徵做更多的處理。

使用鳶尾花資料集(內建)實作

from sklearn import datasets
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import mean_squared_error, accuracy_score
#載入資料集
iris = datasets.load_iris()
#資料整理
x = pd.DataFrame(iris['data'], columns=iris['feature_names'])
y = pd.DataFrame(iris['target'], columns=['target'])
iris_data = pd.concat([x,y], axis=1)#將資料合併
print(iris_data)
#透過兩個特徵來進行分類
iris_data = iris_data[['sepal length (cm)','petal length (cm)','target']] 
print(iris_data)
#這邊分成兩個類別 (山鳶尾、變色鳶尾)
iris_data = iris_data[iris_data['target'].isin([0,1])]
iris_data
X = iris_data[['sepal length (cm)','petal length (cm)']]
y = iris_data[['target']]
#切分訓練集以及測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
print('len X_train:',len(X_train),'len X_test:',len(X_test))
#將資料常態分布化,平均值會變為0, 標準差變為1,使離群值影響降低
sc = StandardScaler()
sc.fit(X_train)
X_train_std = sc.transform(X_train)
X_test_std = sc.transform(X_test)
#使用上面整理好切割好的資料做訓練
lr = LogisticRegression()
model = lr.fit(X_train_std,y_train['target'].values)
#%%分類預測結果
predict = model.predict(X_test_std)
print("predict label:",predict)
#創建顏色庫
markers = ('s', 'x')
colors = ('orange', 'darkblue')
cmap = ListedColormap(colors[:len(np.unique(y))])

#將分類的區塊視覺化
x1_min, x1_max = X_train_std[:, 0].min()-1, X_train_std[:, 0].max()+1 # 特徵1最小值與最大值
x2_min, x2_max = X_train_std[:, 1].min()-1, X_train_std[:, 1].max()+1 # 特徵2最小值與最大值
xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, 0.01),np.arange(x2_min, x2_max, 0.01)) # 將數據變成m*n矩陣:(m根據前面array長度,n根據後面array長度);0.01為contourf的精度
Z = lr.predict(np.array([xx1.ravel(), xx2.ravel()]).T) #ravel將矩陣拉平成一維
Z = Z.reshape(xx1.shape)

plt.figure(figsize=(12,8))
plt.contourf(xx1, xx2, Z, alpha=0.4, cmap=cmap)
plt.xlim(xx1.min(), xx1.max()) 
plt.ylim(xx2.min(), xx2.max()) #Y軸範圍

#畫test資料點位置
y_test_n=np.array(y_test.values)#將label data變成跟特徵的類型一樣以利後續畫圖
plt.scatter(X_test_std[:,0], X_test_std[:,1],alpha=0.6,c = y_test_n,edgecolor='black',marker='s')
plt.xlabel('sepal length (cm) [standardized]',size=20)
plt.ylabel('petal width [standardized]',size=20)
plt.show()

https://ithelp.ithome.com.tw/upload/images/20210908/20140427bc8zlvGJf0.png
從上圖可以看到模型幫助我們找到一條線將資料分成兩類。

2.決策樹(Decision Tree)

透過一系列的是非問題,幫助我們將資料進行切分

  • 從訓練資料中找出規則,讓每一次決策能夠使訊息增益最大化
  • 訊息增益越大代表切分後的兩群資料,群內相似程度越高
  • 例如使用員工資料來預測是否離職,若用是否常加班來切分,可以有效分出離職跟非離職的差別,那此特徵就是一個好特徵。(如下圖所示)

訊息增益:

用來選特徵的,決策樹模型會用特徵切分資料,該選用哪個特徵來切分就是由訊息增益的大小決定的。
https://ithelp.ithome.com.tw/upload/images/20210908/20140427uxR7phOLwW.png

clf = tree.DecisionTreeClassifier()
clf = clf.fit(df_X, df_Y)

3.隨機森林(Random Forest)

隨機森林就是將多個決策樹集合而成,為的就是改善決策樹容易overfitting的問題,而隨機森林也是一種集成學習。

集成 (Ensemble) 就是將多個模型的結果組合在一起,透過投票或是加權的方式得到最終結果,如下圖所示:
https://ithelp.ithome.com.tw/upload/images/20210908/20140427Gdux5CSVFB.png
圖片來源:機器學習百日馬拉松Day43隨機森林 (Random Forest) 介紹

from sklearn.ensemble import RandomForestClassifier
rfc=RandomForestClassifier(n_estimators=100)
rfc_model=rfc.fit(df_X,y)
pred_test = rfc_model.predict(data_test)

4.XGboost

XGBoost是boosting算法的其中一種,Boosting算法的概念是將許多弱分類器集成在一起,形成一個強分類器。有興趣的可以參考原文網址:https://kknews.cc/news/grejk5m.html

from xgboost import XGBClassifier
xgbc=XGBClassifier()
xgbc_model=xgbc.fit(df_X,y)
pred_test = xgbc_model.predict(data_test)

5.支持向量機(Support Vector Classification)

  • SVC : Support Vector Classification 支持向量機用於分類問題
  • SVR : Support Vector Regression 支持向量機用於回歸分析
SVM = SVC()
svc_model = SVM.fit(X_train_std,y_train)

回歸問題

1.線性回歸模型

線性迴歸的目的在於找到一條可以擬合數據的線,使預測值與真實值之間的殘差越小越好,通常可作為 baseline 模型作為參考點。

使用糖尿病資料集(內建)來實作

# 讀取糖尿病資料集
diabetes = datasets.load_diabetes()
x = pd.DataFrame(diabetes['data'],columns=diabetes['feature_names'])
y = pd.DataFrame(diabetes['target'],columns=['target'])
diabetes_data = pd.concat([x,y], axis=1)#將資料合併
diabetes_data
# 取用bmi的特徵
X = np.array(diabetes_data.iloc[:,2:3])
y = np.array(diabetes_data.iloc[:,10:11])
print("Feature shape:", X.shape,"target shape:",y.shape)
#切資料
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=0)
print('len X_train:',len(X_train),'len X_test:',len(X_test))
# 建立一個線性迴歸模型
reg = LinearRegression()
# 將訓練資料丟進去模型訓練
reg_model = reg.fit(X_train, y_train)
# 將測試資料丟進模型得到預測結果
y_pred = reg_model.predict(X_test)
# 迴歸模型的係數與截距
print('coefficients:',reg.coef_)
print('intercept: ',reg.intercept_)
# 預測值與實際值的差距,使用 MSE
print("Mean squared error: %.2f"% mean_squared_error(y_test, y_pred))
# 看模型的準確度
print("R square: %.2f"%r2_score(y_test,y_pred))
#模型效果視覺化
plt.scatter(X_test,y_test,color='black')
plt.plot(X_test, y_pred, color='blue', linewidth=3)
plt.xlabel('bmi',size=20)
plt.ylabel('target',size=20)

https://ithelp.ithome.com.tw/upload/images/20210908/20140427S2WFLMtRqb.png
由上圖可以看到黑色的點點是我們的預測值

2.隨機森林(Random Forest)

# Modeling
rf = RandomForestRegressor(n_estimators = 400, min_samples_leaf=0.12, random_state=123)

#Fitting Random Forest model
rf.fit(X_train, Y_train)

#Predicting using the Random Forest model
Y_pred = rf.predict(X_test)
Y_pred = pd.DataFrame(Y_pred).astype('int')
#Evaluate
print('Mean Absolute Error(MAE):', metrics.mean_absolute_error(Y_test, Y_pred))  
print('Mean Squared Error(MSE):', metrics.mean_squared_error(Y_test, Y_pred))  
print('Root Mean Squared Error(RMSE):', np.sqrt(metrics.mean_squared_error(Y_test, Y_pred)))

3.XGboost

import xgboost
xgb=xgboost.XGBRegressor()
xgb.fit(X_train, Y_train)
xgb_pred = xgb.predict(X_test)

4.支持向量機Support Vector Classification

SVM = SVR()
svr_model = SVM.fit(X_train_std,y_train)

二、非監督式學習

1.K-means(k-平均演算法)

  • K-means 目標是使總體群內平方誤差最小
  • 因爲沒有預先的標記,對於 cluster 數量多少才是最佳解,沒有標準答案,得靠手動測試觀察。
  • 當問題不清楚或是資料未有標註的情況下,可以嘗試用分群算法幫助瞭解資料結構,而其中一個方法是運用 K-means 聚類算法幫助分群資料
  • 分群算法需要事先定義群數,因此效果評估只能藉由人爲觀察。

我們利用內建資料集來實作

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.datasets import make_blobs  #用於生成聚類資料集
from sklearn.cluster import KMeans
#生成
x, y = make_blobs(n_samples=300, centers=4, cluster_std=3, random_state=0) #cluster_std = The standard deviation of the clusters
df = pd.DataFrame({'x':[x],'y':[y]}) #feature 2 dim ,y=label
plt.scatter(x[:,0], x[:,1],c=y)
x = pd.DataFrame(x,columns=['x1','x2'])
y = pd.DataFrame(y,columns=['y'])

from sklearn.cluster import KMeans
n_clusters=4
kmean = KMeans(n_clusters=n_clusters, random_state=0)
kmean.fit(x)
pred_y = kmean.predict(x)

plt.scatter(x=x.iloc[:,0], y=x.iloc[:,1],c=pred_y)

https://ithelp.ithome.com.tw/upload/images/20210908/20140427Gs704eumYM.png
我們設定參數k為四群,而從畫出來的圖可以看到特徵被有效的分成四群。


三、結論

看到上述的這些模型,是不是覺得頭昏腦脹呢?這還只是一小部分而已,之後在這個領域接觸的越深,所碰到的資料也會越複雜,甚至還可能需要自己寫出一個模型,不過對於初學者來說,能夠了解這些模型的原理並知道如何使用它,就可以幫助我們完成一些專案了。


上一篇
DAY13 特徵工程-資料標準化與降維
下一篇
DAY15 模型預測評估方法
系列文
學資料科學的小孩不會變壞- 從入門到實戰全攻略30

尚未有邦友留言

立即登入留言