用 机器学习 对车辆进行评估,一起入门机器学习

聊聊天

这几天一直在看机器学习的有关资料,对机器学习产生浓厚的兴趣,然后自己根据机器学习的入门知识,完成了这个简单的车辆评估程序。希望通过我这篇文章给和我一样刚入机器学习的小伙伴一点帮助,同时希望与更多的人交流技术心得,感悟体会。
好,废话不多说。

开发环境

首先,说一下我系统的开发环境 anaconda3, 可以在百度上直接搜索下载,里面包含了很多机器学习所用到的环境和工具,包括python,在这里说明一下,我用的是python3.6,如果有用python2的小伙伴,可能后面的代码需要自己改动一下。
所以,只要安装anaconda3,你就可以拥有开发机器学习所需要的准备的东西,简单方便。

开始

接下来,我就按照我编写代码的思路和步骤,分步来说。

确定算法

在这个程序中,我采用了K-近邻算法,这个算法比较简单,比较适合入门机器学习,所以我采用这种算法进行开发。

K最近邻(k-Nearest Neighbor,KNN)分类算法,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一。该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。

其实就是相当与我们距离计算的公式

这里写图片描述

测试的数据 与 数据集进行求值,比较距离的大小,就能知道该测试数据更接近与什么结果

收集数据

我们对车辆进行评估,终归要有数据作为支撑,在这里我选用比较热门的Car Evaluation Database数据集来开发这个程序。
大家可以通过以下网址进行下载,这个网站也包含了很多经典的数据集。
http://archive.ics.uci.edu/ml/index.php
看到Car Evaluation,点进去找到我们要的数据,把数据复制粘贴下来,保存到文本文件中。

准备数据

我们可以看一下这个数据集的介绍文本,
 buying       v-high, high, med, low
 maint        v-high, high, med, low
 doors        2, 3, 4, 5-more
 persons      2, 4, more
 lug_boot     small, med, big
 safety       low, med, high

这是我们对车辆进行评估的六个特征量,分别是购买价格,维修费用,车门数量,能容纳的人数,后备箱的大小和安全程度。
而这六个特征量就决定了我们评估的四个结果:
unacc --- 不能接受
acc   --- 还可以接受
good  --- 不错
vgood --- 非常好

上述这些信息,都可以通过我们下载的数据集文件中获得。

首先,我们需要从文本文件中把这些数据读出来。
from numpy import *
import operator 
#读数据集并保存到矩阵中
def filecarmatrix(filepath):
    fr = open(filepath)
    arraylines = fr.readlines()
    numberlines = len(arraylines)
    returnMat = zeros((numberlines, 6)) #生成零矩阵
    classLabelVector = []
    index = 0;        
    for line in arraylines:
        line = line.strip()#移除字符串头尾指定的字符(默认为空格)
        listfromline = line.split(',')
        numline = KeyToNum(listfromline) #将数据进行数字化处理
        returnMat[index, :] = numline[0:6]#将特征数据量传入矩阵
        classLabelVector.append(int(numline[-1]))
        index += 1
    return returnMat, classLabelVector
可以看到我这段代码里面有个函数,KeyToNum 这个函数是用来将我们的数据中的字符串转换为数字,因为我们要用矩阵去做相关的运算,所以我们都要把我们的信息用数字去代替,在这里我代替的方案如下(直接附上KeyToNum函数代码)
def KeyToNum(line):
    #将一行的字符串变成对应的数字
    numline = [] 
    switcher = {
            'vhigh'  : 4 ,
            'high'   : 3 ,
            'med'    : 2 ,
            'low'    : 1 ,
            '5more'  : 5 ,
            'more'   : 6 ,
            'small'  : 1 ,
            'big'    : 3 ,
            'unacc'  : 1 ,
            'acc'    : 2 ,
            'good'   : 3 ,
            'vgood'  : 4 ,          
    }
    for key in line:
        numline.append(switcher.get(key, key))
    return numline
现在我们已经将数据读取出来了,并且转换为矩阵的形式。returnMat为我们六个特征量的矩阵,classLabelVector为相对应的车辆评估结果的列表。

归一化数值

因为我们6个特征量的值权重是相等的,而这6个特征的值我需要对其进行归一化,让它们的值都在0-1之间
#归一化处理数据
'''
归一化数值
newValue = (oldValue - min) / (max - min) 
'''
def autoNorm(DataSet):
    minVals = DataSet.min(0 )#将每列中的最小值放在变量minVals中
    maxVals = DataSet.max(0) #将每列中的最小值放在变量minVals中
    ranges = maxVals - minVals #将每列中的最小值放在变量minVals中
    normDataSet = zeros(shape(DataSet)) #生成一个与dataSet相同的零矩阵
    m = DataSet.shape[0] #求出dataSet列长度
    normDataSet = DataSet - tile(minVals, (m, 1)) #求出oldValue - min
    normDataSet = normDataSet / tile(ranges, (m,1)) #求出归一化数值
    return normDataSet, ranges, minVals

分类器制作(K-近邻算法的实现)

就是计算了测试数据相对于测试集中每一组数据的距离,并且根据,k值来选取最近的K的个数据,并且统计k个数据中,出现次数最高的结果,最为测试数据的结果
#分类器制作
def classifyCar(CarData, DataSet, Labels, k):
    DataSetSize = DataSet.shape[0] #获取矩阵第一纬度的长度
    DiffMat = tile(CarData, (DataSetSize, 1)) - DataSet
    sqDiffMat = DiffMat**2
    sqDistances = sqDiffMat**0.5
    distances = sqDistances.sum(axis=1) #矩阵行相加。生成新矩阵
    sortedDistIndicies = distances.argsort() #返回矩阵中的数组从小到大的下标值,返回新矩阵
    classCount = {}  #初始化新字典
    for i in range(k):
        voterLabel = Labels[sortedDistIndicies[i]]
        classCount[voterLabel] = classCount.get(voterLabel, 0) + 1
    sortedClassCount = sorted(classCount.items(), key = operator.itemgetter(1), reverse=True) #排序
    return sortedClassCount[0][0]

测试检验

这里用我们收集到的数据集的10%数据对我们程序进行检验,检验代码如下
#编写测试代码
def CarEvaClassTest():
    basePer = 0.1 #测试基数,选取文本中10%的数据进行测试
    CarDataMat, CarLabels = filecarmatrix(r'D:\Learning\DataSet\car.txt')
    normMat, ranges, minVals = autoNorm(CarDataMat) #进行数据归一化
    m = normMat.shape[0]  #读取数据的列长度
    numTestVecs = int(m * basePer) #确定测试的数量
    errorCount = 0.0  #记录错误数量的变量
    for i in range(numTestVecs):  #进行循环测试
        result = classifyCar(normMat[i, :], normMat[numTestVecs:m, :], \
                             CarLabels[numTestVecs:m], 6) #通过分类器进行判断
        print('the classifer came back with: %d, the real answer is %d' \
              % (result, CarLabels[i]))
        if(result != CarLabels[i]): #比较判断数据和实际数据,并且打印
            errorCount += 1 #错误计数
    print('the total error rate is %f' % (errorCount/float(numTestVecs)))#打印错误率
可以设置不同的k值进行检验,观察错误率的变化,也可以选取不同的数据进行测试检验,观察

编写交互程序

#交互方法
def CarEvaluation():
    resultList = ['unacceptable', 'accept', 'good', 'very good']
    buying = input('How much is this car? Options: vhigh, high, med, low\n')
    maint = input('How much is the maintenance of the car? Options: vhigh, high, med, low\n')
    doors = input('How many doors does this car have? Options: 2, 3, 4, 5more\n')
    person = input('How many people can this car hold? Options:  2, 4, more\n')
    lug_boot = input('How big is the trunk of this car? Options: small, med, big\n')
    safety = input('How safe is the car? Options: low, med, high\n')
    characteristic = [buying, maint, doors, person, lug_boot, safety]
    CarDataMat, CarLabels = filecarmatrix(r'D:\Learning\DataSet\car.txt')
    normMat, ranges, minVals = autoNorm(CarDataMat) #进行数据归一化
    inArr = array(list(map(int, KeyToNum(characteristic)))) #通过map函数将,KeytoNum生成的列表内容全部转换为数字
    print(KeyToNum(characteristic))
    print(inArr)
    Result= classifyCar((inArr - minVals) / ranges, normMat, CarLabels, 6) 
    print('You will probably like this car:', resultList[Result - 1])

整体代码

# -*- coding: utf-8 -*-
"""
k-近邻算法进行车辆评测

Created on Wed Aug  9 14:25:59 2017

@author: cfd
"""
from numpy import *
import operator 
#数据处理
#数字化处理
def KeyToNum(line):
    #将一行的字符串变成对应的数字
    numline = [] 
    switcher = {
            'vhigh'  : 4 ,
            'high'   : 3 ,
            'med'    : 2 ,
            'low'    : 1 ,
            '5more'  : 5 ,
            'more'   : 6 ,
            'small'  : 1 ,
            'big'    : 3 ,
            'unacc'  : 1 ,
            'acc'    : 2 ,
            'good'   : 3 ,
            'vgood'  : 4 ,          
    }
    for key in line:
        numline.append(switcher.get(key, key))
    return numline
#读数据集并保存到矩阵中
def filecarmatrix(filepath):
    fr = open(filepath)
    arraylines = fr.readlines()
    numberlines = len(arraylines)
    returnMat = zeros((numberlines, 6)) #生成零矩阵
    classLabelVector = []
    index = 0;        
    for line in arraylines:
        line = line.strip()#移除字符串头尾指定的字符(默认为空格)
        listfromline = line.split(',')
        numline = KeyToNum(listfromline) #将数据进行数字化处理
        returnMat[index, :] = numline[0:6]#将特征数据量传入矩阵
        classLabelVector.append(int(numline[-1]))
        index += 1
    return returnMat, classLabelVector


#归一化处理数据
'''
归一化数值
newValue = (oldValue - min) / (max - min)
'''
def autoNorm(DataSet):
    minVals = DataSet.min(0 )#将每列中的最小值放在变量minVals中
    maxVals = DataSet.max(0) #将每列中的最小值放在变量minVals中
    ranges = maxVals - minVals #将每列中的最小值放在变量minVals中
    normDataSet = zeros(shape(DataSet)) #生成一个与dataSet相同的零矩阵
    m = DataSet.shape[0] #求出dataSet列长度
    normDataSet = DataSet - tile(minVals, (m, 1)) #求出oldValue - min
    normDataSet = normDataSet / tile(ranges, (m,1)) #求出归一化数值
    return normDataSet, ranges, minVals

#分类器制作
def classifyCar(CarData, DataSet, Labels, k):
    DataSetSize = DataSet.shape[0] #获取矩阵第一纬度的长度
    DiffMat = tile(CarData, (DataSetSize, 1)) - DataSet
    sqDiffMat = DiffMat**2
    sqDistances = sqDiffMat**0.5
    distances = sqDistances.sum(axis=1) #矩阵行相加。生成新矩阵
    sortedDistIndicies = distances.argsort() #返回矩阵中的数组从小到大的下标值,返回新矩阵
    classCount = {}  #初始化新字典
    for i in range(k):
        voterLabel = Labels[sortedDistIndicies[i]]
        classCount[voterLabel] = classCount.get(voterLabel, 0) + 1
    sortedClassCount = sorted(classCount.items(), key = operator.itemgetter(1), reverse=True) #排序
    return sortedClassCount[0][0]

#编写测试代码
def CarEvaClassTest():
    basePer = 0.1 #测试基数,选取文本中10%的数据进行测试
    CarDataMat, CarLabels = filecarmatrix(r'D:\Learning\DataSet\car.txt')
    normMat, ranges, minVals = autoNorm(CarDataMat) #进行数据归一化
    m = normMat.shape[0]  #读取数据的列长度
    numTestVecs = int(m * basePer) #确定测试的数量
    errorCount = 0.0  #记录错误数量的变量
    for i in range(numTestVecs):  #进行循环测试
        result = classifyCar(normMat[i, :], normMat[numTestVecs:m, :], \
                             CarLabels[numTestVecs:m], 6) #通过分类器进行判断
        print('the classifer came back with: %d, the real answer is %d' \
              % (result, CarLabels[i]))
        if(result != CarLabels[i]): #比较判断数据和实际数据,并且打印
            errorCount += 1 #错误计数
    print('the total error rate is %f' % (errorCount/float(numTestVecs)))#打印错误率

#交互方法
def CarEvaluation():
    resultList = ['unacceptable', 'accept', 'good', 'very good']
    buying = input('How much is this car? Options: vhigh, high, med, low\n')
    maint = input('How much is the maintenance of the car? Options: vhigh, high, med, low\n')
    doors = input('How many doors does this car have? Options: 2, 3, 4, 5more\n')
    person = input('How many people can this car hold? Options:  2, 4, more\n')
    lug_boot = input('How big is the trunk of this car? Options: small, med, big\n')
    safety = input('How safe is the car? Options: low, med, high\n')
    characteristic = [buying, maint, doors, person, lug_boot, safety]
    CarDataMat, CarLabels = filecarmatrix(r'D:\Learning\DataSet\car.txt')
    normMat, ranges, minVals = autoNorm(CarDataMat) #进行数据归一化
    inArr = array(list(map(int, KeyToNum(characteristic)))) #通过map函数将,KeytoNum生成的列表内容全部转换为数字
    print(KeyToNum(characteristic))
    print(inArr)
    Result= classifyCar((inArr - minVals) / ranges, normMat, CarLabels, 6) 
    print('You will probably like this car:', resultList[Result - 1])
#print(KeyToNum(['vhigh','vhigh',2,2,'small','low', 'unacc']))

#returnMat, classLabelVector = filecarmatrix(r'D:\Learning\DataSet\car.txt')
#print(returnMat)
#CarEvaClassTest()
CarEvaluation()

总结

由于个人水平所限,有些地方说得不是很明白,大家可以通过百度或者相关书籍去了解学习,同时,如果有什么建议,可以留言给我。谢谢!
  • 6
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值