Python实现K近邻算法<KNN>_分类器

收集数据

数据来源:http://archive.ics.uci.edu/ml/datasets/Haberman%27s+Survival

文本数据如下图所示:

31,65,4,1
33,58,10,1
33,60,0,1
34,59,0,2
34,66,9,2

这是关于乳腺癌已手术患者存活时间(寿命)的样本集,文本文件中共包含306个样本,样本包含的属性有:

1. 患者做手术时的年龄 opAge

2. 患者做手术的年份-1900 opYear,比如1970年做的手术,则opYear属性的值为70

3. 阳性腋窝淋巴结的数目 cellNum

4. 存活时间 status,其中,status等于1表示该患者存活了5年以上,status等于2表示该患者在5年之内死亡。

使用pandas读取文本文件,将数据转换为DataFrame对象:

data = pd.read_table(r"C:\data\Haberman‘s Survival Data.txt", sep=",", header=None, names=[‘opAge‘, ‘opYear‘, ‘cellNum‘, ‘status‘], engine="python")
data1 = data[data[‘status‘] == 1]  # status为1的数据
data2 = data[data[‘status‘] == 2]  # status为2的数据

查看data.shape为(306, 4)

数据散点图

fig = plt.figure(figsize=(16, 12))
ax = fig.gca(projection="3d") #get current axis
ax.scatter(data1[‘opAge‘], data1[‘opYear‘], data1[‘cellNum‘], c=‘r‘, s=100, marker="*", label="survived 5 years or longer") #status为1的样本的散点图
ax.scatter(data2[‘opAge‘], data2[‘opYear‘], data2[‘cellNum‘], c=‘b‘, s=100, marker="^", label="died within 5 year") #status为2的样本的散点图
ax.set_xlabel("operation age", size=15)
ax.set_ylabel("operation year", size=15)
ax.set_zlabel("cell number", size=15)
ax.set_title(‘Haberman\‘s Survival Scatter Plot‘, size=15, weight=‘bold‘)
ax.set_zlim(0, 30)
ax.legend(loc="lower right", fontsize=15)
plt.show()

得到的3D散点图如下所示:

准备数据

KNN算法的原则是:找到距离目标样本距离最近的K个样本,这K个样本中类别出现次数最多的那个类,作为目标样本的类别。这里采用的距离是欧式距离,那么数值较大的属性在衡量距离的时候起的作用较大,这会导致样本距离衡量出现偏差,为了屏蔽这种影响,需要对数据进行归一化:

# 归一化 (x-min)/(max-min)∈[0,1]
def autoNorm(dataSet):
    minVals = samples.min(axis=0) # 按列求最小值,即求每个属性的最小值
    maxVals = samples.max(axis=0) # 求每个属性的最大值
    factors = maxVals - minVals # 归一化因子
    sNum = dataSet.shape[0]  # 数据集的行数,即样本数
    normDataSet = (dataSet - np.tile(minVals, (sNum, 1))) / np.tile(factors, (sNum, 1))  # 先将minVals和归一化因子转换成与dataSet相同的shape,再做减法和除法运算,最终归一化后的数据都介于[0,1]
    return normDataSet

训练算法

划分数据集

采用K折交叉验证的方法来评估分类器的性能,从样本集中随机抽取10%作为测试集testing data,其余的90%用来做10 fold cross validation

testIdxs = random.sample(range(0, len(samples), 1), len(samples) * 1 / 10)  # 随机选取testing data的索引
testingSet = samples.ix[testIdxs]  # 根据索引从样本集中获取testing data
idxs = range(0, len(samples), 1)  # 总的数据索引序列
#以下for循环是从总的数据索引序列中将testing data的索引去除
for i in range(0, len(testIdxs)):
    idxs.remove(testIdxs[i])
trainData = samples.ix[idxs]  # 获取用作训练的数据集

对trainData使用10折交叉验证,首先随机打乱trainData的索引序列random.shuffle(idxs) idxs是引用类型,在执行完remove操作后,idxs已只剩trainData的索引。

k nearest neighbor

采用欧氏距离作为距离评价准则:

#inX: 目标样本
#dataSet: 用来找k nearest neighbor的数据集,labels是该数据集对应的类别标签,dataSet和labels的索引是一一对应的
def classifyKNN(inX, dataSet, labels, k):
    #以下代码是为了防止出现这种情况:dataSet和labels的索引不是从0开始的有序自然数,导致在argsort排序的时候出现错乱,因为argsort排序结果是从0开始的自然数,因此首先需要重置dataSet和labels的索引,使其索引变为依次从0开始自然数。
    nDataSet = zeros((dataSet.shape[0], dataSet.shape[1])) #与dataSet同型的0矩阵
    j = 0
    for i in dataSet.index:
        nDataSet[j] = dataSet.ix[i]
        j += 1
    nDataSet = pd.DataFrame(nDataSet)

    nLabels = zeros(labels.shape[0]) #与labels同型的0向量
    h = 0
    for i in labels.index:
        nLabels[h] = labels.ix[i]
        h += 1

    dataSetNum = nDataSet.shape[0]  # 样本数(DataFrame行数)
    diffMat = tile(inX, (dataSetNum, 1)) - nDataSet #目标样本与参照样本集的差,对应属性相减,结果为与nDataSet同型的矩阵
    sqDiffMat = diffMat ** 2  #平方
    sqDistances = sqDiffMat.sum(axis=1) #矩阵sqDiffMat的列之和,即目标样本与样本集中每个样本对应属性的差值的平方和
    distances = sqDistances ** 0.5 #平方根,欧氏距离,即目标样本与每个样本点的距离
    sortedDistanceIdx = distances.argsort()  # 距离从小到大的索引值,sortedDistanceIdx的索引是从0开始的自然数,sortedDistanceIdx的值表示对应的distance的索引,比如sortedDistanceIdx[0]是150,表示最小的距离在distances中的索引是150
    classCount = {}
    for i in range(k):
        #找出distance最小的k个索引,然后在nLabels中获取其对应类别
        voteLabel = nLabels[int(sortedDistanceIdx[i])]
        classCount[voteLabel] = classCount.get(voteLabel, 0) + 1
    #classCount字典中存放了统计的label和对应的出现次数
    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True) #倒序
    return sortedClassCount[0][0]  #出现次数最大的label

10折交叉验证

一次验证
#返回在该验证集上的错误率
def train(trainingSet, validationSet, kn):
    errorCount = 0
    vIdxs = validationSet.index
    #遍历验证集,对每个样本使用KNN
    for i in range(0, len(validationSet)):
        pred = classifyKNN(validationSet.loc[vIdxs[i], [‘opAge‘, ‘opYear‘, ‘cellNum‘]], trainingSet[[‘opAge‘, ‘opYear‘, ‘cellNum‘]], trainingSet[‘status‘], kn)
        if (pred != validationSet.at[vIdxs[i], ‘status‘]):
            errorCount += 1
    return errorCount / float(len(validationSet))
10次验证

使用10次验证的平均错误率来评价KNN分类器的性能

# dataSet:用来交叉验证的数据集,idxs是对应的索引序列
# k: k折交叉验证
# kn: kn近邻
def crossValidation(dataSet, idxs, k, kn):
    step = len(idxs) / k
    errorRate = 0
    for i in range(k):
        validationIdx = []
        for i in range(i * step, (i + 1) * step):
            validationIdx.append(idxs[i])
        validationSet = dataSet.ix[validationIdx]  # 获得验证集数据
        temp = idxs[:]
        for i in validationIdx:  # 把验证集的索引去除
            temp.remove(i)
        trainingSet = dataSet.ix[temp]  # 获取训练集数据
        errorRate += train(trainingSet, validationSet, kn)
    aveErrorRate = errorRate / float(k)
    return aveErrorRate

测试算法

交叉验证完毕之后,使用全部的trainData,对testingData进行预测

def predict(trainingSet, testingSet, kn):
    errorCount = 0
    for i in range(0, len(testingSet)):
        vIdxs = testingSet.index
        pred = classifyKNN(testingSet.loc[vIdxs[i], [‘opAge‘, ‘opYear‘, ‘cellNum‘]], trainingSet[[‘opAge‘, ‘opYear‘, ‘cellNum‘]], trainingSet[‘status‘], kn)
        print "The prediction label is %s"%(pred)
        print "The real label is %s"%(testingSet.at[vIdxs[i], ‘status‘])
        if (pred != testingSet.at[vIdxs[i], ‘status‘]):
            errorCount += 1
    return errorCount / float(len(testingSet))
print "The cross validation error ratio is %d" %crossValidation(trainData, idxs, 10, 3)
print "The testing data error ratio is %d"%predict(samples,testingSet,3)

运行结果为:

The cross validation error ratio is 0.28
The prediction result is 1
The real result is 1
The prediction result is 1
The real result is 1
The prediction result is 2
The real result is 2
The prediction result is 1
The real result is 1
The prediction result is 1
The real result is 1
The prediction result is 1
The real result is 1
The prediction result is 1
The real result is 1
The prediction result is 1
The real result is 2
The prediction result is 1
The real result is 1
The prediction result is 2
The real result is 1
The prediction result is 1
The real result is 1
The prediction result is 1
The real result is 1
The prediction result is 2
The real result is 2
The prediction result is 1
The real result is 2
The prediction result is 1
The real result is 1
The prediction result is 1
The real result is 1
The prediction result is 1
The real result is 1
The prediction result is 2
The real result is 2
The prediction result is 1
The real result is 1
The prediction result is 1
The real result is 1
The prediction result is 1
The real result is 1
The prediction result is 1
The real result is 2
The prediction result is 1
The real result is 1
The prediction result is 1
The real result is 1
The prediction result is 1
The real result is 1
The prediction result is 1
The real result is 1
The prediction result is 1
The real result is 1
The prediction result is 1
The real result is 1
The prediction result is 1
The real result is 1
The prediction result is 1
The real result is 2
The testing data error ratio is 0.17
时间: 2024-10-08 09:46:20

Python实现K近邻算法<KNN>_分类器的相关文章

K近邻算法-KNN

何谓K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,单从名字来猜想,可以简单粗暴的认为是:K个最近的邻居,当K=1时,算法便成了最近邻算法,即寻找最近的那个邻居.为何要找邻居?打个比方来说,假设你来到一个陌生的村庄,现在你要找到与你有着相似特征的人群融入他们,所谓入伙. 用官方的话来说,所谓K近邻算法,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例(也就是上面所说的K个邻居),这K个实例的多数属于某个类,就把该输入实例分

机器学习(四) 机器学习(四) 分类算法--K近邻算法 KNN (下)

六.网格搜索与 K 邻近算法中更多的超参数 七.数据归一化 Feature Scaling 解决方案:将所有的数据映射到同一尺度 八.scikit-learn 中的 Scaler preprocessing.py import numpy as np class StandardScaler: def __init__(self): self.mean_ = None self.scale_ = None def fit(self, X): """根据训练数据集X获得数据的均

python用K近邻(KNN)算法分类MNIST数据集和Fashion MNIST数据集

一.KNN算法的介绍 K最近邻(k-Nearest Neighbor,KNN)分类算法是最简单的机器学习算法之一,理论上比较成熟.KNN算法首先将待分类样本表达成和训练样本一致的特征向量:然后根据距离计算待测试样本和每个训练样本的距离,选择距离最小的K个样本作为近邻样本:最后根据K个近邻样本判断待分类样本的类别.KNN算法的正确选取是分类正确的关键因素之一,而近邻样本是通过计算测试样本与每个训练集样本的距离来选定的,故定义合适的距离是KNN正确分类的前提. 本文中在上述研究的基础上,将特征属性值

最基础的分类算法-k近邻算法 kNN简介及Jupyter基础实现及Python实现

k-Nearest Neighbors简介 对于该图来说,x轴对应的是肿瘤的大小,y轴对应的是时间,蓝色样本表示恶性肿瘤,红色样本表示良性肿瘤,我们先假设k=3,这个k先不考虑怎么得到,先假设这个k是通过程序员经验得到. 假设此时来了一个新的样本绿色,我们需要预测该样本的数据是良性还是恶性肿瘤.我们从训练样本中选择k=3个离新绿色样本最近的样本,以选取的样本点自己的结果进行投票,如图投票结果为蓝色:红色=3:0,所以预测绿色样本可能也是恶性肿瘤. 再比如 此时来了一个新样本,我们选取离该样本最近

机器学习实战笔记(Python实现)-01-K近邻算法(KNN)

属原创文章,欢迎转载,但请注明出处:http://www.cnblogs.com/hemiy/p/6155425.html 谢谢! 代码及数据-->https://github.com/Wellat/MLaction 1 算法概述 1.1 算法特点 简单地说,k-近邻算法采用测量不同特征值之间的距离方法进行分类. 优点:精度高.对异常值不敏感.无数据输入假定 缺点:计算复杂度高.空间复杂度高 适用数据范围:数值型和标称型 1.2 工作原理 存在一个训练样本集,并且每个样本都存在标签(有监督学习)

K近邻算法——KNN

KNN(K-Nearest Neighbor)算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性.该方法在确定分类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别.所以比较特殊的是它不需要训练,易于理解,易于实现. 在KNN中,通过计算对象间距离来作为各个对象之间的相似性指标,在这里距离一般使用欧氏距离或曼哈顿距离: 整个KNN算法过程可以描述为:输入测试数据,将测试数据的特征与训练集中对应的特

k近邻算法(knn)的并行mpi实现

C语言的串行版本已经前些篇博客给出,现在来讨论给算法的并行程序.该算法有很多种并行的方法,比较好的思路有以下几种. 思路一: 也是最容易想到的,就是将训练集在每台机器上都备份一份,然后将预测数据集平分给每台机器.这种并行方案就相当于这些机器单独计算一份预测集,简单来说有多少台机器,其加速比就是多少,由于不需要进程间的通信,所以是一种理想的并行方法. 思路二: 采用主从模式,让一个进程充当master,其他进程作为slave.master结点读取一条测试数据并广播给所有进程(当然也可以选择所有进程

机器学习随笔01 - k近邻算法

算法名称: k近邻算法 (kNN: k-Nearest Neighbor) 问题提出: 根据已有对象的归类数据,给新对象(事物)归类. 核心思想: 将对象分解为特征,因为对象的特征决定了事对象的分类. 度量每个特征的程度,将其数字化. 所有特征值构成元组,作为该对象的坐标. 计算待检测对象和所有已知对象的距离,选择距离最接近的k个已知对象 (k近邻中的k来源于此). 这k个对象中出现次数最多的分类就是待检测对象的分类. 重要前提: 需要有一批已经正确归类了的对象存在.也就是通常说的训练数据. 重

机器学习经典算法具体解释及Python实现--K近邻(KNN)算法

(一)KNN依旧是一种监督学习算法 KNN(K Nearest Neighbors,K近邻 )算法是机器学习全部算法中理论最简单.最好理解的.KNN是一种基于实例的学习,通过计算新数据与训练数据特征值之间的距离,然后选取K(K>=1)个距离近期的邻居进行分类推断(投票法)或者回归.假设K=1.那么新数据被简单分配给其近邻的类.KNN算法算是监督学习还是无监督学习呢?首先来看一下监督学习和无监督学习的定义.对于监督学习.数据都有明白的label(分类针对离散分布,回归针对连续分布),依据机器学习产