構建決策樹時出現ValueError: Length of feature_names, 4 does not match number of features, 10的解決辦法
以下為原代碼:
import pandas as pd
from sklearn import tree
ball_data = pd.read_csv('ball.csv')
cat_features = ['Outlook','Temperature','Humidity','Windy']
ball_data_onehot = pd.get_dummies(ball_data,columns=cat_features)
ball_data_onehot['Play'] = ball_data_onehot['Play'].map({'No':0,'Yes':1}).astype(int)
ball_data_tr_in = ball_data_onehot.drop(columns=['Play'])
ball_data_tr_out = ball_data_onehot['Play']
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(ball_data_tr_in,ball_data_tr_out,test_size=0.3,random_state=1)
#random_state=1表示資料集中的測驗集和訓練集每次運行都隨機生成,random_state=1表示除第一次運行資料集中的訓練集和測驗集是隨機生成的以外,之后每次運行的資料集和測驗集都和第一次運行一樣
print(X_train)
print(y_train)
clf = tree.DecisionTreeClassifier(criterion='entropy')
model = clf.fit(X_train,y_train)
res = model.predict(X_test)
print(res) #模型結果輸出
print(y_test) #實際值
print(sum(res==y_test)/len(res)) #準確率
#測驗DecisionTreeClassifier()不加引數的情況
clf1 = tree.DecisionTreeClassifier()
clf1 = clf.fit(ball_data_tr_in,ball_data_tr_out)
print('clf1:'+str(clf1)) #列印模型,列印出來是一個函式
print(clf1)
#自己構建一個資料A,代入模型對A進行預測
A = ([[0,1,0,0,0,1,0,1,0,1]])
predict_result = clf.predict(A)
print('預測結果:'+str(predict_result))
if predict_result==0:
print('濕度正常,有點雨,有霧,有風的時候不去打球')
#構建決策樹
import graphviz
dot_data = tree.export_graphviz(model,out_file = None,
feature_names=['Outlook','Temperature','Humidity','Windy'],
class_names = ['No','Yes'],
filled = True,rounded = True,
special_characters = True)
graph = graphviz.Source(dot_data)
graph.render('PlayBall')
pycharm運行后報錯將錯誤索引到構建決策樹時的tree.export_graphviz中的feature_names這一引數上,以下為代碼錯誤部分:
dot_data = tree.export_graphviz(model,out_file = None,
feature_names=['Outlook','Temperature','Humidity','Windy'],
class_names = ['No','Yes'],
filled = True,rounded = True,
special_characters = True)
錯誤就出在feature_names=[‘Outlook’,‘Temperature’,‘Humidity’,‘Windy’] 這個地方,feature_names這一引數的作用是使決策樹圖中的各個小塊可以顯示其對應的特征名(自己是初學者描述不夠詳細,具體可以去搜其他關于export_graphviz()引數的資料),而這一引數要求引數值必須與被分析的資料集中的特征名(也叫屬性名)對應,數量一致且順序一致,且不要把類標號class也寫進去(因為類標號是最終分析的結果),
以上面原代碼為例,一開始讀取ball.csv資料檔案,具體內容如下:
| Outlook | Temperature | Humidity | Windy | Play |
|---|---|---|---|---|
| sunny | hot | high | no | No |
| sunny | hot | high | yes | No |
| overcast | hot | high | no | Yes |
| rain | mild | high | no | Yes |
| rain | cool | normal | no | Yes |
| rain | cool | normal | yes | No |
| overcast | cool | normal | yes | Yes |
| sunny | mild | high | yes | No |
| sunny | cool | normal | no | Yes |
| rain | mild | normal | no | Yes |
| sunny | mild | normal | yes | Yes |
| overcast | mild | high | yes | Yes |
| overcast | hot | normal | no | Yes |
| rain | mild | high | yes | No |
可以發現特征名為Outlook,Temperature,Humidity,Windy(且以此順序),Play是類標號,在原代碼一開始我們定義了一個cat_features = [‘Outlook’,‘Temperature’,‘Humidity’,‘Windy’] 的串列用于存放我們所需要進行的獨熱編碼的列名稱(即特征名),ball_data_onehot = pd.get_dummies(ball_data,columns=cat_features) 用于對資料進行獨熱編碼,注意一定要理解獨熱編碼的具體含義,在此處非常重要,具體可以去查其他相關資料;一開始提到錯誤出現在feature_name這里,因為feature_name要求和資料的特征名一致,但是此時觀察上表以及cat_features發現不管是特征名還是特征名的順序都一致,但是為什么會出現Length of feature_names, 4 does not match number of features, 10(feature_name的個數4與資料中特征名的個數10不符) 這樣的錯誤呢?

其實稍微了解獨熱編碼后會發現,pd.get_dummies() 對資料進行獨熱編碼后,資料的結構會發生很大的改變,在對上表的資料進行獨熱編碼后資料變為:
| Outlook_overcast | Outlook_rain | Outlook_sunny | Temperature_cool | Temperature_hot | Temperature_mild | Humidity_high | Humidity_normal | Windy_no | Windy_yes |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 |
| 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 1 |
| 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 |
| 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 0 |
| 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 |
| 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 |
| 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 |
| 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 |
| 0 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 |
| 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 |
| 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 1 |
| 1 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 |
| 1 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 |
| 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 |
發現經過獨熱編碼后此時特征名已經變成了:Outlook_overcast,Outlook_rain,Outlook_sunny,Temperature_cool,Temperature_hot,Temperature_mild,Humidity_high,Humidity_normal,Windy_no,Windy_yes,恰好是10個,真相大白,
這才是feature_names的正確賦值,此時將feature_names改為:
feature_names=['Outlook_overcast','Outlook_rain','Outlook_sunny','Temperature_cool','Temperature_hot','Temperature_mild','Humidity_high','Humidity_normal','Windy_no','Windy_yes']
即可解決錯誤,之所以出現此錯誤,是因為對獨熱編碼的方式不夠了解,自己以后引以為戒,第一次寫博客寫的不好,希望能對遇到相同問題的朋友有所幫助,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/230306.html
標籤:python
