KNN——水果分类

一、数据集处理

1、下载数据集

尽可能的寻找更多苹果,香蕉,杨桃的图片,作为本次的数据集。
在这里插入图片描述

2、统一数据集格式

利用代码统一图片大小和文件格式
统一图片名称,对应种类图片用 名称+下划线+编号 ,便于为图片加上标签

# 统一图片格式
fileList = os.listdir(r"C:\Users\cx\Desktop\work\machine_learning\knn\fruit\carambola")
# 输出此文件夹中包含的文件名称
print("修改前:" + str(fileList)[1])
# 得到进程当前工作目录
currentpath = os.getcwd()
# 将当前工作目录修改为待修改文件夹的位置
os.chdir(r"C:\Users\cx\Desktop\work\machine_learning\knn\fruit\carambola")
# 名称变量
num = 1
# 遍历文件夹中所有文件
for fileName in fileList:
    # 匹配文件名正则表达式
    pat = ".+\ .(jpg|jpeg|JPG)"
    # 进行匹配
    pattern = re.findall(pat, fileName)
    # 文件重新命名
    os.rename(fileName, "carambola_" + str(num) + ".jpg")
    # fileName.resize(256, 256)
    # 改变编号,继续下一项
    num = num + 1
print("***************************************")
# 改回程序运行前的工作目录
# os.chdir(currentpath)
# 刷新
sys.stdin.flush()
# 输出修改后文件夹中包含的文件名称
print("修改后:" + str(os.listdir(r"C:\Users\cx\Desktop\work\machine_learning\knn\fruit\carambola"))[1])

统一文件大小

from PIL import Image
import os
import glob

# 修改图片文件大小
# filename:图片文件名
# outdir:修改后要保存的路径
def convertImgSize(filename, outdir, width=256, height=256):
    img = Image.open(filename)
    try:
        new = img.resize((width, height), Image.BILINEAR)
        p = os.path.basename(filename)
        print(p)
        new.save(os.path.join(outdir, os.path.basename(filename)))
    except Exception as e:
        print(e)

if __name__ == '__main__':
    # 查找给定路径下图片文件,并修改其大小
    for filename in glob.glob('C:/Users/cx/Desktop/work/machine_learning/knn/fruit/carambola/*.jpg"):
        convertImgSize(filename, 'C:/Users/cx/Desktop/work/machine_learning/knn/fruit/carambola')

最后处理好的图片:
在这里插入图片描述

3、加载数据集

为数据集加上标签:苹果,香蕉,杨桃图片对应标签为: apple, banana,carambola
将图片做归一化处理,展平成为一维数组

# 加载数据集
def lode_data():
    data = []
    labels = []
    for img in os.listdir(r"./fruit"):
        # 为图片贴标签
        label = img.split("_")
        labels.append(label[0])

        #图片归一化 
        img = "./fruit/" + img
        img = cv2.imread(img, 1)
        img = (img - np.min(img)) / (np.max(img) - np.min(img))                    
        data.append(img.flatten())
    data = np.array(data)
    labels = np.array(labels)
 
    return data, labels

二、分离训练集、验证集

我这里就直接用封装好的方法,将上面加载好的验证集,分成30%验证集,70验证集。

data, labels = lode_data()
# 从样本中随机抽取30% 做验证集, 其余70% 做训练集
train_data,test_data,train_labels,test_labels = train_test_split(data, labels, test_size = 0.30, random_state = 20, shuffle = True)        

三、定义KNN模型

KNN模型定义都有一个套路,按照对应的步骤就能很好实现出来,具体步骤包括:

  • 计算欧式距离
  • 按照计算距离排序
  • 获取前k个样本标签
  • 返回出现次数最多标签

1、计算欧式距离

将图片展开成为一维向量之后,可以计算测试集里面每一张图片与其他图片的欧式距离。对应每一个像素点先求差,在求平方和,最后开方就得到了欧式距离。

    dis = (np.tile(test_img, (data .shape[0], 1)) - data) ** 2
    dis_sq = dis.sum(axis=1)
    dis_res = dis_sq ** 0.5

2、对所有距离排序

利用argsort()函数对所有距离排序,返回对应的索引

 dis_sort = dis_res.argsort()

3、获取前k个样本的标签

构造一个分类器,遍历距离最短的前k个索引,根据索引得到对应的标签,最后将标签全部放到分类器中。

    classcount={}
    for i in range(k):
        # 取距离最近的前k个,获取对应标签
        vote_label = labels[dis_sort[i]]
        classcount[vote_label] = classcount.get(vote_label, 0) + 1

4、返回出现次数最多的标签

将所有标签降序排序,第一个就是出现次数最多的标签。

    # 将获取的标签进行降序排序
    sorted_classcount = sorted(classcount.items(), key = operator.itemgetter(1), reverse = True)
    # 返回出现次数最多的标签
    return sorted_classcount[0][0]

5、KNN算法代码

# knn算法实现
def knn(test_img, data , labels, k):
    # 计算欧氏距离
    dis = (np.tile(test_img, (data .shape[0], 1)) - data) ** 2
    dis_sq = dis.sum(axis=1)
    dis_res = dis_sq ** 0.5

    # 按照距离依次排序, 返回索引
    dis_sort = dis_res.argsort()

    # 构造分类器
    classcount={}
    for i in range(k):
        # 取距离最近的前k个,获取对应标签
        vote_label = labels[dis_sort[i]]
        classcount[vote_label] = classcount.get(vote_label, 0) + 1
    # 将获取的标签进行降序排序
    sorted_classcount = sorted(classcount.items(), key = operator.itemgetter(1), reverse = True)
    # 返回出现次数最多的标签
    return sorted_classcount[0][0]

四 、测试模型

在上面KNN模型定义中,输入一个测试数据,会返回一个距离为K中,出现次数最多的标签。用测试集里面每一个测试样本,利用模型返回的标签和自己正确的标签比对,最终可以得到正确率。K的值从0遍历到20,输出每个K值对应的正确率。

# 获取标签匹配成功的概率
def test_all(train_data, train_labels, test_data, test_labels, k):
    right = 0
    for i in range(len(test_data)):
        if knn(test_data[i], train_data, train_labels, k) == test_labels[i]:
            right+=1
    return right/len(test_data)

# 训练
def  train():
    right = []
    data, labels = lode_data()

    # 从样本中随机抽取20% 做验证集, 其余80% 做训练集
    for k in range(0, (len(labels)-1)):
        train_data,test_data,train_labels,test_labels = train_test_split(data, labels, test_size = 0.20
                                                 ,random_state = 20, shuffle = True) 
        right.append(test_all(train_data, train_labels, test_data, test_labels, k + 1))
        i = str(k + 1) 
        print('K = {}, 正确率 = {}'.format(i, right[k]))

    plt.plot( range(len(test_data) + 1) , right)
    plt.show()

train()

1、K取值和正确率曲线

在这里插入图片描述

2、结果分析

取几个比较具有代表性的k值分析:

  1. K = 5 时 ,训练的准确率只有0.59,导致这个结果原因可能是两张图片背景太简单,有很多空白的地方 ,而且两类水果形状和大小相似 。这些空白的地方灰度值十分相似,最后不同水果算出的欧式距离很小。在K值比较小时,训练集两张图片之间具有特殊性,导致结果不是很理想。例如下面两张图片,框出的大概就是图片大小,有很多灰度相同的空白区域,下面两种不同水果但距离比较小:
    在这里插入图片描述

  2. K = 40 时,正确率为0.72。我的三种水果的样本集数量不是完全相等,苹果50张左右、杨桃40张左右、香蕉60张左右。最后k值太大时,在距离为k的测试结果中,样本数量比较多的标签更容易被统计。而且有的图片背景比较模糊,两张图片差异比较大,最后相同水果算出的距离比较大,导致匹配概率比较小。例如下面同种水果距离比较大:
    在这里插入图片描述

  3. K = 30时,正确率为0.81。由于三种数据集总体上的差异比较明显,又避免了k值比较小时出现的不同水果算出的欧式距离很小、相同水果算出欧式距离比较大的情况,最后测试结果比较理想。不同水果总体差异明显:在这里插入图片描述

  • 7
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
### 回答1: KNN(K-Nearest Neighbors)是一种常用的机器学习算法,可以应用于水果分类问题。在使用KNN进行水果分类时,我们需要明确以下步骤: 1. 数据收集:首先,我们需要收集有关水果数据集。这些数据集包括水果的特征,例如颜色、形状、质地等。 2. 数据预处理:对于KNN算法,数据预处理是非常重要的一步。我们需要将数据集分为训练集和测试集,并进行特征工程以准备数据。 3. 特征选择:选择适当的特征对于KNN算法的性能至关重要。我们可以使用一些特征选择的方法,例如相关性分析、主成分分析等。 4. 计算距离:KNN基于距离来进行分类。我们需要计算未知样本与训练样本之间的距离。常用的距离度量方法包括欧氏距离、曼哈顿距离等。 5. 确定K值:K值代表KNN算法中选择的邻居数量。我们需要根据实际情况选择合适的K值。 6. 进行分类:将未知样本的特征与训练样本进行比对,选取距离最近的K个样本。根据这K个样本的类别,使用少数服从多数的原则确定未知样本的分类。 7. 评估模型:最后,我们需要评估KNN分类器的性能。可以使用一些评估指标,例如准确率、召回率等来评估模型的效果。 总之,使用KNN进行水果分类的过程包括数据收集、数据预处理、特征选择、计算距离、确定K值、进行分类以及评估模型的步骤。KNN是一种简单而有效的分类算法,适用于许多分类问题。 ### 回答2: KNN(K最近邻)是一种常见的机器学习算法,可用于水果分类问题。基本原理是通过测量不同实例之间的距离,将某个未标记的实例分类到距离最近的已标记实例的类别。 为了使用KNN进行水果分类,首先我们需要构建一个数据集数据集应包含水果的多个特征,例如大小、颜色、纹理等。每个样本应包含这些特征以及其所属的水果类别。 接下来,我们需要将数据集拆分为训练集和测试集。训练集用于训练KNN模型,测试集用于评估模型的性能。 训练阶段包括以下步骤: 1. 选择一个合适的K值,即选择最近邻的数量。这可以通过交叉验证等方法来确定。 2. 计算训练集中每个样本与其他样本的距离,通常使用欧氏距离或曼哈顿距离进行计算。 3. 根据距离值对样本进行排序,选择距离最近的K个样本。 4. 根据K个样本的类别,通过多数投票的方式确定未标记实例的类别。 测试阶段包括以下步骤: 1. 计算测试集中每个样本与训练集中样本的距离。 2. 选取最近的K个样本。 3. 根据K个样本的类别进行多数投票,确定测试实例的类别。 4. 与测试集的真实类别进行比较,评估模型的性能。 在进行水果分类时,可以选择不同的特征和K值,以达到最佳的分类效果。需要注意的一点是,特征选择应具有对分类有影响的能力,而K值的选择应考虑到数据集的大小和样本分布等因素。 总之,使用KNN进行水果分类的步骤包括数据集构建、训练模型和测试模型。通过调整特征和K值,我们可以得到较高的分类准确率。 ### 回答3: 使用knn算法进行水果分类是一种常用的机器学习方法。KNN,即k最近邻算法,采用了简单而直观的理念。首先,收集一定数量已被标记的水果样本数据集,其中包含水果的特征信息(如颜色、形状、大小等),并将其分为不同的类别(如苹果、香蕉、橙子等)。然后,要对一个未知的水果进行分类,首先计算该水果与训练集中所有样本的特征相似度。根据计算结果,选取距离最近的k个样本(即最近邻)。最后,通过统计这k个样本所属类别,确定该未知水果所属的类别。 使用KNN算法进行水果分类的关键是选择合适的k值。k值的选择一般基于经验和交叉验证方法。当k值较小时,模型会更加复杂,容易受到噪声的影响;而当k值较大时,则可能忽略了一些局部的特征,导致分类错误。因此,选择合适的k值是一个权衡的过程。 KNN算法的优点是简单易实现,对待分类样本的分布没有假设,并且可以对多种特征进行分类。然而,KNN算法也存在一些缺点。首先,由于需要计算待分类样本与所有训练样本的距离,计算开销较大;其次,对于不平衡的数据集KNN算法易受到主导类别的影响;另外,对于特征空间的维度较高的情况下,由于“维度灾难”的问题,KNN性能会下降。 总之,使用KNN算法进行水果分类是一种简单而有效的方法,可以根据水果的特征将其正确分类到相应的类别中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我没得冰阔落.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值