利用决策树算法在鲍鱼数据集上对年龄进行预测
在上一篇文章中,通過調取sklearn庫中的tree模塊來構建在鮑魚數據集上的決策樹,并對測試集鮑魚的年齡進行預測,但是,通過調庫的方式只能處理數值型的屬性,若數據集中既包含連續型屬性和離散型屬性,則處理起來比較困難。而在本文中,將具體實現決策樹的構建過程,并能分別處理連續型屬性和離散型屬性,最后對?鮑魚數據集?中的鮑魚年齡進行預測。
目錄
前言
一、?數據集
二、步驟
?1.引入庫
?2.讀入數據
?3.數據預處理
?4.計算信息增益
?5.劃分數據集
?6.計算最優劃分屬性
?7.構建決策樹
三.預測
總結
參考文章:
?
前言
?本文將具體實現決策樹的構建過程,并對?鮑魚數據集?中的鮑魚年齡進行預測。
以下是本篇文章正文內容
一、?數據集
訓練集:
?
測試集:
數據集下載:
訓練集:https://pan.baidu.com/s/1f4yf9vlndVar2J4cLqfjDg?????????提取碼:U1S1
測試集:https://pan.baidu.com/s/1QQxqDsyoSrs529H49LLg2g?????????提取碼:U2S2
二、步驟
?1.引入庫
代碼如下:(當然有些沒有用到)
import pandas as pd import matplotlib.pyplot as plt import numpy as np from sklearn.metrics import precision_score from scipy.stats import multivariate_normal from mpl_toolkits.mplot3d import Axes3D import copy?2.讀入數據
代碼如下:
# 讀取數據 train_datas=pd.read_csv(path1,header=None) test_datas=pd.read_csv(path2,header=None)path為文件路徑
?3.數據預處理
#轉換成列表 train_data=np.array(train_datas[1:][:]).tolist() label=train_datas[:1][:] labels=np.array(label).tolist()[0][:-1] labelProperties = [0, 1, 1, 1, 1, 1, 1, 1] # 屬性的類型,0表示離散,1表示連續test_data=test_datas.drop(columns=[8]) #轉換成列表 testData=np.array(test_data[1:][:]).tolist()?4.計算信息增益
def cal_Ent(dataSet):# 計算Ent(D)# 訓練集大小length=len(dataSet)# 標簽字典Ent_D_dict={}for data in dataSet:label=data[-1]if label in Ent_D_dict:Ent_D_dict[label]+=1else:Ent_D_dict[label]=1Ent_D=0for i in Ent_D_dict.values():odd=i/lengthEnt_D-=odd*np.log2(odd)return Ent_D?5.劃分數據集
(連續型屬性):
# 劃分數據集, axis:按第幾個特征劃分, value:劃分特征的值, LorR: value值左側(小于)或右側(大于)的數據集 def splitDataSet_c(dataSet, axis, value, LorR='L'):retDataSet = []featVec = []if LorR == 'L':for featVec in dataSet:if float(featVec[axis]) < value:retDataSet.append(featVec)else:for featVec in dataSet:if float(featVec[axis]) > value:retDataSet.append(featVec)return retDataSet(離散型屬性):
def splitDataSet(dataSet, axis, value):retDataSet = [] #創建返回的數據集列表for featVec in dataSet: #遍歷數據集if featVec[axis] == value:reducedFeatVec = featVec[:axis] #去掉axis特征reducedFeatVec.extend(featVec[axis+1:]) #將符合條件的添加到返回的數據集retDataSet.append(reducedFeatVec)return retDataSet?6.計算最優劃分屬性
# 選擇最好的數據集劃分方式 def chooseBestFeatureToSplit_c(dataSet, labelProperty):numFeatures = len(labelProperty) # 特征數baseEntropy = cal_Ent(dataSet) # 計算根節點的信息熵bestInfoGain = 0.0bestFeature = -1bestPartValue = None # 連續的特征值,最佳劃分值for i in range(numFeatures): # 對每個特征循環featList = [example[i] for example in dataSet]uniqueVals = set(featList) # 該特征包含的所有值newEntropy = 0.0bestPartValuei = Noneif labelProperty[i] == 0: # 對離散的特征for value in uniqueVals: # 對每個特征值,劃分數據集, 計算各子集的信息熵subDataSet = splitDataSet(dataSet, i, value)prob = len(subDataSet) / float(len(dataSet))newEntropy += prob * cal_Ent(subDataSet)else: # 對連續的特征sortedUniqueVals = list(uniqueVals) # 對特征值排序sortedUniqueVals.sort()listPartition = []minEntropy = float("inf")for j in range(len(sortedUniqueVals) - 1): # 計算劃分點partValue = (float(sortedUniqueVals[j]) + float(sortedUniqueVals[j + 1])) / 2# 對每個劃分點,計算信息熵dataSetLeft = splitDataSet_c(dataSet, i, partValue, 'L')dataSetRight = splitDataSet_c(dataSet, i, partValue, 'R')probLeft = len(dataSetLeft) / float(len(dataSet))probRight = len(dataSetRight) / float(len(dataSet))Entropy = probLeft * cal_Ent(dataSetLeft) + probRight * cal_Ent(dataSetRight)if Entropy < minEntropy: # 取最小的信息熵minEntropy = EntropybestPartValuei = partValuenewEntropy = minEntropyinfoGain = baseEntropy - newEntropy # 計算信息增益print("第%d個特征的增益為%.3f" % (i, infoGain)) #打印每個特征的信息增益if infoGain > bestInfoGain: # 取最大的信息增益對應的特征bestInfoGain = infoGainbestFeature = ibestPartValue = bestPartValueireturn bestFeature, bestPartValue def majorityCnt(classList):classCount = {}for vote in classList: #統計classList中每個元素出現的次數if vote not in classCount.keys():classCount[vote] = 0classCount[vote] += 1sortedClassCount = sorted(classCount.items(), key = operator.itemgetter(1), reverse = True) #根據字典的值降序排序return sortedClassCount[0][0]?7.構建決策樹
# 創建樹, 樣本集 特征 特征屬性(0 離散, 1 連續) def createTree_c(dataSet, labels, labelProperty):print("---------------------------------------------")# print dataSet, labels, labelPropertyclassList = [example[-1] for example in dataSet] # 類別向量if classList.count(classList[0]) == len(classList): # 如果只有一個類別,返回return classList[0]if len(dataSet[0]) == 1: # 如果所有特征都被遍歷完了,返回出現次數最多的類別return majorityCnt(classList)bestFeat, bestPartValue = chooseBestFeatureToSplit_c(dataSet,labelProperty) # 最優分類特征的索引if bestFeat == -1: # 如果無法選出最優分類特征,返回出現次數最多的類別return majorityCnt(classList)if labelProperty[bestFeat] == 0: # 對離散的特征bestFeatLabel = labels[bestFeat]myTree = {bestFeatLabel: {}}labelsNew = copy.copy(labels)labelPropertyNew = copy.copy(labelProperty)del (labelsNew[bestFeat]) # 已經選擇的特征不再參與分類del (labelPropertyNew[bestFeat])featValues = [example[bestFeat] for example in dataSet]uniqueValue = set(featValues) # 該特征包含的所有值for value in uniqueValue: # 對每個特征值,遞歸構建樹subLabels = labelsNew[:]subLabelProperty = labelPropertyNew[:]myTree[bestFeatLabel][value] = createTree_c(splitDataSet(dataSet, bestFeat, value), subLabels,subLabelProperty)else: # 對連續的特征,不刪除該特征,分別構建左子樹和右子樹bestFeatLabel = labels[bestFeat] + '<' + str(bestPartValue)myTree = {bestFeatLabel: {}}subLabels = labels[:]subLabelProperty = labelProperty[:]# 構建左子樹valueLeft = '是'myTree[bestFeatLabel][valueLeft] = createTree_c(splitDataSet_c(dataSet, bestFeat, bestPartValue, 'L'), subLabels,subLabelProperty)# 構建右子樹valueRight = '否'myTree[bestFeatLabel][valueRight] = createTree_c(splitDataSet_c(dataSet, bestFeat, bestPartValue, 'R'), subLabels,subLabelProperty)return myTree Trees = createTree_c(train_data, labels, labelProperties)?運行結果:
三.預測
# 測試算法 def classify_c(inputTree, featLabels, featLabelProperties, testVec):firstStr = list(inputTree.keys())[0] # 根節點firstLabel = firstStrlessIndex = str(firstStr).find('<')if lessIndex > -1: # 如果是連續型的特征firstLabel = str(firstStr)[:lessIndex]secondDict = inputTree[firstStr]featIndex = featLabels.index(firstLabel) # 跟節點對應的特征classLabel = Nonefor key in secondDict.keys(): # 對每個分支循環if featLabelProperties[featIndex] == 0: # 離散的特征if testVec[featIndex] == key: # 測試樣本進入某個分支if type(secondDict[key]).__name__ == 'dict': # 該分支不是葉子節點,遞歸classLabel = classify_c(secondDict[key], featLabels,featLabelProperties, testVec)else: # 如果是葉子, 返回結果classLabel = secondDict[key]else:partValue = float(str(firstStr)[lessIndex + 1:]) # print(testVec[featIndex],partValue)if float(testVec[featIndex]) < partValue: # 進入左子樹if type(secondDict['是']).__name__ == 'dict': # 該分支不是葉子節點,遞歸classLabel = classify_c(secondDict['是'], featLabels,featLabelProperties, testVec)else: # 如果是葉子, 返回結果classLabel = secondDict['是']else:if type(secondDict['否']).__name__ == 'dict': # 該分支不是葉子節點,遞歸classLabel = classify_c(secondDict['否'], featLabels,featLabelProperties, testVec)else: # 如果是葉子, 返回結果classLabel = secondDict['否']return classLabel for i in range(len(testData)):testClass = classify_c(Trees, labels, labelProperties, testData[i])print("第",i,"條測試數據的預測ring為:",testClass)?與調庫的方法進行對比:
參考上一篇文章:
https://blog.csdn.net/qq_53644346/article/details/125101128?spm=1001.2014.3001.55yixaihttps://blog.csdn.net/qq_53644346/article/details/125101128?spm=1001.2014.3001.5501
調庫預測的結果:
?發現結果一樣!
總結
以上就是實現決策樹算法的所有內容,當然以上算法也可以處理其他的數據集,無論是離散屬性和連續屬性都可以處理。
參考文章:
?
?
?
?
?
?
?
?
總結
以上是生活随笔為你收集整理的利用决策树算法在鲍鱼数据集上对年龄进行预测的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用线性回归,岭回归,Lasso回归预测
- 下一篇: 数据分析——“鲍鱼的年龄”数据集