python学习day-11 机器学习-监督学习-分类-决策树&临近取样KNN

一、Dtree理论部分

0. 机器学习中分类和预测算法的评估:
  • 准确率
  • 速度
  • 强壮行   当有噪声或者几个值缺失时,还能够进行评估
  • 可规模性    当数据从指数增长时,变得非常的,算法能够继续工作
  • 可解释性

1. 什么是决策树/判定树(decision tree)?

     
     判定树是一个类似于流程图的树结构:其中,每个内部结点表示在一个属性上的测试,每个分支代表一个属性输出,而每个树叶结点代表类或类分布。树的最顶层是根结点。
 
 
2.  机器学习中分类方法中的一个重要算法
 
3.  构造决策树的基本算法                     
                                                           分支                   根结点                结点
 
 
 
 
     3.1 熵(entropy)概念:
 
          信息和抽象,如何度量?
          1948年,香农提出了 ”信息熵(entropy)“的概念
          一条信息的信息量大小和它的不确定性有直接的关系,要搞清楚一件非常非常不确定的事情,或者          
          是我们一无所知的事情,需要了解大量信息==>信息量的度量就等于不确定性的多少
          比特(bit)来衡量信息的多少
 
          
 
          变量的不确定性越大,熵也就越大
          
 
     3.1 决策树归纳算法 (ID3)
          选择属性判断结点
          信息获取量(Information Gain):Gain(A) = Info(D) - Infor_A(D)
          通过A来作为节点分类获取了多少信息
 
 
           类似,Gain(income) = 0.029, Gain(student) = 0.151, Gain(credit_rating)=0.048
 
          所以,选择age作为第一个根节点
 
          重复。。。一直算下去
 
 
          算法:
  • 树以代表训练样本的单个结点开始
  • 如果样本都在同一个类,则该结点成为树叶,并用该类标号
  • 否则,算法使用称为信息增益的基于熵的度量作为启发信息,选择能够最好地将样本分类的属性(步骤6)。该属性成为该结点的“测试”或“判定”属性在算法的该版本中,
  • 所有的属性都是分类的,即离散值。连续属性必须离散化。
  • 对测试属性的每个已知的值,创建一个分枝,并据此划分样本
  • 算法使用同样的过程,递归地形成每个划分上的样本判定树。一旦一个属性出现在一个结点上,就不必该结点的任何后代上考虑它
  • 递归划分步骤仅当下列条件之一成立停止:
  • (a) 给定结点的所有样本属于同一类
  • (b) 没有剩余属性可以用来进一步划分样本在此情况下,使用多数表决
  • 这涉及将给定的结点转换成树叶,并用样本中的多数所在的类标记它。替换地,可以存放结
  • 点样本的类分布。
  • (c) 分枝
  • test_attribute = a i 没有样本在这种情况下,以 samples 中的多数类
  • 创建一个树叶
 
     3.1 其他算法:
               C4.5:  Quinlan
               Classification and Regression Trees (CART): (L. Breiman, J. Friedman, R. Olshen, C. Stone)
               共同点:都是贪心算法,自上而下(Top-down approach)
               区别:属性选择度量方法不同: C4.5 (gain ratio), CART(gini index), ID3 (Information Gain)
 
     3.2 如何处理连续性变量的属性? 
 
4. 树剪枝叶 (避免overfitting)
     4.1 先剪枝
     4.2 后剪枝
5. 决策树的优点:
     直观,便于理解,小规模数据集有效     
6. 决策树的缺点:
     处理连续变量不好
     类别较多时,错误增加的比较快
     可规模性一般

 

二、决策树的应用---代码应用

1.首先利用python里机器学习的库   scikit-learn

      1.1: 特性:
简单高效的数据挖掘和机器学习分析
对所有用户开放,根据不同需求高度可重用性
基于Numpy, SciPy和matplotlib
开源,商用级别:获得 BSD许可 
     1.2 覆盖问题领域:
          分类(classification), 回归(regression), 聚类(clustering), 降维(dimensionality reduction)
          模型选择(model selection), 预处理(preprocessing)
2,安装
     使用用scikit-learn
     安装scikit-learn: pip, easy_install, windows installer
     安装必要package:numpy, SciPy和matplotlib, 可使用Anaconda (包含numpy, scipy等科学计算常用
     package)
3.在运行程序的时候我会出现
AttributeError: '_csv.reader' object has no attribute 'next'
 
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()

 


输出结果

 

 

 

 

 

 

 

posted @ 2018-07-13 21:56  enough  阅读(478)  评论(0编辑  收藏  举报