本章内容
================================
(一)什么是k-近邻分类算法
(二)怎样从文件中解析和导入数据
(三)使用Matplotlib创建扩散图
(四)对数据进行归一化
=================================
(一) 什么是k-近邻分类算法
简单地说,k-近邻算法采用测量不同特征值之间的距离方法进行分类,k-近邻是一种有监督的分类算法。
k-近邻的工作原理:存在一个样本数据集,也称之为训练样本集,并且样本集中的每个数据都存在标签,即每个样本所属的类别。输入没有标签的新数据,将新数据的每个特征与样本数据集中的每一个数据的特征进行比较,然后提取与新数据最相似的k个样本数据集,根据这k个样本数据集的类别标签,这k个样本数据中出现最多的类别即为新数据的类别标签。
举例:根据表中提供的信息,求最后一部电影的电影类型?下图是每部电影的打斗镜头数、接吻镜头数以及电影评估类型
本文结合k-近邻分类算法的一般步骤,利用python代码实现。
k-近邻分类算法的一般步骤:
(1)导入数据
from numpy import *
import operator def createDataSet():
'''
Use two arrays represent the information of chart.
'''
group = array([[3,104],[2,100],[1,81],[101,10],[99,5],[98,2]])
label = ['love','love','love','action','action','action']
return group, label
(2)分类器的实现
def classify(x, dataSet, label, k):
'''
The kNN classifier.
''' '''
Compute the distance
'''
# shape return [m,n]
# m is the row number of the array
# n is the column number of the array
dataSetSize = dataSet.shape[0]
# tile can expand a vector to an array
# (dataSetSize, 1) expand row and column
# x = [1,3]
# print(tile(x,(3,1)))
# result [[1,3],[1,3],[1,3]]
diffMat = tile(x, (dataSetSize, 1)) - dataSet
sqDiffMat = diffMat ** 2
# sqDistance is a 1 x m array
sqDistance = sqDiffMat.sum(axis=1)
distances = sqDistance ** 0.5 '''
Choose the k samples, according to the distances
'''
sortedDistIndicies = distances.argsort()
classCount = {}
for i in range(k):
voteIlabel = label[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1 '''
Sort and find the max class
'''
sortedClassCount = sorted(classCount.iteritems(),
key = operator.itemgetter(1),
reverse = True)
return sortedClassCount[0][0]
(3)测试新数据
group , labels = createDataSet()
x = [18, 90]
print(classify(x,group,labels,3))
(4)实验结果
love
===========================================
(二)怎样从文件中解析和导入数据
一般原始的数据存放在文本文件中,每个样本占据一行,N个样本就有N行.每个样本数据有n个特征,最后一列为样本的类别。
怎样将数据从文件中读取到数组中呢?
def file2matrix(filename, n):
f = open(filename)
arrayOLines = f.readlines()
numberOfLines = len(arrayOLines)
returnMat = zeros((numberOfLines,n))
classLabelVector = []
index = 0
for line in arrayOLines:
line = line.strip()
listFormLine = line.split('\t')
returnMat[index,:] = listFormLine[0:n]
classLabelVector.append(int(listFormLine[-1]))
index += 1
return returnMat, classLabelVector
==========================================
(三)使用Matplotlib创建散点图分析数据
Matplotlib可以将数据的两种类型的特征表示在一张2D的图中。
import matplotlib.pyplot as plt
from numpy import *
datmax = array([[2,3],[4,5]])
plt.scatter(datmax[:,0],datmax[:,1])
plt.xlabel('Feature0')
plt.ylabel('Feature1')
plt.show()
结果如下:
============================================
(四)归一化数值
如下图所示,我们很容易发现,使用欧式距离衡量数据之间的相似度,特数字差值最大的特征对计算结果影响最大,就如下图,每年获得的飞行常客里程数这个特征对计算结果的影响远大于其他两个特征的影响。若训练过程中,我们认为每一特征是等权重的。
在处理这种不同取值范围的特征值时,我们通常采用的方法是将数值归一化,将取值范围处理为[0,1]或[-1,1]。
本文以最大最小进行归一化:
from numpy import * def autoNorm(dataSet):
'''
Use Max-min method to normalize the feature value
''' # find the min value of each feature
# minVals is a 1 X m (m is the number of feature)
minVals = dataSet.min(0)
# find the max value of each feature
# maxVals is a 1 X m (m is the number of feature)
maxVals = dataSet.max(0)
ranges = maxVals - minVals
normDataSet = zeros(shape(dataSet))
# the number of samples
m = dataSet.shape[0]
normDataSet = dataSet - tile(minVals,(m,1))
normDataSet = normDataSet / tile(ranges,(m,1))
20 return normDataSet, minVals, ranges
测试数据:
10%作为测试集
90%作为训练集
def datingClassTest():
'''
Test
'''
# hold out 10%
hoRatio = 0.10
# load dataSet file
datingDataMat, datingLabels = file2matrix('datingTestSet2.txt') #load data setfrom file
normMat, ranges, minVals = autoNorm(datingDataMat)
m = normMat.shape[0]
numTestVecs = int(m*hoRatio)
errorCount = 0.0
for i in range(numTestVecs):
classifierResult = classify(normMat[i], normMat[numTestVecs:m], datingLabels[numTestVecs:m], 3)
if (classifierResult != datingLabels[i]):
errorCount += 1.0
print ("the total error rate is: %f" % (errorCount/float(numTestVecs)))
print errorCount,numTestVecs
===========================================
(五)总结
优点:精度高、对异常值不敏感、无数据输入假定。
缺点:计算复杂度高、空间复杂度高。
使用数据范围:数值型和标称型。