上篇部落格說的是SoftMax回歸的基本内容,包括公式推導。這篇部落格基于葡萄酒資料進行葡萄酒品質預測模型建構,使用Softmax算法構模組化型,并擷取Softmax算法建構的模型效果(注意:分成11類)
資料
資料來源:Wine Quality Data Set
資料概要:

資料的屬性
![]()
機器學習(回歸九)——SoftMax回歸-代碼實作資料代碼
翻譯過來,大緻内容:
屬性資訊:
輸入變量(基于理化測試):
1 -固定酸度
2 -揮發性酸度
3 -檸檬酸
4 -殘餘糖
5 -氯化物
6 -遊離二氧化硫
7 -二氧化硫總量
8 -密度
9 - pH值
10 -硫酸鹽
11 -酒精
輸出變量(基于感官資料):
12 -品質(0 - 10分)
看幾條具體資料
代碼
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import pandas as pd
import warnings
import sklearn
from sklearn.linear_model import LogisticRegressionCV
from sklearn.linear_model.coordinate_descent import ConvergenceWarning
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import label_binarize
from sklearn import metrics
## 設定字元集,防止中文亂碼
mpl.rcParams['font.sans-serif']=[u'simHei']
mpl.rcParams['axes.unicode_minus']=False
## 攔截異常
warnings.filterwarnings(action = 'ignore', category=ConvergenceWarning)
## 讀取資料
path1 = "datas/winequality-red.csv"
df1 = pd.read_csv(path1, sep=";")
df1['type'] = 1 # 設定資料類型為紅葡萄酒
path2 = "datas/winequality-white.csv"
df2 = pd.read_csv(path2, sep=";")
df2['type'] = 2 # 設定資料類型為白葡萄酒
# 合并兩個df
df = pd.concat([df1,df2], axis=0)
## 自變量名稱
names = ["fixed acidity","volatile acidity","citric acid",
"residual sugar","chlorides","free sulfur dioxide",
"total sulfur dioxide","density","pH","sulphates",
"alcohol", "type"]
## 因變量名稱
quality = "quality"
## 顯示
df.head(5)
## 異常資料處理
new_df = df.replace('?', np.nan)
datas = new_df.dropna(how = 'any') # 隻要有列為空,就進行删除操作
print ("原始資料條數:%d;異常資料處理後資料條數:%d;異常資料條數:%d" % (len(df), len(datas), len(df) - len(datas)))
原始資料條數:6497;異常資料處理後資料條數:6497;異常資料條數:0
## 提取自變量和因變量
X = datas[names]
Y = datas[quality]
## 資料分割
X_train,X_test,Y_train,Y_test = train_test_split(X,Y,test_size=0.25,random_state=0)
print ("訓練資料條數:%d;資料特征個數:%d;測試資料條數:%d" % (X_train.shape[0], X_train.shape[1], X_test.shape[0]))
訓練資料條數:4872;資料特征個數:12;測試資料條數:1625
# 2. 資料格式化(歸一化)
# 将資料縮放到[0,1]
ss = MinMaxScaler()
X_train = ss.fit_transform(X_train) ## 訓練模型及歸一化資料
## 檢視y值的範圍和數理
Y_train.value_counts()
5 1606
7 805
4 161
8 146
3 20
9 2
Name: quality, dtype: int64
# 3. 模型建構及訓練
## penalty: 過拟合解決參數,l1或者l2
## solver: 參數優化方式
### 當penalty為l1的時候,參數隻能是:liblinear(坐标軸下降法);
### 當penalty為l2的時候,參數可以是:lbfgs(拟牛頓法)、newton-cg(牛頓法變種)
## multi_class: 分類方式參數;參數可選: ovr(預設)、multinomial;這兩種方式在二進制分類問題中,效果是一樣的;在多元分類問題中,效果不一樣
### ovr: one-vs-rest, 對于多元分類的問題,先将其看做二進制分類,分類完成後,再疊代對其中一類繼續進行二進制分類
### multinomial: many-vs-many(MVM),對于多元分類問題,如果模型有T類,我們每次在所有的T類樣本裡面選擇兩類樣本出來,
#### 不妨記為T1類和T2類,把所有的輸出為T1和T2的樣本放在一起,把T1作為正例,T2作為負例,
#### 進行二進制邏輯回歸,得到模型參數。我們一共需要T(T-1)/2次分類
## class_weight: 特征權重參數
### Softmax算法相對于Logistic算法來講,在sklearn中展現的代碼形式來講,主要隻是參數的不同而已
## Logistic算法回歸(二分類): 使用的是ovr;如果是softmax回歸,建議使用multinomial
lr = LogisticRegressionCV(fit_intercept=True, Cs=np.logspace(-5, 1, 100),
multi_class='multinomial', penalty='l2', solver='lbfgs')
lr.fit(X_train, Y_train)
# 4. 模型效果擷取
r = lr.score(X_train, Y_train)
print("R值:", r)
print("特征稀疏化比率:%.2f%%" % (np.mean(lr.coef_.ravel() == 0) * 100))
print("參數:",lr.coef_)
print("截距:",lr.intercept_)
print("機率:", lr.predict_proba(X_test)) # 擷取sigmoid函數傳回的機率值
print("機率:", lr.predict_proba(X_test).shape) # 擷取sigmoid函數傳回的機率值
R值: 0.5496715927750411
特征稀疏化比率:0.00%
參數: [[ 0.9730127 2.16084285 -0.41754754 -0.49107226 0.90062986 1.4392444
0.75285349 0.23015819 0.00696097 -0.69411951 -0.71662184 -0.29344398]
[ 0.62645663 5.12629124 -0.38350372 -2.1611902 1.21085251 -3.71460614
-1.45924414 1.33501236 0.33882333 -0.86777815 -2.74856763 2.03150322]
[-1.73734378 1.95681945 0.48966012 -1.91168338 0.64512953 -1.67662964
2.20493483 1.49022497 -1.3581056 -2.23627334 -5.01448694 -0.75503315]
[-1.19653545 -2.61094004 -0.34375325 0.17322861 -0.04192244 0.8170301
-0.28178849 0.51768511 -0.67621769 0.185218 0.01886649 -0.71342696]
[ 1.15776936 -4.66419 -0.30888948 2.21347594 -2.00208967 1.66891233
-1.02875476 -2.14504321 0.80606712 2.68429533 3.36550273 -0.73559995]
[-0.07708272 -1.8260927 0.69470163 2.0761507 -0.6231927 1.49048446
-0.15842754 -1.36420613 0.72475406 1.06822926 4.69108042 0.04776849]
[ 0.25372326 -0.1427308 0.26933225 0.10109059 -0.08940709 -0.02443551
-0.02957338 -0.06383129 0.15771782 -0.13957159 0.40422677 0.41823233]]
截距: [-2.33409277 -1.16759486 4.90906789 4.31851264 1.29806235 -2.26232821
-4.76162703]
機率: [[2.29894328e-03 3.30729714e-02 4.66552531e-01 … 5.29492016e-02
5.83107037e-03 3.08278584e-04]
[2.39084537e-03 1.73052873e-02 8.05569443e-02 … 3.13136934e-01
3.58259317e-02 4.63436966e-04]
[3.37404394e-03 1.55263335e-02 3.98405130e-01 … 8.76639384e-02
1.21057934e-02 3.78833283e-04]
…
[3.27231592e-03 1.62465297e-02 8.38101430e-02 … 3.70830765e-01
5.46102363e-02 5.42625050e-04]
[4.98416654e-03 2.55531822e-02 7.29802986e-01 … 1.82922910e-02
2.68720817e-03 1.48008504e-04]
[5.89788267e-03 3.64331319e-02 3.99745247e-01 … 8.04591823e-02
1.82397973e-02 5.04254984e-04]]
機率: (1625, 7)
# 資料預測
## a. 預測資料格式化(歸一化)
X_test = ss.transform(X_test) # 使用模型進行歸一化操作
## b. 結果資料預測
Y_predict = lr.predict(X_test)
## c. 圖表展示
x_len = range(len(X_test))
plt.figure(figsize=(14,7), facecolor='w')
plt.ylim(-1,11)
plt.plot(x_len, Y_test, 'ro',markersize = 8, zorder=3, label=u'真實值')
plt.plot(x_len, Y_predict, 'go', markersize = 12, zorder=2, label=u'預測值,$R^2$=%.3f' % lr.score(X_train, Y_train))
plt.legend(loc = 'upper left')
plt.xlabel(u'資料編号', fontsize=18)
plt.ylabel(u'葡萄酒品質', fontsize=18)
plt.title(u'葡萄酒品質預測統計', fontsize=20)
plt.show()
看一下效果:
紅色的點 ∙ ∙ \color {#F00} { \bullet} ∙∙ 表示的真實值,綠色的點 ∙ ∙ \color {#0F0} { \bullet} ∙ 是我們預測的值,最終結果似乎不太好哈。