決策樹(機(jī)器學(xué)習(xí)1)(代碼)

實(shí)驗(yàn)內(nèi)容

You are offered an excel file.
In this file, you can get the information of all the students in XXX university. The information includes students’ personal information (such as name, student ID, respective departments, age, native place) and course information (such as name of the courses and their respective grades).
You are asked to build a classification model to divide the grades into five categories: excellent, good, medium, pass, fail. The classification process is based on the information of name and native place. You should also show you results in a visual way.

理論分析

這次實(shí)驗(yàn)要求我們按照名字和籍貫,預(yù)測(cè)學(xué)生成績(jī)的等級(jí)。因?yàn)橹岸际桥芎瘮?shù)逼近類模型,這次我想嘗試一下可解釋性強(qiáng)的決策樹模型。
決策樹是一種簡(jiǎn)單高效并且具有強(qiáng)解釋性的模型,廣泛應(yīng)用于數(shù)據(jù)分析領(lǐng)域。其本質(zhì)是一顆由多個(gè)判斷節(jié)點(diǎn)組成的樹,如:


在使用模型進(jìn)行預(yù)測(cè)時(shí),根據(jù)輸入?yún)?shù)依次在各個(gè)判斷節(jié)點(diǎn)進(jìn)行判斷游走,最后到葉子節(jié)點(diǎn)即為預(yù)測(cè)結(jié)果。
現(xiàn)在有這樣的一些數(shù)據(jù),需要從姓名和籍貫預(yù)測(cè)成績(jī)所屬類別,共5個(gè)等級(jí)。


如果我們以籍貫先進(jìn)行分類,能得到一些結(jié)果(在葉子上),但是這樣分葉子上不一定是同一類標(biāo)簽。所以我們引入對(duì)一個(gè)集合進(jìn)行的有序程度進(jìn)行量化,然后引入信息增益概念對(duì)一次拆分進(jìn)行量化評(píng)價(jià)。
熵是信息論中的概念,用來表示集合的無序程度,熵越大表示集合越混亂,反之則表示集合越有序。熵的計(jì)算公式為:
E=-P log_2P
信息增益,假設(shè)集合 U,一次拆分后變?yōu)榱藘蓚€(gè)集合 u1 和 u2 ,則有:
\Delta E=E(U)-(P_{u1} E(u1)+P_{u2}E(u2))

可以通過信息增益量化一次拆分的結(jié)果好壞,下一步就是構(gòu)造決策樹,主要步驟如下:
1.遍歷每個(gè)決策條件(如:籍貫、姓名),對(duì)結(jié)果集進(jìn)行拆分
2.計(jì)算該決策條件下,所有可能的拆分情況的信息增益,信息增益最大的拆分為本次最優(yōu)拆分
3.遞歸執(zhí)行1、2兩步,直至信息增益<=0

實(shí)驗(yàn)結(jié)果

語(yǔ)言:Python3.6
系統(tǒng):MacOS 10.13.3
硬件:2.9 GHz Intel Core i5
16 GB 1867 MHz DDR3
1.數(shù)據(jù)量化
將文本數(shù)據(jù)轉(zhuǎn)成可計(jì)算形式。這里我采用二值詞計(jì)數(shù)向量編碼姓名,用one-hot編碼籍貫。
例如,名字:abbd -> [1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
籍貫:102 ->[0,1,0,0,0]
將分?jǐn)?shù)按照等間隔5分類成了[0]=excellent, good, medium, pass,[5]= fail。
2.數(shù)據(jù)可視化
這里做了pca降維
name explained variance ratio: 0.212
ID explained variance ratio: 0.186
猜想:成績(jī)與名字應(yīng)該沒有關(guān)系



發(fā)現(xiàn)數(shù)據(jù)確實(shí)沒有明顯的聚集分布。
3.調(diào)整模型參數(shù)
測(cè)試不同的最大深度有什么不一樣效果


結(jié)果完全的欠擬合。符合猜想。
4.那也得訓(xùn)練模型



無論哪個(gè)特征,模型都無法收斂。

  1. 模型導(dǎo)出



實(shí)驗(yàn)總結(jié)

決策樹容易過度擬合數(shù)據(jù),它可能專門針對(duì)訓(xùn)練集創(chuàng)建出來的分支,其熵值可能會(huì)比真實(shí)情況有所降低。進(jìn)行剪枝可以減輕這種現(xiàn)象,人工設(shè)置一個(gè)信息增益的閥值,自下而上遍歷決策樹,將信息增益低于該閥值的拆分進(jìn)行合并
從本實(shí)驗(yàn)來看,籍貫與名字對(duì)最終成績(jī)影響小于30%。
本次實(shí)驗(yàn)簡(jiǎn)單嘗試了決策樹算法,該算法雖然簡(jiǎn)單,但是在很多場(chǎng)景能取得非常好的效果。另外,從決策樹發(fā)展出了更為高級(jí)復(fù)雜的隨機(jī)森林,如果有時(shí)間,,可以去深入了解。

代碼

import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
from sklearn.preprocessing import minmax_scale
from sklearn import tree
import graphviz
from sklearn.model_selection import learning_curve,validation_curve
from mpl_toolkits.mplot3d import Axes3D

# file='chengji.csv'
# f_csv=pd.read_csv(file)
# 把籍貫向量化
# '''
# jiguan={}
# ids=(f_csv['籍貫'])
# j=0
# for i in ids:
#     if i not in jiguan:
#         jiguan[i]=j
#         j+=1
# print(jiguan)
# id_list=np.zeros((len(ids),len(jiguan.keys())))#9類
# for i,id in enumerate(ids):
#     id_list[i][jiguan[id]]=1
# print(id_list)
# np.save('idlist.npy',id_list)
# '''

# 名字詞向量化
# names=(f_csv['姓名'].values)
# print(names.values)
# names=np.array(names)
# np.save('names.npy',names)
# print(names==names0)

# hash_text=text.HashingVectorizer(n_features=26)
# labels=np.load('label.npy')
# grades_one=np.load('grades_one.npy')
# print(names)
# start=ord('a')
# name_vec=np.zeros((len(names),26),dtype=np.uint8)
# for i,n in enumerate(names):
#     n=set(n)
#     for a in n:
#         name_vec[i][ord(a)-start]=1
#     pass
# print(name_vec)
# np.save('name_vec.npy',name_vec)
# t=hash_text.transform(names)
# exit()
# name_vec=np.load('name_vec.npy')
# id_list=np.load('idlist.npy')

# nb,rf,svm,
#
# for i,l in enumerate(labels):
#     one=np.where(l == 1)[0].ravel()[0]
#     print(one)
#     labels[i]=one

# labels=labels[:,:1].astype(np.int32)
# np.save('label.npy',labels)
# print(labels)
# labels=np.load('label.npy')
# names=np.load('name_vec.npy')
# id_list=np.load('idlist.npy')
# X=np.concatenate((names,id_list),axis=1)
# np.save('X.npy',X)
# exit()
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
cmap=cm.get_cmap('Set1')
np.random.seed(0)

X=np.load('X.npy')[:,:]
labels=np.load('label.npy')
from sklearn.decomposition import PCA
pca = PCA(n_components=1)
name=pca.fit_transform(X[:,:26])
print('pca(n=%d) explained variance ratio: %.3f' %(1, np.sum(pca.explained_variance_ratio_)))
ID=pca.fit_transform(X[:,26:])
print('pca(n=%d) explained variance ratio: %.3f' %(1, np.sum(pca.explained_variance_ratio_)))
ID,name=minmax_scale(ID),minmax_scale(name)
def draw_image(x,y):
    for i in range(5):
        indice=np.where(y==[i])[0]
        xi=x[indice]
        # print(xi)
        # plt.scatter(xi[:,0],xi[:,1],c=cmap(np.ones((len(indice),))*1/(i+1)))
        ax.scatter(xi[:,0],xi[:,1],
        np.ones((len(indice),1))*1/(i+1),
        c=cmap(1-np.ones((len(indice),))*i*0.1)
        )
    pass
nex_x=np.concatenate((name,ID),axis=1)
draw_image(nex_x,labels)
# plt.show()
plt.savefig('showme3d.tiff')

'''
# 決策樹
clf=tree.DecisionTreeClassifier(max_depth=7)

clf.fit(X,labels)
print(clf.score(X,labels),np.sum(clf.feature_importances_[:26]))
print(clf.predict([X[0]]),labels[0])
dot_data = tree.export_graphviz(clf, out_file=None,
                            filled=True, rounded=True,
                            special_characters=True)
graph = graphviz.Source(dot_data)
graph.render("grades_by_name",cleanup=True)
'''
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容