虽然深度学习也属于机器学习,但是一般说机器学习指的是除深度学习以外的传统的旧的机器学习算法。虽然两者几乎是不同的思想逻辑体系,可以直接越过机器学习直接学习深度学习尤其是现在深度学习大行其道。但其实机器学习在数据较少时还是比深度学习来的好用,而且基于规则的算法可解释性也会强一些,所以适合做中间过渡(应该也可以作为深度学习复杂算法的基准模型)。ml通常将问题分解为多个子问题最终合并,而深度学习提倡端到端的解决问题。所以还是有必要简单看一下机器学习。
一般树模型的机器学习方法的底层模型都是决策树。例如随机森林算法的基本单元即是决策树,可用于回归分析,但一般都用于分类,其底层逻辑是基于规则的判断系统。该系统主要有两个指标来减少系统误差,熵和信息增益。
集合D可以分Y类,其熵
某个特征v有X个可能取值,该特征的信息增益
公式不容易看明白可以直接看程序(以watermelon数据集为例):
def readWatermelonDataSet():
ifile = open(".\\res\\watermelondataset.txt")
featureName = ifile.readline() #表头
labels = (featureName.split(' ')[0]).split(',')
lines = ifile.readlines()
dataSet = []
for line in lines:
tmp = line.split('\n')[0]
tmp = tmp.split(',')
dataSet.append(tmp)
return dataSet, labels
d,l=readWatermelonDataSet()
print(*d,sep="\n")
print("feature name:",l)
import numpy as np
#计算信息熵
def calcInformationEntropy(dataSet):
#dataSet最后一列是类别,前面是特征
catalKnV = {}
m = len(dataSet)
for i in range(m):# for every row
#.get()函数:如果没有这个key,就返回默认值;如果有这个key,就返回这个key的value
# print(catalKnV.get(dataSet[i][-1], 0))
catalKnV[dataSet[i][-1]] = catalKnV.get(dataSet[i][-1], 0) + 1;
#count the total recs for each catalog
ent = 0
for key in catalKnV.keys():
p = float(catalKnV[key]) / m
ent = ent - (p * np.log2(p))
return ent
EntD = calcInformationEntropy(d)
print(EntD)
#计算信息增益之前,定义按某个特征划分数据集的函数,之后用于信息增益的计算
def splitAccordColValue(dataSet, axis, value):
"""数据集去掉axis列,并按该列的值分类
dataSet:数据集
axis: 要划分的列下标
value: 该列的值为value时,保留该行数据,得到新的数据集
"""
splitedDataSet = []
for data in dataSet:
if(data[axis] == value):
reduceFeatureVec = data[: axis]
reduceFeatureVec.extend(data[axis + 1 :])
splitedDataSet.append(reduceFeatureVec)
return splitedDataSet
#计算信息增益,然后选择最优的特征进行划分数据集
#信息增益的计算公式:西瓜书P75
def chooseBestFeatureToSplit(dataSet):
#计算整个集合的熵
EntD = calcInformationEntropy(dataSet)
mD = len(dataSet) #行
featureNumber = len(dataSet[0][:]) - 1 #列
maxGain = -1000
bestFeatureIndex = -1
for i in range(featureNumber):
#featureSet = set(dataSet[:][i]) #错误写法:dataSet[:][i]仍然是获取行
featureCol = [x[i] for x in dataSet] #取列表某列的方法!!
featureSet = set(featureCol)
splitedDataSet = []
for av in featureSet:
retDataSet = splitAccordColValue(dataSet, i, av)
splitedDataSet.append(retDataSet)
gain = EntD
for ds in splitedDataSet:
mDv = len(ds)
gain = gain - (float(mDv) / mD) * calcInformationEntropy(ds)
if(bestFeatureIndex == -1):#初始
maxGain = gain
bestFeatureIndex = i
elif(maxGain < gain):#该列信息有增益
maxGain = gain
bestFeatureIndex = i
return bestFeatureIndex
melonBestFeature = chooseBestFeatureToSplit(d)
print(melonBestFeature)
['青绿', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', '是']
['乌黑', '蜷缩', '沉闷', '清晰', '凹陷', '硬滑', '是']
['乌黑', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', '是']
['青绿', '蜷缩', '沉闷', '清晰', '凹陷', '硬滑', '是']
['浅白', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', '是']
['青绿', '稍蜷', '浊响', '清晰', '稍凹', '软粘', '是']
['乌黑', '稍蜷', '浊响', '稍糊', '稍凹', '软粘', '是']
['乌黑', '稍蜷', '浊响', '清晰', '稍凹', '硬滑', '是']
['乌黑', '稍蜷', '沉闷', '稍糊', '稍凹', '硬滑', '否']
['青绿', '硬挺', '清脆', '清晰', '平坦', '软粘', '否']
['浅白', '硬挺', '清脆', '模糊', '平坦', '硬滑', '否']
['浅白', '蜷缩', '浊响', '模糊', '平坦', '软粘', '否']
['青绿', '稍蜷', '浊响', '稍糊', '凹陷', '硬滑', '否']
['浅白', '稍蜷', '沉闷', '稍糊', '凹陷', '硬滑', '否']
['乌黑', '稍蜷', '浊响', '清晰', '稍凹', '软粘', '否']
['浅白', '蜷缩', '浊响', '模糊', '平坦', '硬滑', '否']
['青绿', '蜷缩', '沉闷', '稍糊', '稍凹', '硬滑', '否']
feature name: ['色泽', '根蒂', '敲声', '纹理', '脐部', '触感', '好瓜\n']
0.9975025463691153
3
树的设计,节点用哪个特征,以及判断的依据都是根据信息增益。还有一些其他的指标如信息增益率,基尼指数等
#递归构建决策树
def createTree(dataSet, labels):
classList = [x[-1] for x in dataSet]
print("classlist:",classList)
# if(len(set(classList)) == 1):
# return classList[0]
if(classList.count(classList[0]) == len(classList)):
return classList[0]
elif(len(dataSet[0]) == 1): #所有的属性全部划分完毕
return majorityCnt(classList)
else:
bestFeatureIndex = chooseBestFeatureToSplit(dataSet)
bestFeatureLabel = labels[bestFeatureIndex]
myTree = {bestFeatureLabel: {}}
del(labels[bestFeatureIndex]) #使用完该属性之后,要删除
featureList = [x[bestFeatureIndex] for x in dataSet]
featureSet = set(featureList)
for feature in featureSet:
subLabels = labels[:] #拷贝一份,防止label在递归的时候被修改 (list是传引用调用)
tmpDataSet = splitAccordColValue(dataSet, bestFeatureIndex, feature) #划分数据集
myTree[bestFeatureLabel][feature] = createTree(tmpDataSet, subLabels)
return myTree
tree = createTree(d, l)
print(tree)
sklearn.tree.DecisionTreeClassifier(criterion=’gini/xxx’)中有C 4.5 C4.5C4.5 什么的,使用的是增益率准则,先从候选划分属性中找出信息增益高于平均水平的属性,再从中选择增益率最高的。CART 决策树算法使用基尼指数(Gini index)来选择划分属性。 了解了思想,具体先不管。
随机森林是多个决策树的集合,每个树有各自的标准并且每棵树用,例如n=百分之八十的样本,部分数据集而非全部数据集N训练,最终少数服从多数得到最终的判定结果。回归问题则是采用所有树返回结果的均值。随机森林属于集成学习中的bagging。集成学习有boosting和bagging方法。
随机森林用kaggle的教程和数据集看一下。Car_Evaluation_Dataset
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
import matplotlib.pyplot as plt # data visualization
import seaborn as sns # statistical data visualization
%matplotlib inline
df = pd.read_csv('.\\res\\car_evaluation.csv',header=None)
col_names = ['buying', 'maint', 'doors', 'persons', 'lug_boot', 'safety', 'class']
df.columns = col_names
print(df['class'].value_counts())
# check missing values in variables
df.isnull().sum()
#Declare feature vector and target variable
X = df.drop(['class'], axis=1)#用这些特征去预测类别
y = df['class']#要分辨的类别
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.33, random_state = 42)
df.head()
可以看到数据有6个特征,我们要根据这六个特征对每条数据分类。一共有4类class,是我们要判断的target的值

scikitlearn的随机森林算法中,需要将类别都编码为数值类型。
import category_encoders as ce
from sklearn.preprocessing import OrdinalEncoder
encoder = ce.OrdinalEncoder(cols=['buying', 'maint', 'doors', 'persons', 'lug_boot', 'safety'])
X_train = encoder.fit_transform(X_train)
X_test = encoder.transform(X_test)
X_train.head()

接着就可以训练模型,先用10棵树的森林模型。(代码步骤:先建立10棵树的模型类,将训练数据集填入,再用测试数据集的特征得到测试数据集的结果,最后和实际的结果比较准确性)
from sklearn.ensemble import RandomForestClassifier
# instantiate the classifier
rfc = RandomForestClassifier(n_estimators=10, random_state=0)
# fit the model
rfc.fit(X_train, y_train)
# Predict the Test set results
y_pred = rfc.predict(X_test)
# Check accuracy score
from sklearn.metrics import accuracy_score
print('Model accuracy score with 10 decision-trees : {0:0.4f}'. format(accuracy_score(y_test, y_pred)))
再用100棵树的森林模型,可以发现准确性从0.94提升到0.96, 没什么提升,所以10棵树就足够。
# instantiate the classifier with n_estimators = 100
rfc_100 = RandomForestClassifier(n_estimators=100, random_state=0)
# fit the model to the training set
rfc_100.fit(X_train, y_train)
# Predict on the test set results
y_pred_100 = rfc_100.predict(X_test)
# Check accuracy score
print('Model accuracy score with 100 decision-trees : {0:0.4f}'. format(accuracy_score(y_test, y_pred_100)))
看看那个特征贡献最大
# Creating a seaborn bar plot
sns.barplot(x=feature_scores, y=feature_scores.index)
# Add labels to the graph
plt.xlabel('Feature Importance Score')
plt.ylabel('Features')
# Add title to the graph
plt.title("Visualizing Important Features")
# Visualize the graph
plt.show()

参考:https://blog.youkuaiyun.com/weixin_46075647/article/details/121063862
1222



被折叠的 条评论
为什么被折叠?



