Python机器学习之手写KNN算法预测城市空气质量

目录
  • 一、KNN算法简介
  • 二、KNN算法实现思路
  • 三、KNN算法预测城市空气质量
    • 1. 获取数据
    • 2. 生成测试集和训练集
    • 3. 实现KNN算法

一、KNN算法简介

KNN(K-Nearest Neighbor)最邻近分类算法是数据挖掘分类(classification)技术中常用算法之一,其指导思想是"近朱者赤,近墨者黑",即由你的邻居来推断出你的类别。

KNN最邻近分类算法的实现原理:为了判断未知样本的类别,以所有已知类别的样本作为参照,计算未知样本与所有已知样本的距离,从中选取与未知样本距离最近的 K 个已知样本,再根据少数服从多数的投票法则(majority-voting),将未知样本与 K 个最邻近样本中所属类别占比较多的归为一类。

KNN算法的核心思想:寻找最近的 k 个数据,推测新数据的分类

KNN算法的关键:

1.样本的所有特征都要做可比较的量化

若是样本特征中存在非数值的类型,必须采取方法将其量化为数值。例如样本特征中包含颜色,可通过将颜色转换为灰度值来实现距离计算。

2.样本特征要做归一化处理

样本有多个参数,每一个参数都有自己的定义域和取值范围,他们对距离计算的影响不一样,如取值较大的影响力会盖过取值较小的参数。所以样本参数必须做一些 scale 处理,最简单的方式就是所有特征的数值都采取归一化处理。

3.需要一个距离函数以计算两个样本之间的距离

通常使用的距离函数有:欧氏距离、余弦距离、汉明距离、曼哈顿距离等,一般选欧氏距离作为距离度量,但是这是只适用于连续变量。在文本分类这种非连续变量情况下,余弦距离可以用来作为度量。通常情况下,如果运用一些特殊的算法来计算度量的话,K近邻分类精度可显著提高,如运用大边缘最近邻法或者近邻成分分析法。

以计算二维空间中的A(x1,y1)、B(x2,y2)两点之间的距离为例,常用的欧氏距离的计算方法如下图所示:

确定K的值

K值选的太大易引起欠拟合,太小容易过拟合,需交叉验证确定 K 值。

KNN算法的优点:

简单,易于理解,易于实现,无需估计参数,无需训练;

适合对稀有事件进行分类;

特别适合于多分类问题(multi-modal,对象具有多个类别标签), KNN比 SVM 的表现要好。

KNN算法的缺点:

KNN算法在分类时有个主要的不足是:当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的 K 个邻居中大容量类的样本占多数。该算法只计算最近的邻居样本,某一类的样本数量很大,那么或者这类样本并不接近目标样本,或者这类样本很靠近目标样本。无论怎样,数量并不能影响运行结果。可以采用权值的方法(和该样本距离小的邻居权值大)来改进。

该方法的另一个不足之处是计算量较大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的 K 个最近邻点。

二、KNN算法实现思路

要自己动手用 Python 实现 KNN 算法,主要有以下三个步骤:

  • 算距离:给定待分类样本,计算它与已分类样本中的每个样本的距离。
  • 找邻居:圈定与待分类样本距离最近的 K 个已分类样本,作为待分类样本的近邻。
  • 做分类:根据这 K 个近邻中的大部分样本所属的类别来决定待分类样本该属于哪个分类。

三、KNN算法预测城市空气质量

1. 获取数据

数据来源:http://www.tianqihoubao.com/aqi/chengdu-201901.html

对于这种 Table 表格型数据,可以直接用 pandas 的 read_html() 大法,将数据保存到csv,也就不用再写爬虫去解析网页和提取数据了。

# -*- coding: UTF-8 -*-
"""
@File    :spider.py
@Author  :叶庭云
@CSDN    :https://yetingyun.blog.csdn.net/
@http://www.tianqihoubao.com/aqi/beijing-201901.html
"""
import pandas as pd
import logging

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s: %(message)s')

for page in range(1, 13):   # 12个月
    if page < 10:
        url = f'http://www.tianqihoubao.com/aqi/guangzhou-20190{page}.html'
        df = pd.read_html(url, encoding='gbk')[0]
        if page == 1:
            df.to_csv('2019年广州空气质量数据.csv', mode='a+', index=False, header=False)
        else:
            df.iloc[1:,::].to_csv('2019年广州空气质量数据.csv', mode='a+', index=False, header=False)
    else:
        url = f'http://www.tianqihoubao.com/aqi/guangzhou-2019{page}.html'
        df = pd.read_html(url, encoding='gbk')[0]
        df.iloc[1:,::].to_csv('2019年广州空气质量数据.csv', mode='a+', index=False, header=False)

    logging.info(f'{page}月空气质量数据下载完成!')

多爬取几个城市 2019 年历史空气质量数据保存到本地

2. 生成测试集和训练集

import pandas as pd

# 将2019年成都空气质量数据作为测试集
df = pd.read_csv('2019年成都空气质量数据.csv')
# 取质量等级  AQI指数  当天AQI排名  PM2.5 。。。8列数据
# SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame 解决方法
df1 = df[['AQI指数', '当天AQI排名', 'PM2.5', 'PM10', 'So2', 'No2', 'Co', 'O3']].copy()

air_quality = []
# print(df['质量等级'].value_counts())
# 质量等级列数据为字符串  转为为标签  便于判断预测
for i in df['质量等级']:
    if i == "优":
        air_quality.append('1')
    elif i == "良":
        air_quality.append('2')
    elif i == "轻度污染":
        air_quality.append('3')
    elif i == "中度污染":
        air_quality.append('4')
    elif i == "重度污染":
        air_quality.append('5')
	elif i == "严重污染":
        air_quality.append('6')

print(air_quality)
df1['空气质量'] = air_quality

# 将数据写入test.txt
# print(df1.values, type(df1.values)) # <class 'numpy.ndarray'>
with open('test.txt', 'w') as f:
    for x in df1.values:
        print(x)
        s = ','.join([str(i) for i in x])
        # print(s, type(s))
        f.write(s + '\n')
import pandas as pd

# 自定义其他几个城市空气质量数据作为训练集
df = pd.read_csv('2019年天津空气质量数据.csv', encoding='utf-8')
# 取质量等级  AQI指数  当天AQI排名  PM2.5 。。。8列数据
# SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame 解决方法
df1 = df[['AQI指数', '当天AQI排名', 'PM2.5', 'PM10', 'So2', 'No2', 'Co', 'O3']].copy()

air_quality = []
# print(df['质量等级'].value_counts())
# 质量等级列数据为字符串  转为为数字标识
for i in df['质量等级']:
    if i == "优":
        air_quality.append('1')
    elif i == "良":
        air_quality.append('2')
    elif i == "轻度污染":
        air_quality.append('3')
    elif i == "中度污染":
        air_quality.append('4')
    elif i == "重度污染":
        air_quality.append('5')
    elif i == "严重污染":
        air_quality.append('6')

print(air_quality)
df1['空气质量'] = air_quality

# 将数据写入追加写入到train.txt
# print(df1.values, type(df1.values)) # <class 'numpy.ndarray'>
with open('train.txt', 'a+') as f:
    for x in df1.values:
        print(x)
        s = ','.join([str(i) for i in x])
        # print(s, type(s))
        f.write(s + '\n')

3. 实现KNN算法

读取数据集

def read_dataset(filename1, filename2, trainingSet, testSet):
      with open(filename1, 'r') as csvfile:
          lines = csv.reader(csvfile)  # 读取所有的行
          dataset1 = list(lines)       # 转化成列表
          for x in range(len(dataset1)):  # 每一行数据
              for y in range(8):
                  dataset1[x][y] = float(dataset1[x][y])   # 8个参数转换为浮点数
              testSet.append(dataset1[x])    # 生成测试集

      with open(filename2, 'r') as csvfile:
          lines = csv.reader(csvfile)  # 读取所有的行
          dataset2 = list(lines)       # 转化成列表
          for x in range(len(dataset2)):   # 每一行数据
              for y in range(8):
                  dataset2[x][y] = float(dataset2[x][y])  # 8个参数转换为浮点数
              trainingSet.append(dataset2[x])  # 生成训练集

计算欧氏距离

def calculateDistance(testdata, traindata, length):  # 计算距离
      distance = 0  # length表示维度 数据共有几维
      for x in range(length):
          distance += pow((int(testdata[x]) - int(traindata[x])), 2)
      return round(math.sqrt(distance), 3)    # 保留3位小数

找 K 个相邻最近的邻居

def getNeighbors(self, trainingSet, test_instance, k):  # 返回最近的k个边距
      distances = []
      length = len(test_instance)
      # 对训练集的每一个数计算其到测试集的实际距离
      for x in range(len(trainingSet)):
          dist = self.calculateDistance(test_instance, trainingSet[x], length)
          print('训练集:{} --- 距离:{}'.format(trainingSet[x], dist))
          distances.append((trainingSet[x], dist))
      distances.sort(key=operator.itemgetter(1))  # 按距离从小到大排列
      # print(distances)
      neighbors = []
      # 排序完成后取距离最小的前k个
      for x in range(k):
          neighbors.append(distances[x][0])
      print(neighbors)
      return neighbors

计算比例最大的分类

def getResponse(neighbors):   # 根据少数服从多数,决定归类到哪一类
      class_votes = {}
      for x in range(len(neighbors)):
          response = neighbors[x][-1]  # 统计每一个分类的多少  空气质量的数字标识
          if response in class_votes:
              class_votes[response] += 1
          else:
              class_votes[response] = 1
      print(class_votes.items())
      sortedVotes = sorted(class_votes.items(), key=operator.itemgetter(1), reverse=True)  # 按分类大小排序  降序
      return sortedVotes[0][0]    # 分类最大的  少数服从多数   为预测结果

预测准确率计算

def getAccuracy(test_set, predictions):
      correct = 0
      for x in range(len(test_set)):
          # predictions预测的与testset实际的比对  计算预测的准确率
          if test_set[x][-1] == predictions[x]:
              correct += 1
          else:
              # 查看错误预测
              print(test_set[x], predictions[x])

      print('有{}个预测正确,共有{}个测试数据'.format(correct, len(test_set)))
      return (correct / (len(test_set))) * 100.0

run函数调用

# -*- coding: UTF-8 -*-
"""
@Author  :叶庭云
@公众号  :修炼Python
@CSDN    :https://yetingyun.blog.csdn.net/
"""
def run(self):
    training_set = []    # 训练集
    test_set = []        # 测试集
    self.read_dataset('./train_4/test.txt', './train_4/train.txt', training_set, test_set)  # 数据划分
    print('Train set: ' + str(len(training_set)))
    print('Test set: ' + str(len(test_set)))
    # generate predictions
    predictions = []
    k = 7  # 取最近的6个数据
    for x in range(len(test_set)):  # 对所有的测试集进行测试
        neighbors = self.getNeighbors(training_set, test_set[x], k)  # 找到8个最近的邻居
        result = self.getResponse(neighbors)  # 找这7个邻居归类到哪一类
        predictions.append(result)

    accuracy = self.getAccuracy(test_set, predictions)
    print('预测准确度为:  {:.2f}%'.format(accuracy))   # 保留2位小数

运行效果如下:

可以通过增加训练集城市空气质量数据量,调节找邻居的数量k,提高预测准确率。

 

以上就是Python机器学习之手写KNN算法预测城市空气质量的详细内容,更多关于Python KNN 预测空气质量的资料请关注我们其它相关文章!

(0)

相关推荐

  • python实现kNN算法识别手写体数字的示例代码

    1.总体概要 kNN算法已经在上一篇博客中说明.对于要处理手写体数字,需要处理的点主要包括: (1)图片的预处理:将png,jpg等格式的图片转换成文本数据,本博客的思想是,利用图片的rgb16进制编码(255,255,255)为白色,(0,0,0)为黑色,获取图片大小后,逐个像素进行判断分析,当此像素为空白时,在文本数据中使用0来替换,反之使用1来替换. from PIL import Image '''将图片转换成文档,使用0,1分别替代空白和数字''' pic = Image.open('

  • Python机器学习之底层实现KNN

    一.导入数据 借助python自带的pandas库导入数据,很简单.用的数据是下载到本地的红酒集. 代码如下(示例): import pandas as pd def read_xlsx(csv_path): data = pd.read_csv(csv_path) print(data) return data 二.归一化 KNN算法中将用到距离,因此归一化是一个重要步骤,可以消除数据的量纲.我用了归一化,消除量纲也可以用标准化,但是作为新手,我觉得归一化比较简单. 其中最大最小值的计算用到了

  • Python机器学习之KNN近邻算法

    一.KNN概述 简单来说,K-近邻算法采用测量不同特征值之间的距离方法进行分类 优点:精度高.对异常值不敏感.无数据输入假定 缺点:计算复杂度高.空间复杂度高 适用数据范围:数值型和标称2型 工作原理:存在一个样本数据集合,也称为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一个数据与所属分类的对应关系(训练集).输入没有标签的新数据之后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签(测试集).一般来说,我们只选择样

  • python KNN算法实现鸢尾花数据集分类

    一.knn算法描述 1.基本概述 knn算法,又叫k-近邻算法.属于一个分类算法,主要思想如下: 一个样本在特征空间中的k个最近邻的样本中的大多数都属于某一个类别,则该样本也属于这个类别.其中k表示最近邻居的个数. 用二维的图例,说明knn算法,如下: 二维空间下数据之间的距离计算: 在n维空间两个数据之间: 2.具体步骤: (1)计算待测试数据与各训练数据的距离 (2)将计算的距离进行由小到大排序 (3)找出距离最小的k个值 (4)计算找出的值中每个类别的频次 (5)返回频次最高的类别 二.鸢

  • python机器学习基础K近邻算法详解KNN

    目录 一.k-近邻算法原理及API 1.k-近邻算法原理 2.k-近邻算法API 3.k-近邻算法特点 二.k-近邻算法案例分析案例信息概述 第一部分:处理数据 1.数据量缩小 2.处理时间 3.进一步处理时间 4.提取并构造时间特征 5.删除无用特征 6.签到数量少于3次的地点,删除 7.提取目标值y 8.数据分割 第二部分:特征工程 标准化 第三部分:进行算法流程 1.算法执行 2.预测结果 3.检验效果 一.k-近邻算法原理及API 1.k-近邻算法原理 如果一个样本在特征空间中的k个最相

  • python实现KNN分类算法

    一.KNN算法简介 邻近算法,或者说K最近邻(kNN,k-NearestNeighbor)分类算法是数据挖掘分类技术中最简单的方法之一.所谓K最近邻,就是k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表. kNN算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性.该方法在确定分类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别. kNN方法在类别决策时,只与极少量的相邻样本有

  • Python机器学习之手写KNN算法预测城市空气质量

    目录 一.KNN算法简介 二.KNN算法实现思路 三.KNN算法预测城市空气质量 1. 获取数据 2. 生成测试集和训练集 3. 实现KNN算法 一.KNN算法简介 KNN(K-Nearest Neighbor)最邻近分类算法是数据挖掘分类(classification)技术中常用算法之一,其指导思想是"近朱者赤,近墨者黑",即由你的邻居来推断出你的类别. KNN最邻近分类算法的实现原理:为了判断未知样本的类别,以所有已知类别的样本作为参照,计算未知样本与所有已知样本的距离,从中选取与

  • python实现识别手写数字 python图像识别算法

    写在前面 这一段的内容可以说是最难的一部分之一了,因为是识别图像,所以涉及到的算法会相比之前的来说比较困难,所以我尽量会讲得清楚一点. 而且因为在编写的过程中,把前面的一些逻辑也修改了一些,将其变得更完善了,所以一切以本篇的为准.当然,如果想要直接看代码,代码全部放在我的GitHub中,所以这篇文章主要负责讲解,如需代码请自行前往GitHub. 本次大纲 上一次写到了数据库的建立,我们能够实时的将更新的训练图片存入CSV文件中.所以这次继续往下走,该轮到识别图片的内容了. 首先我们需要从文件夹中

  • Python实现识别手写数字 Python图片读入与处理

    写在前面 在上一篇文章Python徒手实现手写数字识别-大纲中,我们已经讲过了我们想要写的全部思路,所以我们不再说全部的思路. 我这一次将图片的读入与处理的代码写了一下,和大纲写的过程一样,这一段代码分为以下几个部分: 读入图片: 将图片读取为灰度值矩阵: 图片背景去噪: 切割图片,得到手写数字的最小矩阵: 拉伸/压缩图片,得到标准大小为100x100大小矩阵: 将图片拉为1x10000大小向量,存入训练矩阵中. 所以下面将会对这几个函数进行详解. 代码分析 基础内容 首先我们现在最前面定义基础

  • Python实现识别手写数字大纲

    写在前面 其实我之前写过一个简单的识别手写数字的程序,但是因为逻辑比较简单,而且要求比较严苛,是在50x50大小像素的白底图上手写黑色数字,并且给的训练材料也不够多,导致准确率只能五五开.所以这一次准备写一个加强升级版的,借此来提升我对Python处理文件与图片的能力. 这次准备加强难度: 被识别图片可以是任意大小: 不一定是白底图,只要数字颜色是黑色,周围环境是浅色就行: 加强识别手写数字的逻辑,提升准确率. 因为我还没开始正式写,并且最近专业课程学习也比较紧迫,所以可能更新的比较慢.不过放心

  • Python实现识别手写数字 简易图片存储管理系统

    写在前面 上一篇文章Python实现识别手写数字-图像的处理中我们讲了图片的处理,将图片经过剪裁,拉伸等操作以后将每一个图片变成了1x10000大小的向量.但是如果只是这样的话,我们每一次运行的时候都需要将他们计算一遍,当图片特别多的时候会消耗大量的时间. 所以我们需要将这些向量存入一个文件当中,每次先看看图库中有没有新增的图片,如果有新增的图片,那么就将新增的图片变成1x10000向量再存入文件之中,然后从文件中读取全部图片向量即可.当图库中没有新增图片的时候,那么就直接调用文件中的图片向量进

  • Python实战之手写一个搜索引擎

    一.前言 这篇文章,我们将会尝试从零搭建一个简单的新闻搜索引擎 当然,一个完整的搜索引擎十分复杂,这里我们只介绍其中最为核心的几个模块 分别是数据模块.排序模块和搜索模块,下面我们会逐一讲解,这里先从宏观上看一下它们之间的工作流程 二.工作流程 三.数据模块 数据模块的主要作用是爬取网络上的数据,然后对数据进行清洗并保存到本地存储 一般来说,数据模块会采用非定向爬虫技术广泛爬取网络上的数据,以保证充足的数据源 但是由于本文只是演示,所以这里我们仅会采取定向爬虫爬取中国社会科学网上的部分文章素材

  • caffe的python接口之手写数字识别mnist实例

    目录 引言 一.数据准备 二.导入caffe库,并设定文件路径 二.生成配置文件 三.生成参数文件solver 四.开始训练模型 五.完成的python文件 引言 深度学习的第一个实例一般都是mnist,只要这个例子完全弄懂了,其它的就是举一反三的事了.由于篇幅原因,本文不具体介绍配置文件里面每个参数的具体函义,如果想弄明白的,请参看我以前的博文: 数据层及参数 视觉层及参数 solver配置文件及参数 一.数据准备 官网提供的mnist数据并不是图片,但我们以后做的实际项目可能是图片.因此有些

  • Python数据分析之双色球基于线性回归算法预测下期中奖结果示例

    本文实例讲述了Python数据分析之双色球基于线性回归算法预测下期中奖结果.分享给大家供大家参考,具体如下: 前面讲述了关于双色球的各种算法,这里将进行下期双色球号码的预测,想想有些小激动啊. 代码中使用了线性回归算法,这个场景使用这个算法,预测效果一般,各位可以考虑使用其他算法尝试结果. 发现之前有很多代码都是重复的工作,为了让代码看的更优雅,定义了函数,去调用,顿时高大上了 #!/usr/bin/python # -*- coding:UTF-8 -*- #导入需要的包 import pan

  • JS实现手写 forEach算法示例

    本文实例讲述了JS实现手写 forEach算法.分享给大家供大家参考,具体如下: 手写 forEach forEach()方法对数组的每个元素执行一次提供的函数 arr.forEach(callback(currentValue [, index [, array]])[, thisArg]); callback currentValue 数组中正在处理的当前元素. index 可选 数组中正在处理的当前元素的索引. array 可选 forEach() 方法正在操作的数组. thisArg 可

随机推荐