读《机器学习:实战》(一):第二章 k-近岭算法

原创
2017/04/04 18:18
阅读数 100

       第二章-(k-近邻算法)
  1.k-近岭算法概述
    概念:采用测量不同特征值之间的距离方法进行分类
    优缺点
      优点:精度高,对异常值不敏感,无数据输入假定
      缺点:计算复杂度高,空间复杂度高
      适用于:标称型和数值型
    工作原理:根据学习样本数据集,学习分类。一个新的数据产生,通过学习样本数据集 的特征比较,然后选取相近(最近岭)的特征值分类标签。一般来说我们只取数据集中 最相近的前k个数据。然后再这k个数据中选择最近岭的分类标签,作为新数据的分类标签
  2.Python中的k-近岭算法:classify(intX,dataSet,labels,k)-->标签有代码 代码1

    

#!coding:utf8

#嗯
from numpy import *


groups = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
labels = array(['A','A','B','B'])
# 结果是4
#print groups.shape[0]
i = tile([0,0],(4,1))-groups
#print i
#print '*'*20
##通过比较发现对数组求平方值,是对数组里的每一项求平方和,比如[1,2]的平方是[1,4]
#m = i**2
#print groups
#print m
#print '*'*20
#print m.sum(axis=1)#axis=1时代表对数组的行求和
#print m.sum(axis=0)#axis=0时代表对数组的列求和
#d = m.sum(axis=1)**0.5
#print d
#argsort方法是对矩阵中正序排序的后的值在原矩阵中的索引值,比如[2,1,0,5]argsort 后是[0,1,2,5] 在原数组中的索引值为[2,1,0,3]
#print d.argsort()
def classify(intX,dataSet,labels,k):
    #获取数据集数组维度
    dataSetSize = dataSet.shape[0]
    #tile 将intX,转换成一个dataSetSize行1列的矩阵,再减去远数组的值,可以得到[[(Ex-Ax),(Ey-Ay)],[(Ex-Bx),(Ey-By)]....]的数组
#    代表着,输入的intX与dataSet的向量点距离点。
    diffMat = tile(intX,(dataSetSize,1))-dataSet
    #对diffMat做平方计算
    sqDuffNat = diffMat**2
    #对sqDuffNat求和再求平方根
    d = (sqDuffNat.sum(axis=1))**0.5
#   以上表示特征值之间的距离,而k-近岭算法就是根据 这个距离来进行比较分类的
#    获得特征值距离正序排序后的索引值
    indexSort = d.argsort()
    #而k-近岭算法的核心是,选取测量点和样本数据特征值距离最近的k条值,然后再在将这k条值进行排序,取最小的的距离。这个距离对应的分类就是测量点的分类
    
    return labels[indexSort[0]]
#    for i in range(k):
        #需要将前k个距离,和分类一一对应。indexSort是d排序过后的索引值,故,indexSort[i]的值在dataSet,和labels中是一一对应的。
        #我们只需将对应的labels放入对应的classCount中即可。其实,不需要排序就可以
        
x = classify([0,0],groups,labels,3)        
print x    
    
    
    
    
    
     


    intX:新的数据
    dataSet:样本学习集
    labels:标签向量
    k:k值
  3.不同特征值之间的距离公式
  4.k-近岭算法:改进约会网站的配对效果-->标签有代码
    虽然,前面的代码可以运行,但是将计算公式导入一个数据发现,有一个值得大小远远大于其他两个数据值的大小
      第二个值远远大于其他俩个值
    这时,为了算法的正确性,我们必须对数据进行归一化
      所谓归一化,就是将所有数据都转化为0~1之间或者-1~1之间的值
      归一化代码 <代码2>

#!coding:utf8



#传入动态参数为list表
def autoOne(*lists):
    #获取动态参数的长度
    num = len(lists)

    for i in range(num):
        maxs = max(lists[i])
        mins = min(lists[i])
        n = maxs - mins
        list1 = lists[i]
        lens = len(list1)
        for j in range(lens):
            list1[j] = (float(list1[j]-mins))/n
#测试通过
#list2 = [1.0,2.0,3.0,4.0,5.0,100.0]
#list3 = [100,200,244,666,108] 
#autoOne(list2,list3)
#print list2
#print list3
 


      考虑到还需要对测量数据进行归一化,故重写了代码 代码3

#!coding:utf8


#传入动态参数为list表
def autoOne(*lists):
    #获取动态参数的长度
    num = len(lists)
    listMins = []
    listn=[]
    for i in range(num):
        maxs = max(lists[i])
        mins = min(lists[i])
        n = maxs - mins
        #将每个数组的最小值和极差放入一个数组中
        listMins.append(float(mins))
        listn.append(float(n))
        list1 = lists[i]
        lens = len(list1)
        for j in range(lens):
            list1[j] = (float(list1[j]-mins))/n
    return listMins,listn
#测试通过
listTest1 = [1.0,2.0,3.0,4.0,5.0,100.0]
listTest2 = [100,200,244,666,108] 
#autoOne(list2,list3)
#print list2
#print list3
#对测试数据进行归一
def testAutoOne(listMins,listn,list):
    num = len(list)
    for i in range(num):
        list[i] = (float(list[i])-float(listMins[i]))/float(listn[i])
    return list
##测试通过
#list = [1.3,101]
#list1,list2 = autoOne(listTest1,listTest2)
#print listTest1
#print listTest2
#
#testAutoOne(list1, list2, list)
#print list
 


    归一化之后的配对代码 代码4

#coding:utf8
#打开相应文件
import matplotlib 
import matplotlib.pyplot as plt
from numpy import *
from com.jinghangzz.k_near import classify
from com.jinghangzz.autoOne import autoOne, testAutoOne
file = open("G:\\datingTestSet2.txt")
#file 读取内容,一行一行的读。
lines=file.readlines()
#新建两个数组分别对应学习样本数据集,和类别
a=[]
b=[]
c=[]
linesArray = []
labels = []
#遍历lines
for line in lines:
    line = line.strip()
    list = line.split('\t')
    #将三个感兴趣特征加入相对应的数组中
    a.append(float(list[0]))
    b.append(float(list[1]))
    c.append(float(list[2]))
    labels.append([float(list[3])])
#对a,b,c数组进行归一化
mins,n = autoOne(a,b,c)
#遍历。然后将a,b,c的值赋给linesArray
for i in range(len(a)):
    linesArray.append([a[i],b[i],c[i]])
    
#将linesArray和labels都转化为numpy数组。
linesArray = array(linesArray)
labels = array(labels)
#对于
#print linesArray
#print linesArray[999,0]
#使用matplotlib画出图形
#fig = plt.figure()
#ax = fig.add_subplot(111)
#ax.scatter(linesArray[:,0],linesArray[:,1],15.0*labels,15.0*labels)
#plt.show()
#print linesArray
#print labels
#导入classify函数,对新的数据点进行分类
list = testAutoOne(mins,n,[40920,8.1,1])
x = classify(list,linesArray,labels,20)
print x







 


    之后,还有对代码的正确率的测试,这里就不写了。我们一般取学习样本数据集的10%作为测试数据,其余90%为学习样本
    如果正确率可以接受,就可以愉快的对你想见的对象进行测试啦。
  5.手写识别系统

        还没看,以后补充

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部