0.原理
略
1.数据
http://www.ai-xlab.com/my/course/135
1.课时1-课程资料AllElectronics.csv
是CSV文件,依据已有数据推断是否买电脑
数据属性:age,income,student,credit_rating
标签属性:Yes/No
共14笔数据
2.cart.csv已经处理好数据
2.需要的库
csv,sklearn,graphviz
其中graphviz需要独立安装并自行设置环境变量,否则报错:make sure the Graphviz executables are on your systems’ PATH
3.数据预处理
3.0.读取数据
读取CSV数据可用csv或者Pandas,csv为按行依次读取,且为列表类型
Padas为整体读取,dataframe类型
分别获取标签列表labellist和特征列表featurelist
import csv
from sklearn import tree
from sklearn.feature_extraction import DictVectorizer
from sklearn.preprocessing import LabelBinarizer
def read_csv(filename):
# 获取csv数据
with open(filename, 'r') as f:
labellist = [] # 创建标签列表:是否买电脑
featurelist = [] # 创建属性列表:age,student......
f_reader = csv.reader(f)
f_headers = next(f_reader) # 读取表头
for row in f_reader:
f_dict = {} # 创建字典,{age:senior,student:yes......}
labellist.append(row[-1]) # 添加标签
for i in range(1, 5):
f_dict[f_headers[i]] = row[i] # 添加属性
featurelist.append(f_dict)
return featurelist, labellist
3.1数据处理
将所获得列表编码
1.特征数据编码sklearn 特征提取,dictvectorizer:将字典数据向量化编码,注意这里不能用pandas.get_dummies,TypeError: unhashable type: ‘dict’,即不能处理列表中的字典数据,但结果与get_dummies相同
2.标签数据编码:LabelBinarizer()
def process_f(featurelist, labellist):
# 数据预处理(编码)
# sklearn 特征提取,dictvectorizer:将字典数据向量化编码,注意这里不能用pandas.get_dummies,TypeError: unhashable type: 'dict',即不能处理列表中的字典数据
# 处理feature
dict_v = DictVectorizer()
x_data = dict_v.fit_transform(featurelist).toarray() # 转化为array**
# print(x_data)
# [[0. 0. 1. 0. 1. 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.]......]
# 处理label
# y_data = []
# for i in labellist:
#
# if i == 'yes':
# y_data.append(1)
# else:
# y_data.append(0)
# 或者用sklearn中的LabelBinarizer
label_binary = LabelBinarizer()
y_data = label_binary.fit_transform(labellist)
return x_data, y_data, dict_v, label_binary
4.建立决策树模型并验证
if __name__ == '__main__':
filename = r'C:\Users\hp\Desktop\决策树\AllElectronics.csv'
featurelist, labellist = read_csv(filename)
x_data, y_data, dict_v, label_binary = process_f(featurelist, labellist)
# 测试
# 创建分类决策树完成分类
model = tree.DecisionTreeClassifier(criterion='entropy') # criterion 选择划分节点的标准:默认gini指数(CART),还可entropy(C4.5)
# 输入数据建立模型:
model.fit(x_data, y_data) # 求得数据集的均值方差最大值最小值等
false_count = 0
for i in range(len(x_data)):
x_test = x_data[i]
predict = model.predict(x_test.reshape(1, -1)) # 由于预测时要传入二维数组,因此作转化
print('predict:%s' % (predict))
if predict != y_data[i]:
false_count += 1
print(false_count)
# 可视化
可视化
import graphviz
dot_data = tree.export_graphviz(model, feature_names=dict_v.get_feature_names(), class_names=label_binary.classes_)
# dict_v.get_feature_names()获取特征名称(向量化之后),即逆向量化
# label_binary.classes_获取分类标签名称
graph = graphviz.Source(dot_data)
graph.render('Decision_tree')
结果
同理可对数据2进行处理、可视化
不同的是由于数据均为数字,可以用 np.genfromtxt(filename, delimiter=’,’)进行读取:
data = np.genfromtxt(filename, delimiter=',')
x_data = data[1:, 1:-1] # 多维列表的访问,1:第一行到最后一行,第一列到倒数第二列
y_data = data[1:, -1]
# 创建决策树模型
model = tree.DecisionTreeClassifier() # 默认使用基尼指数计算
# 输入数据创建决策树
model.fit(x_data, y_data)
dot_data = tree.export_graphviz(model,
feature_names=['house_yes', 'house_no', 'single', 'married', 'divorced', 'income'],
class_names=['no', 'yes'])
graph=graphviz.Source(dot_data)
graph.render('cart')
以下为非线性二分类数据:LR-testSet2.txt
shape(x_data)=(118,2),shape(y_data)=(118,)
为了画等高线需要用pyplot.contourf(x,y,z)
但是x,y必须为meshgrid生成的网格矩阵
0.设置数据范围
x_min=x_data[:,0].min()-1#x_min,max,y_min,max是为了画等高线设置的数据范围,保证不出圈
x_max=x_data[:,0].max()+1
y_min=x_data[:,1].min()-1
y_max=x_data[:,1].max()+1
x_range=np.arange(x_min,x_max,0.2)
y_range=np.arange(y_min,y_max,0.2)
其中x_range:(196,),y_range(194,)
1.生成网格矩阵
xx,yy=np.meshgrid(x_range,y_range)#生成网格矩阵
xx:(194,196),yy:(194,196)
meshgird生成两个shape相同的矩阵:
2.预测
z=model.predict(np.c_[xx.ravel(),yy.ravel()])
#ravel()将xx,yy恢复成一维向量
np.c_()行连接
print(np.shape(xx.ravel())) # 38024=194*196,ravel()降维为列向量
print(np.shape(merged_x_data))#(38024, 2)
3.画图
z=z.reshape(xx.shape)# 改为194*196列,使得坐标对应上
cs=plt.contourf(xx,yy,z)
plt.scatter(x_data[:,0],x_data[:,1],c=y_data)
plt.show()
4.精度分析
精度分析使用sklearn.metrics.classification_report
1.训练集精度
z_train = model.predict(x_train) # print(len(z_train))#88
print(classification_report(z_train, y_train)) # 输出精度报告
# precision recall f1-score support
#
# 0.0 1.00 1.00 1.00 46
# 1.0 1.00 1.00 1.00 42
#
# accuracy 1.00 88
# macro avg 1.00 1.00 1.00 88
# weighted avg 1.00 1.00 1.00 88
2.测试集精度
# 利用测试数据作检验
z_test = model.predict(x_test) # print(len(z_test)) # 30
print(classification_report(z_test, y_test)) # 输出精度报告
# precision recall f1-score support
#
# 0.0 0.86 0.80 0.83 15
# 1.0 0.81 0.87 0.84 15
#
# accuracy 0.83 30
# macro avg 0.83 0.83 0.83 30
# weighted avg 0.83 0.83 0.83 30
可以发现训练精度很高:100%
测试精度降低——过拟合
看看决策树图形
可以看到分叉很多,造成过拟合(模型复杂)
因此可以通过剪枝解决过拟合问题:
model(max_depth:树的最大深度,min_samples_split:内部节点再划分所需最小样本数)