python学习day-11 机器学习-监督学习-分类-决策树&临近取样KNN
一、Dtree理论部分
- 准确率
- 速度
- 强壮行 当有噪声或者几个值缺失时,还能够进行评估
- 可规模性 当数据从指数增长时,变得非常的,算法能够继续工作
- 可解释性
1. 什么是决策树/判定树(decision tree)?
- 树以代表训练样本的单个结点开始
- 如果样本都在同一个类,则该结点成为树叶,并用该类标号
- 否则,算法使用称为信息增益的基于熵的度量作为启发信息,选择能够最好地将样本分类的属性(步骤6)。该属性成为该结点的“测试”或“判定”属性在算法的该版本中,
- 所有的属性都是分类的,即离散值。连续属性必须离散化。
- 对测试属性的每个已知的值,创建一个分枝,并据此划分样本
- 算法使用同样的过程,递归地形成每个划分上的样本判定树。一旦一个属性出现在一个结点上,就不必该结点的任何后代上考虑它
- 递归划分步骤仅当下列条件之一成立停止:
- (a) 给定结点的所有样本属于同一类
- (b) 没有剩余属性可以用来进一步划分样本在此情况下,使用多数表决
- 这涉及将给定的结点转换成树叶,并用样本中的多数所在的类标记它。替换地,可以存放结
- 点样本的类分布。
- (c) 分枝
- test_attribute = a i 没有样本在这种情况下,以 samples 中的多数类
- 创建一个树叶
二、决策树的应用---代码应用
1.首先利用python里机器学习的库 scikit-learn
简单高效的数据挖掘和机器学习分析对所有用户开放,根据不同需求高度可重用性基于Numpy, SciPy和matplotlib开源,商用级别:获得 BSD许可
from sklearn.feature_extraction import DictVectorizer import csv from sklearn import tree from sklearn import preprocessing from sklearn.externals.six import StringIO # Read in the csv file and put features into list of dict and list of class label allElectronicsData = open(r'C:\Users\222\PycharmProjects\Dtree\AllElectronics.csv', 'rb') reader = csv.reader(allElectronicsData) headers = reader.next()
# Read in the csv file and put features into list of dict and list of class label
allElectronicsData = open(r'C:\Users\222\PycharmProjects\Dtree\AllElectronics.csv', 'rt')
reader = csv.reader(allElectronicsData)
headers = next(reader)
1.For version 3.2 and above 2.Change:reader.next() To: next(reader) 3.then I get another error:
_csv.Error: iterator should return strings, not bytes (did you open the file in text mode?)
4.Edit: Figured it out needed to : change rb to rt
来自 https://blog.csdn.net/qing101hua/article/details/77002444
4.而我又遇到了问题
ValueError: Expected 2D array, got 1D array instead:
根据提示找到问题所在为 调用svc.predict()处出现问题
查看svc.predict的使用方法
print(help(svc.predict))
修改前
test_prediction = svc.predict(hog_features.reshape)
修改后
test_prediction = svc.predict(hog_features.reshape(1,-1))
执行后错误消失
5.决策树的代码
from sklearn.feature_extraction import DictVectorizer #导入模块
import csv
from sklearn import tree
from sklearn import preprocessing
from sklearn.externals.six import StringIO
# Read in the csv file and put features into list of dict and list of class label
allElectronicsData = open(r'C:\Users\222\PycharmProjects\Dtree\AllElectronics.csv', 'rt') #打开文件
reader = csv.reader(allElectronicsData) #读取文件
headers = next(reader) #将第一行的标题读取
print(headers)
featureList = [] #特征列表和标签列表
labelList = []
for row in reader: #遍历第一列到倒数第二列 生成字典
labelList.append(row[len(row)-1])
rowDict = {}
for i in range(1, len(row)-1):
rowDict[headers[i]] = row[i]
featureList.append(rowDict)
print(featureList) #形成一个大字典 方便后续进行数据转换
# Vetorize features
vec = DictVectorizer()
dummyX = vec.fit_transform(featureList) .toarray() #转换的特征数据顺序与初始数据对上 01010011。。。。
print("dummyX: " + str(dummyX))
print(vec.get_feature_names())
print("labelList: " + str(labelList)) #标签
# vectorize class labels
lb = preprocessing.LabelBinarizer() #最终y 的结果
dummyY = lb.fit_transform(labelList)
print("dummyY: " + str(dummyY))
# Using decision tree for classification
# clf = tree.DecisionTreeClassifier()
clf = tree.DecisionTreeClassifier(criterion='entropy')#利用库里的算法对x y 处理
clf = clf.fit(dummyX, dummyY)
print("clf: " + str(clf))
# Visualize model(graphviz要自己下载 )
with open("allElectronicInformationGainOri.dot", 'w') as f:
f = tree.export_graphviz(clf, feature_names=vec.get_feature_names(), out_file=f)
oneRowX = dummyX[0, :]
print("oneRowX: " + str(oneRowX))
newRowX = oneRowX
newRowX[0] = 0
newRowX[2] = 1
print("newRowX: " + str(newRowX))
predictedY = clf.predict(newRowX.reshape(1,-1))
print("predictedY: " + str(predictedY))
结果
6.需要安装graphviz 是一个可视化的软件
转化dot文件至pdf可视化决策树:dot -Tpdf iris.dot -o outpu.pdf
7.Anaconda去官网下载这个,并添加到环境变量中,和加入到pydev里选取编译器
KNN临近取样
一、理论知识
1.1 Cover和Hart在1968年提出了最初的邻近算法
1.2 分类(classification)算法
1.3 输入基于实例的学习(instance-based learning), 懒惰学习(lazy learning)
2. 算法详述
2.1 步骤:
为了判断未知实例的类别,以所有已知类别的实例作为参照
选择参数K
计算未知实例与所有已知实例的距离
选择最近K个已知实例
根据少数服从多数的投票法则(majority-voting),让未知实例归类为K个最邻近样本中最多数的类别
2.2 细节:关于K
关于距离的衡量方法:
3.2.1 Euclidean Distance 定义
其他距离衡量:余弦值(cos), 相关度 (correlation), 曼哈顿距离 (Manhattan distance)
3. 算法优缺点:
3.1 算法优点 简单 易于理解 容易实现 通过对K的选择可具备丢噪音数据的健壮性
3.2 算法缺点
x没问题 但是y就出现问题了
需要大量空间储存所有已知实例
算法复杂度高(需要比较所有已知实例与要分类的实例)
当其样本分布不平衡时,比如其中一类样本过大(实例数量过多)占主导的时候,新的未知实例容易被归类为这个主导样本,因为这类样本实例的数量过大,但这个新的未知实例实际并木接近目标样本
4. 改进版本
考虑距离,根据距离加上权重
比如: 1/d (d: 距离)
二、代码
运行程序时我出现了以下问题
1. IndentationError:expected an indented block错误解决
Python语言是一款对缩进非常敏感的语言,给很多初学者带来了困惑,即便是很有经验的Python程序员,也可能陷入陷阱当中。最常见的情况是tab和空格的混用会导致错误,或者缩进不对,而这是用肉眼无法分别的。
在编译时会出现这样的错IndentationError:expected an indented block说明此处需要缩进,你只要在出现错误的那一行,按空格或Tab(但不能混用)键缩进就行。
2. Python 中 'unicodeescape' codec can't decode bytes in position XXX: trun错误解决方案
类似的错误,原来是图片路径写的 有问题,错误代码如下
loadDataset('C:\Users\222\PycharmProjects\KNN\irisdata.txt', split, trainingset, testset)
修改为
loadDataset('C:\Users\\222\P\ycharmProjects\\KNN\\irisdata.txt', split, trainingset, testset)
loadDataset(r'C:\Users\222\PycharmProjects\KNN\irisdata.txt', split, trainingset, testset)
loadDataset(r'C:/Users/222/PycharmProjects/KNN/irisdata.txt', split, trainingset, testset)
3. AttributeError: 'dict' object has no attribute 'iteritems'
Python3.5中:iteritems变为items
4.此csv文件并非二进制文件, 只是一个文本文件。就要将rb改为rt
with open(filename, 'rt') as csvfile:
with open(filename, 'rb') as csvfile:
代码实现
import csv
import random
import math
import operator
#将要用的数据集装载进来
def loadDataset(filename, split, trainingSet = [], testSet = []): #文件名,分割第几行,训练集,测试集
with open(filename, 'rt') as csvfile: #读取文件所有行数
lines = csv.reader(csvfile) #转化为列表
dataset = list(lines) #遍历
for x in range(len(dataset)-1):
for y in range(4):
dataset[x][y] = float(dataset[x][y])
if random.random() < split: #出现一个随机的行数如果小于分割的位置 就把它加入训练集,否则就加到测试集
trainingSet.append(dataset[x])
else:
testSet.append(dataset[x])
#计算距离
def euclideanDistance(instance1, instance2, length): #输入两个实例和维度,返回距离值
distance = 0
for x in range(length):
distance += pow((instance1[x]-instance2[x]), 2)
return math.sqrt(distance)
#返回最近的k个邻居
def getNeighbors(trainingSet, testInstance, k):
distances = []
length = len(testInstance)-1
for x in range(len(trainingSet)):
#testinstance
dist = euclideanDistance(testInstance, trainingSet[x], length)
distances.append((trainingSet[x], dist))
#distances.append(dist)
distances.sort(key=operator.itemgetter(1)) #从小到大进行排序
neighbors = []
for x in range(k):
neighbors.append(distances[x][0])
return neighbors
#根据少数服从多数的法则
def getResponse(neighbors):
classVotes = {}
for x in range(len(neighbors)):
response = neighbors[x][-1]
if response in classVotes:
classVotes[response] += 1
else:
classVotes[response] = 1
sortedVotes = sorted(classVotes.items(), key=operator.itemgetter(1), reverse=True) #按降序排列
return sortedVotes[0][0]
#准确率是多少
def getAccuracy(testSet, predictions):
correct = 0
for x in range(len(testSet)):
if testSet[x][-1] == predictions[x]:
correct += 1
return (correct/float(len(testSet)))*100.0
def main():
#prepare data
trainingSet = []
testSet = []
split = 0.67
loadDataset('C:/Users/王孝义/PycharmProjects/KNN/irisdata.txt', split, trainingSet, testSet)
print ('Train set: ' + repr(len(trainingSet)))
print ('Test set: ' + repr(len(testSet)))
#generate predictions
predictions = []
k = 3
for x in range(len(testSet)):
# trainingsettrainingSet[x]
neighbors = getNeighbors(trainingSet, testSet[x], k)
result = getResponse(neighbors)
predictions.append(result)
print ('>predicted=' + repr(result) + ', actual=' + repr(testSet[x][-1]))
print ('predictions: ' + repr(predictions))
accuracy = getAccuracy(testSet, predictions)
print('Accuracy: ' + repr(accuracy) + '%')
if __name__ == '__main__':
main()
输出结果