Machine Learning入门TF2.0(KNN手写识别算法实现)

机器学习的形式

关于机器学习是什么我就不过多解释,下面仅仅对其简单分下类:

  • 监督学习
    在学习过程中提供标签,对错标签
    这一类学习目的主要是用于回归和分类。

  • 无监督学习
    提供未知标签的一组样本,然后去给这些样本分类。也称聚类问题。模式识别领域

  • 半监督学习
    监督学习和无监督学习组合的一种方式。

  • 强化学习(阿尔法狗 Alpha Zero)
    智能系统从环境到行为映射的学习,以此为奖励信号。

  • 迁移学习

前面所介绍的学习方法从某种角度说是从数理统计角度对一些东西做出的归纳

  • 深度学习
    而深度学习是从另一方面,生物模拟这方面入手。有点仿生学的意思。模拟人类的神经元。

简单做了一个脑图如下:
Machine Learning

从零搭建KNN

KNN(k - nearestneighbor)算法即K最近邻算法。该算法有点类似于类比,简单说就是我现在有一个东西需要分类,我把它与已经分类好的东西进行比较,和谁最像,那么这个东西就是什么。
以下是其具体实现:

from tensorflow.keras import datasets
import tensorflow as tf
import math
import numpy as np
#虽然导入了tensorflow,但实际上并没有用到tensorflow的神经网络的框架,只是用它来得到并稍微处理了一下数据集

# 按照四步走来编写代码,四步即 准备数据->搭建网络->训练网络->测试网络
# 准备数据
(train_images, train_labels), (test_images, test_labels) = datasets.mnist.load_data()
# 训练图像保存在一个uint8 类型的数组中,其形状为(60000, 28, 28),取值区间为[0, 255]。
# 我们需要将其变换为一个float32 数组,其形状为(60000, 28 * 28),取值范围为0~1。
train_images = train_images.reshape(60000, 28*28).astype('float32') / 255
test_images = test_images.reshape(10000, 28*28).astype('float32') / 255
# 对标签进行分类编码(one-hot编码)
train_labels = tf.keras.utils.to_categorical(train_labels)
test_labels = tf.keras.utils.to_categorical(test_labels)
# 搭建KNN并测试(此处我们用KNN来实现手写识别严格意义上来说,并不是搭建一个网络,这三个步骤都包含在下面)
# 且以下是用minst数据集的训练集和测试集分别来测试这种最简单的KNN算法的准确性,我的测试结果大概是90%
def knn_test(test_sum, train_sum):
    print("测试KNN算法的准备性")
    accracy = 0
    for i in range(test_sum):
        test_data = test_images[i]
        for j in range(train_sum):
            train_data = train_images[j]
            dist = get_dist(train_data, test_data)
            if j == 0:
                min_dist = dist
                min_index = j
            else:
                if dist < min_dist:
                    min_dist = dist
                    min_index = j
        predict = np.argmax(train_labels[min_index])
        real_data = np.argmax(test_labels[i])
        if predict == real_data:
            accracy += 1/test_sum
        print("预测:", predict, "实际:", real_data)
    print("准确性:", accracy)
# 求“距离”函数
def get_dist(train_data, test_data):
    data_pow = 0.
    for k in range(784):
        data_pow += math.pow(train_data[k]-test_data[k], 2)
    data_pow = math.sqrt(data_pow)
    return data_pow

# 测试
test_sum = 20
train_sum = 1000
knn_test(test_sum, train_sum)

优化

在求"距离"的时候那个循环代码其实是可以优化的:仅用下面一行代码即可:

min_index = np.argmin(np.sqrt(np.sum(np.square(test_data-train_data), axis=1)))

优化后的整体代码:

from tensorflow.keras import datasets
import tensorflow as tf
import math
import numpy as np
from PIL import Image
#虽然导入了tensorflow,但实际上并没有用到tensorflow的神经网络的框架,只是用它来得到并稍微处理了一下数据集

# 按照四步走来编写代码,四步即 准备数据->搭建网络->训练网络->测试网络
# 准备数据
(train_images, train_labels), (test_images, test_labels) = datasets.mnist.load_data()
# 训练图像保存在一个uint8 类型的数组中,其形状为(60000, 28, 28),取值区间为[0, 255]。
# 我们需要将其变换为一个float32 数组,其形状为(60000, 28 * 28),取值范围为0~1。
train_images = train_images.reshape(60000, 28*28).astype('float32') / 255
test_images = test_images.reshape(10000, 28*28).astype('float32') / 255
# 对标签进行分类编码(one-hot编码)
train_labels = tf.keras.utils.to_categorical(train_labels)
test_labels = tf.keras.utils.to_categorical(test_labels)
# 搭建KNN并测试(此处我们用KNN来实现手写识别严格意义上来说,并不是搭建一个网络,这三个步骤都包含在下面)
# 且以下是用minst数据集的训练集和测试集分别来测试这种最简单的KNN算法的准确性,我的测试结果大概是80%
def knn_test(test_sum, train_sum):
    print("测试KNN算法的准备性")
    accracy = 0
    for i in range(test_sum):
        test_data = test_images[i]
        train_data = train_images[0:train_sum, :]
        # 优化如下
        min_index = np.argmin(np.sqrt(np.sum(np.square(test_data-train_data), axis=1)))

        predict = np.argmax(train_labels[min_index])
        real_data = np.argmax(test_labels[i])
        if predict == real_data:
            accracy += 1/test_sum
        print("预测:", predict, "实际:", real_data)
    print("准确性:", accracy)
# 测试
test_sum = 200
train_sum = 50000
knn_test(test_sum, train_sum)

手写识别demo

以上仅仅使用MINST数据集中的训练集和测试集做了一下测试,如果能让代码识别自己写的数字呢?其实只需要稍微改一下刚才的代码即可。
但是首先我们得先自己画一个数字,可以用画图板画了一个数字,并且最后得到的要是28*28像素的,因为之前的代码的是以这样的图片为基础写的,你当然可以改代码,但是简单起见,我直接改图片。
下面是我用windows自带的画图板画的一个数字:
图片
识别代码如下:

from tensorflow.keras import datasets
import tensorflow as tf
import math
import numpy as np
from PIL import Image

# 准备数据
(train_images, train_labels), (test_images, test_labels) = datasets.mnist.load_data()
train_images = train_images.reshape(60000, 28*28).astype('float32') / 255
train_labels = tf.keras.utils.to_categorical(train_labels)

# 识别自己写的数字的代码
def image_reshape(image_address):   # 将28*28像素图片转化为28*28数组
    #注意此处输入的image需要是28*28像素的
    image = Image.open(image_address).convert('L')  # 用PIL中的Image.open打开图像
    image.save("test01.png")
    # .convert('L')是将图片灰度化处理,原本是彩色图片,也就是维度是(28,28,3),将其变为(28,28)
    image_arr = np.array(image)  # 转化成numpy数组

    image_arr = np.reshape(image_arr, 28 * 28).astype('float32') / 255
    #再将其变换为一个float32 数组,其形状为(784,),取值范围为0~1。
    print(image_arr)
    return image_arr
def knn_real(image_address,train_sum):
    test_data = image_reshape(image_address)
    train_data = train_images[0:train_sum, :]
    min_index = np.argmin(np.sqrt(np.sum(np.square(test_data - train_data), axis=1)))
    predict = np.argmax(train_labels[min_index])
    print("预测:", predict)

train_sum = 40000
knn_real("test.png", train_sum)

发布了17 篇原创文章 · 获赞 6 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44307764/article/details/102353344