深度学习笔记:01快速构建一个手写数字识别系统以及张量的概念

深度学习笔记:01快速构建一个手写数字识别系统

神经网络代码最好运行在GPU中,但是对于初学者来说运行在GPU上成本太高了,所以先运行在CPU中,就是慢一些。

一、安装keras框架

  1. 使用管理员模式打开cmd,运行以下指令
C:\WINDOWS\system32>pip install tensorflow_cpu -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com

(以后安装也可以这样,只要将tensorflow_cpu换成需要下载的库或包名,根据自己需求自行更改即可)

安装完成:在这里插入图片描述

  1. 检测是否安装上keras框架:

    运行以下指令:

    import tensorflow
    import keras
    print(keras.__version__)
    

    我的输出结果是:2.9.0。安装完毕,可以使用啦~

二、熟悉mnist数据集

首先,我们先把我们需要的数据集引入,并且定义两个数据集

from keras.datasets import mnist 
(train_images,train_labels),(test_images,test_labels) = mnist.load_data()

其中,这个images和labels分别表示我们这个mnist数据集中的图片和这个图片所对应的数字(标签),例如:

print(test_images)

结果:在这里插入图片描述

这个可能并不方便看出什么来,那么我们通过:

print(test_images.shape)

结果:在这里插入图片描述

可以看出这个test_images是一个含有10000个元素的数组,并且每个元素是一个28×28的二维数组(像素)。也就是这个test_images含有10000张像素为28×28的手写数字图片。

下面我们再看一下test_labels:

print(test_labels)

结果:在这里插入图片描述

test_labels是标记我们test_images的标签,他也是有10000个元素并且每个元素都和test_images的元素一一对应。相当于告诉我们test_images每个图片对应的手写数字是什么。

我们可以通过下面几行代码做一个简短的验证:

digit = test_images[0]
import matplotlib.pyplot as plt # matpoltlib是一个绘制图案的python库
plt.imshow(digit,cmap=plt.cm.binary)
plt.show()

结果:在这里插入图片描述

确实,test_labels也显示第一个数字是7。验证完毕~

三、使用keras框架快速构建手写数字识别函数

首先我们之前提过神经网络的模型结构:在这里插入图片描述

下面这段代码完成的是这个模型结构的上半部分:在这里插入图片描述

from keras import models
from keras import layers

network = models.Sequential() 
network.add(layers.Dense(512,activation="relu",input_shape=(28*28,)))
# activation="relu"的意思是激活函数是relu函数 input_shape=(28*28,)的意思是我接受的这个神经网络必须是28*28的二维数组
network.add(layers.Dense(10,activation="softmax"))

**Sequential()函数的作用:**将你的神经网络的每一层都想象成一个佛珠,然后把每个你想串联起来的网络层名字传给Sequential函数,他的作用就是把每个网络层像串佛珠一样串联起来,这样你就不用每个都去链接一次了。

下面我们再来完善我们这个模型的下半部分:

network.compile(optimizer="rmsprop",loss="categorical_crossentropy",metrics=["accuracy"])

**compile()函数的作用:**用于将源代码编译为代码对象或AST模块对象。 可以根据提供的模式使用exec()eval()函数执行返回的代码对象,以构造代码对象。

那么我们这一行就对应着这个网络模型的下半部分。

下面我们在对我们images数据进行进一步的处理:

train_images = train_images.reshape((60000,28*28))
train_images = train_images.astype('float32')/255

test_images = test_images.reshape(10000,28*28)
test_images = test_images.astype('float32')/255
  1. 将我们原来的train_images里面28×28的二维数组变成28×28的一维数组

  2. 再将每一个元素里面的数值都除以255(因为像素点)

    因为我们传给网络进行训练的图片是一个灰度图,灰度图指的是这里面的每一个像素点他的值都介于0~255之间。所以除以255以后他的每个数都变成了0~1之间的一个浮点数,这样传给网络便于接下来的识别与统计。

接下来我们来转化labels数据:

from keras.utils import to_categorical
print("before change:",test_labels[0])
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
print("after change:",test_labels[0])

关键点:调用categorical接口转换

目的:将数字变成数组表示。因为图片中包含的都是0~9一共10个数字,下面我们将这个数字变成由10个元素组成的数组。比如说刚刚我们的数字7,将其变成数组以后就其余元素都是0只有数组的第七个元素是1。然后将这个转换给我们的神经网络进行识别。

结果:
在这里插入图片描述

最后一步,开始训练我们的神经网络:

network.fit(train_images,train_labels,epochs=5,batch_size=128)

现在我们准备开始训练网络,在 keras中这一步是通过调用网络的fit方法来完成的—— 我们在训练数据上拟合(fit)模型。

epochs表示每次训练改进时都是进行5个循环

batch_size=128表示每次训练都从这个数组中_images随机抽取128个图片来进行统计

结果如图:在这里插入图片描述

训练过程中显示了两个数字:一个是网络在训练数据上的损失(loss),另一个是网络在 训练数据上的精度(acc)。

下面我们调用evaluate接口看我们对这个测试的图片进行识别看识别成功率为多少

test_loss,test_acc=network.evaluate(test_images,test_labels,verbose=1)
print('test_acc:',test_acc)

我这边是:在这里插入图片描述

最后我们拿一张图片,来看一下这个对于这张图片我们的神经网络的识别结果:

from keras.datasets import mnist
(train_images,train_labels),(test_images,test_labels) = mnist.load_data()
digit = test_images[1]
plt.imshow(digit,cmap=plt.cm.binary)
plt.show()

test_images = test_images.reshape(10000,28*28)
res = network.predict(test_images)
print(res[1])

for i in range(res[1].shape[0]):
    if(res[1][i] == 1):
        print("the number for the picture is",i)
        break

结果很不错!成功识别是2
在这里插入图片描述

四、张量的概念

tensor的中文意思就是:张量

tensor是后面在进行神经网络开发时的最基本的概念,存储在多维数组(Numpy)中。

tensor的常用属性有维度(dim),和形状(shape)

  • 0-dim的tensor就是一个常量,在python中,我们通过ndim的属性来获取tensor的维度,通过shape属性来获取形状
import numpy as np
x= np.array(666)
print(x)
print(x.ndim)
print(x.shape)
666
0
()
  • 1-dim的tensor就是一个数组
x= np.array([0,1,4,9])
print(x)
print(x.ndim)
print(x.shape)
[0 1 4 9]
1
(4,)
  • 2-dim的tensor就是一个二维数组
x = np.array([
    [1,2,3,4],
    [2,2,3,4],
    [3,2,3,4]
])
print(x)
print(x.ndim)
print(x.shape)
[[1 2 3 4]
 [2 2 3 4]
 [3 2 3 4]]
2
(3, 4)

所以我们可以理解为一个n-dim的tensor,他其实就是一个一维数组,数组中每个元素都是(n-1)-dim的tensor。所以,3-dim张量就是一个一维数组,数组中的每个元素就是2-dim的tensor,相关代码如下:

x = np.array([
    [
        [1,2],
        [3,4]
    ],
    [
        [5,6],
        [7,8]
    ],
    [
        [9,1],
        [1,2]
    ]
])
print(x.ndim)
print(x.shape)
3
(3, 2, 2)

shape告诉我们,这个x有三个元素,每个元素都是一个2*2的二维数组

几维张量括号内就对应几个数字:

  1. 第一个数字3:表示这个3-张量内包括3个元素,即2-dim张量
  2. 第二个数字2:2-dim张量内包含2个元素,即1-dim张量
  3. 第三个数字2:1-dim张量内包含2个元素,即0-dim张量(常量)

所以对照我们上节所学train_images:

image-20220802210055611

所以在面对大规模的张量时我们可以实现另一种操作就是将张量中的某一部分的值单独提取出来:

from keras.datasets import mnist
(train_images,train_labels),(test_images,test_labels) = mnist.load_data()
my_slice = train_images[10:100]
print(my_slice.shape)
image-20220802210719852

这就是batch的概念:batch值得是从全部数据中抽出一部分形成一个子集,上面代码中的my_slice就是一个batch

五、张量的运算

张量的relu运算:将张量内的值x与0作比较,如果x>0 不变,如果x<0 则将x变成0

类似下面的函数实现:

def naive_relu(x):
    assert len(x.shape) == 2
    x = x.copy() #确保操作不对x产生影响
    for i in range(x.shape[0]):
        for j in range(x.shape[1]):
            x[i][j] = max (x[i][j],0)        
    return x

x = np.array([
    [1,-1],
    [-2,1]
])
print(naive_relu(x))
image-20220802211754771

==张量的点乘运算:==1-dim的点乘是每个之间点乘并求和累加

类似下面的函数实现:

def naive_vector_dot(x,y):
    assert len(x.shape) == 1
    assert len(y.shape) == 1
    assert x.shape[0] == y.shape[0]
    
    z = 0.
    for i in range(x.shape[0]):
        z = z + x[i] * y[i]
    
    return z

x = np.array([1,2,3])
y = np.array([4,5,6])

print(naive_vector_dot(x,y))
image-20220802212645578

所以类推高维张量之间做点乘运算,类似于矩阵的运算。

即:一个m*n的矩阵也只能乘以一个n*s的矩阵,这俩矩阵第一个的列数必须得等于第二个的行数

例如:

def naive_matrix_vector_dot(x,y):
    z = np.zeros(x.shape[0])
    for i in range(x.shape[0]):
        z[i] = naive_vector_dot(x[i,:],y)
    return z

x = np.array([
    [4,5,6],
    [7,8,9]
])
y = np.array(
    [1,2,3]
)

print(naive_matrix_vector_dot(x,y))
image-20220802214958580

转化成矩阵运算也就是这个意思:

image-20220802215031056

最后,张量是深度学习中最基础的一个概念。务必要搞清楚!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值