文章目录

  • 1.多分类任务
  • 1.MNIST数据集
  • 2.多分类损失函数
  • 3.手写识别:训练
  • 4.手写识别:使用
  • 5.自定义更新写法
  • 2.使用Tensorflow构建神经网络
  • 1.导入mnist数据集
  • 2.构建神经网络模型
  • 3.神经网络中所用函数
  • 4.神经网络训练更新


1.多分类任务

1.MNIST数据集

  训练数据:6万张
  测试数据:1万张

2.多分类损失函数
  • 虚拟变量
       取值为0或1的变量,当对象属于虚拟变量代表的类别时,取值为1。
      常用于解决多分类问题,先将多分类变量转变为虚拟变量
  • 独热编码(one-hot)
      N个状态:N个寄存器进行编码,且任意时候只有一位有效
import pandas as pd
  # 独热编码
  df = pd.DataFrame([['one'],['two'],['three']],columns = ['y'])
  # pd.DataFrame()创建带标签的二维数组,(data数据,index=行标签,columns=列标签),标签默认0-n
  print(df)
  df_oh = pd.get_dummies(df['y'])
  # pd.get_dummies()对虚拟变量进行编码
  print(df_oh)
  print(df_oh[['one','two','three']])  #形式转换
  • 损失函数
    1.0-1损失函数(0-1 Loss)
    tensorflow怎么查看神经模型的准确率 tensorflow训练神经网络_数据集
    2.二元交叉熵(binary crossentropy)
    tensorflow怎么查看神经模型的准确率 tensorflow训练神经网络_损失函数_02
        yi  样本i的标签,1或0
        pi  样本i标签为yi 的几率
    3.稀疏分类交叉熵(sparse categorical crossentropy)
    tensorflow怎么查看神经模型的准确率 tensorflow训练神经网络_python_03
    优点:偏导数易于获取,模型差时学习速率快
    缺点:矩阵参数随类别数增大而增大,开放集学习问题
3.手写识别:训练
  • 导入mnist数据集
from tensorflow import keras
  import matplotlib.pyplot as plt
  mnist = keras.datasets.mnist  #导入MNIST数据集
  (train_images,train_labels),(test_images,test_labels) = mnist.load_data()  #将数据集分为训练集和测试集
  print(type(train_images),train_images.shape)  #train_images的类型,大小
  print(train_labels)  #查看train_labels

  plt.imshow(train_images[0])  #画第一幅图
  plt.colorbar()
  plt.show()
  print(train_labels[0])
  • 归一化
train_images,test_images = train_images/255.0,test_images/255.0  #将图  片转为灰度图,数值范围0-1,归一化
  plt.imshow(train_images[0],cmap = plt.cm.binary)  #画第一幅图,  plt.cm.binary 黑白色彩
  plt.colorbar()
  plt.show()

  plt.figure(figsize = (10,10))  #显示多张图片
  for i in range(25):
      plt.subplot(5,5,i+1)
      plt.xticks([])  #去除x y的坐标刻度
      plt.yticks([])
      plt.imshow(train_images[i], cmap = plt.cm.binary)  #plt.cm.binary 黑白色彩
      plt.xlabel(train_labels[i])  #将x轴标签替换为手写数字
  plt.show()
  • 模型构建与编译
import numpy as np
  model = keras.Sequential(  #构建神经网络模型
      [
          keras.layers.Flatten(input_shape = (28,28)),  #第一层,Flatten()将二维数组降成一维
          keras.layers.Dense(128,activation = 'relu'),  #第二层
          keras.layers.Dense(10,activation = 'softmax')  #第三层,输出层
      ]
  )
  print(model.summary())  #输出模型概述
  model.compile(optimizer = 'adam',
                loss = 'sparse_categorical_crossentropy',  #设置模型损失函数为稀疏分类交叉熵
                metrics = ['accuracy'])

  model.fit(train_images,train_labels,epochs = 5,verbose = 0)  #开始训练模型,5次,不输出
  test_loss,test_acc = model.evaluate(test_images,test_labels)  #模型评价
  print('Test accuracy:',test_acc)  #输出模型准确率
  
  predictions = model.predict(test_images)  #模型预测
  print(np.argmax(predictions[0]))  #argmax()返回其中元素最大值所对应的索引
4.手写识别:使用
  • 模型评估
def plot_image(i,predictions_array,true_label,img):  #自定义绘数字图函数
      predictions_array,true_label,img = predictions_array,true_label[i],img[i]
      plt.xticks([])  #去除x y刻度
      plt.yticks([])

      plt.imshow(img,cmap = plt.cm.binary)
      predicted_label = np.argmax(predictions_array)  #预测数字
      if predicted_label == true_label:  #如果预测等于实际,颜色蓝色
          color = 'b'
      else:
          color = 'r'  #如果与实际不符,颜色红色
      plt.xlabel('%d %.2f%s(%d)'%(predicted_label,np.max(predictions_array)*100,'%',true_label))
      # x轴标签 预测值 预测值概率 真实值

  def plot_value_array(i,predictions_array,true_label):  #自定义绘柱状图
      predictions_array,true_label = predictions_array,true_label[i]
      plt.xticks(range(10))  # x轴标签0-9
      plt.yticks([])  # y轴无标签

      thisplot = plt.bar(range(10),predictions_array,color = '#777777')  #绘制柱状图并暂时储存thisplot,x柱子坐标,height柱子高度,color柱子颜色,'#777777'灰色
      plt.ylim(0,1)  #设置y轴的范围0-1
      predicted_label = np.argmax(predictions_array)  #预测数字

      thisplot[predicted_label].set_color('r')  #将预测数字设置为蓝色
      thisplot[true_label].set_color('b')  #将真实数字设置为红色

  #开始绘图
  i = 0
  plt.figure(figsize = (6,3))  #设置总绘图大小
  plt.subplot(1,2,1)  #绘制第一个子图
  plot_image(i,predictions[i],test_labels,test_images)
  plt.subplot(1,2,2)  #绘制第二个子图
  plot_value_array(i,predictions[i],test_labels)
  plt.show()

  #绘制多幅连续子图
  num_rows = 5  #行数
  num_cols = 3  #列数
  num_images = num_rows*num_cols  #总图数目
  plt.figure(figsize = (2*2*num_cols,2*num_rows))
  for j in range(num_images):
      plt.subplot(num_rows,2*num_cols,2*j+1)  #绘制第一个子图
      plot_image(i+j,predictions[i+j],test_labels,test_images)
      plt.subplot(num_rows,2*num_cols,2*j+2)
      plot_value_array(i+j,predictions[i+j],test_labels)
  plt.tight_layout()  #自动调整子图参数,使其填充整个图像区域
  plt.show()
  • 对本地文件进行识别
from PIL import Image
  #对本地图片进行手写识别
  img = Image.open('my_num.bmp')  #导入本地图片
  img = np.array(img)  #将图片转化为数组
  img = img/255.0  #将数组转为0-1之间
  my_num = 1-img  #白为1转为黑为1
  my_num = my_num.reshape(1,28,28)  #改变数组形状
  plt.imshow(my_num[0],cmap = plt.cm.binary)  #绘图
  plt.colorbar()
  plt.show()
  res = model.predict(my_num)  #输出预测数字
  print(np.argmax(res))
5.自定义更新写法
  • 离散化权重
import numpy as np
  import matplotlib.pyplot as plt

  #权重操作
  G_min = -1  #最小值
  G_max = 1  #最大值
  A_p = 0.8
  A_d = 0.8
  def LTP(P):
      return (G_max - G_min) * (1 - np.exp(P / A_p)) / (1 - np.exp(1 / A_p)) + G_min  # 向上更新
  def LTD(P):
      return (G_max - G_min) * (1 - np.exp((1 - P) / A_d)) / (1 - np.exp(1 / A_d)) + G_min  # 向下更新
  def L(P):
      return (G_max - G_min) * P + G_min  #线性
  x = np.linspace(0,1,20)  #创建数组
  y = []
  for p in x:
      y.append(LTP(p))  #在y数组末尾添加
  plt.scatter(x,y)  #绘制散点图
  plt.show()

  y = []
  for p in x:
      y.append(LTD(p))  #在y数组末尾添加
  plt.scatter(x,y)  #绘制散点图
  plt.show()

  y = []  #线性
  for p in x:
      y.append(L(p))  #在y数组末尾添加
  plt.scatter(x,y)  #绘制散点图
  plt.show()
  • 自定义权重更新
import tensorflow as tf
  from tensorflow import keras
  
  mnist = keras.datasets.mnist  #导入mnist数据集
  (train_images,train_labels),(test_images,test_labels) = mnist.load_data()  #数据集分为训练集和测试集
  train_images,test_images = train_images/255.0,test_images/255.0  #将图片转为灰度图,数值范围0-1
  model = keras.Sequential(  #构建神经网络模型
      [
          keras.layers.Flatten(input_shape = (28,28)),  #第一层,Flatten()将二维数组降成一维
          keras.layers.Dense(128,activation = 'relu',use_bias = False),  #第二层,use_bias = False不使用偏移量b
          keras.layers.Dense(10,activation = 'softmax',use_bias = False)  #第三层,输出层
      ]
  )
  model.compile(optimizer = 'sgd',  #使用梯度下降来优化
                loss = 'sparse_categorical_crossentropy',  #设置模型损失函数为稀疏分类交叉熵
                metrics = ['accuracy'])
  P10 = 100*(np.random.rand(28*28,128))+0.5  #生成随机数组,数值范围0-100,大小784*128,*100离散化,+0.5便于四舍五入
  P1 = P10.astype(int)  #将浮点数转换为整数,astype数据类型转换
  P20 = 100*(np.random.rand(128,10))+0.5  #随机数组,大小125*10
  P2 = P20.astype(int)  #类型转换

  def ini_net(model,P1,P2):  #神经网络模型初始化
      weight_1 = 2*(P1/100-0.5)  #权重,范围-1到1
      weight_2 = 2*(P2/100-0.5)
      weights = [weight_1,weight_2]  #总权重数组
      model.set_weights(weights)  #模型设置权重

  def update_net(model,func_p,func_d):  #自定义模型更新函数
      weights_bak = model.get_weights()  #获取原来模型的权重
      model.fit(train_images,train_labels,epochs = 1,verbose = 0)  #模型训练一次,不输出
      weights = model.get_weights()  #获取训练后模型的权重
      for i in range(len(weights[0])):
          for j in range(len(weights[0][0])):
              if weights[0][i][j] > weights_bak[0][i][j]:  #如果原来权重大于训练后权重
                  if(P1[i][j] < 100):  #如果权重小于1大于-1时才更新权重
                      P1[i][j] +=1  #每次更新加0.01
                  weights[0][i][j] = func_p(P1[i][j]/100)
              elif weights[0][i][j] < weights_bak[0][i][j]:  #如果原来权重小于训练后权重
                  if(P1[i][j] > 0):  #如果权重小于1大于-1时才更新权重
                      P1[i][j] -=1  #每次更新减0.01
                  weights[0][i][j] = func_d(P1[i][j]/100)

      for i in range(len(weights[1])):
          for j in range(len(weights[1][0])):
              if weights[1][i][j] > weights_bak[1][i][j]:  #如果原来权重大于训练后权重
                  if(P1[i][j] < 100):  #如果权重小于1大于-1时才更新权重
                      P1[i][j] +=1  #每次更新加0.01
                  weights[1][i][j] = func_p(P1[i][j]/100)
              elif weights[1][i][j] < weights_bak[1][i][j]:  #如果原来权重小于训练后权重
                  if(P1[i][j] > 0):  #如果权重小于1大于-1时才更新权重
                      P1[i][j] -=1  #每次更新减0.01
                  weights[1][i][j] = func_d(P1[i][j]/100)
      model.set_weights(weights)  #设置更新后权重

  EPOCHS = 20  #更新次数
  ini_net(model,P1,P2)  #初始化
  acc1 = []  #储存线性准确度
  for epochs in range(EPOCHS):
      update_net(model,L,L)  #线性更新
      train_loss,train_acc = model.evaluate(train_images,train_labels)  #评价模型
      acc1.append(train_acc)
  test_loss,test_acc = model.evaluate(test_images,test_labels)  #检验模型

  #重新初始化模型
  P1 = P10.astype(int)  #将浮点数转换为整数,astype数据类型转换
  P2 = P20.astype(int)  #类型转换
  ini_net(model,P1,P2)  #初始化
  acc2 = []  #储存线性准确度
  for epochs in range(EPOCHS):
      update_net(model,LTP,LTP)  #非线性更新(0.8 0.8)
      train_loss,train_acc = model.evaluate(train_images,train_labels)  #评价模型
      acc2.append(train_acc)
  test_loss,test_acc = model.evaluate(test_images,test_labels)  #检验模型

  plt.plot(np.arange(1,21),acc1,'o-')  #np.arange()返回起点到终点固定步长的数组,步长默认1,    plt.plot()绘制点线图
  plt.plot(np.arange(1,21),acc2,'o-')
  plt.show()

2.使用Tensorflow构建神经网络

1.导入mnist数据集
import numpy as np
  import tensorflow as tf
  from tensorflow import keras

  gpus = tf.config.list_physical_devices('GPU')  #查看当前主机上GPU列表
  tf.config.experimental.set_memory_growth(gpus[0],True)  #动态申请显存

  mnist = keras.datasets.mnist  #导入mnist数据集
  (x_train,y_train),(x_test,y_test) = mnist.load_data()  #数据集分为训练集和测试集
  x_train,x_test = np.array(x_train,np.float32),np.array(x_test,np.float32)  #64位浮点数变为32位浮点数
  x_train,x_test = x_train/255.0,x_test/255.0  #将图片转为灰度图,数值范围0-1
  x_train,x_test = x_train.reshape(-1,28*28),x_test.reshape(-1,28*28)  #三维变二维,-1模糊控制,固定28*28列
  print(x_train.shape,x_test.shape)  #输出其形状
2.构建神经网络模型
n_hidden_1 = 128  #每层神经元数目
  n_hidden_2 = 256
  random_normal = tf.initializers.RandomNormal()  #生成服从正态分布的随机张量
  weights = {  #权重
      'h1':tf.Variable(random_normal([28*28,n_hidden_1])),  #第一层
      'h2':tf.Variable(random_normal([n_hidden_1,n_hidden_2])),  #第二层
      'out':tf.Variable(random_normal([n_hidden_2,10]))  #输出层
  }
  biases = {  #偏移量
      'b1':tf.Variable(tf.zeros([n_hidden_1])),  #初始为零,第一层
      'b2':tf.Variable(tf.zeros([n_hidden_2])),  #第二层
      'out':tf.Variable(tf.zeros([10]))  #输出层
  }
3.神经网络中所用函数
def neural_net(x):  #自定义神经网络函数
      #第一层
      layer_1 = tf.add(tf.matmul(x,weights['h1']),biases['b1'])  #返回x*h1+b1
      layer_1 = tf.nn.sigmoid(layer_1)  #激活函数sigmoid
      #第二层
      layer_2 = tf.add(tf.matmul(layer_1,weights['h2']),biases['b2']) #返回layer_1*h2+b2
      layer_2 = tf.nn.sigmoid(layer_2)  # 激活函数sigmoid
      #输出层
      out_layer = tf.add(tf.matmul(layer_2,weights['out']),biases['out'])
      return tf.nn.softmax(out_layer)  #激活函数softmax
  def cross_entropy(y_pred,y_true):  #自定义稀释函数交叉熵
      y_true = tf.one_hot(y_true,10)  #tf.one_hot()将向量y_true转换为独热编码的形式,10个类别
      y_pred = tf.clip_by_value(y_pred,1e-9,1.0)  #tf.clip_by_value()将张量数值控制在特定范围,1e-9到1
      return tf.reduce_mean(-tf.reduce_sum(y_true*tf.math.log(y_pred),1))  #tf.reduce_mean()求平均值,tf.reduce_sum()求和
  def accuracy(y_pred,y_true):  #自定义准确率
      correct_prediction = tf.equal(tf.argmax(y_pred,1),tf.cast(y_true,tf.int64))  #tf.equal()张量值相等返回true否则返回false
      return tf.reduce_mean(tf.cast(correct_prediction,tf.float32))  #tf.cast()转换为指定类型
4.神经网络训练更新
EPOCHS = 100  #训练次数
  for epoch in range(EPOCHS):  #梯度下降方法
      with tf.GradientTape() as tape:  #自动记录微分操作
          pred_val = neural_net(x_train)
          loss = cross_entropy(pred_val,y_train)

      trainable_var = list(weights.values())+list(biases.values())

      grads = tape.gradient(loss,trainable_var)   #计算梯度

      optimizer = tf.optimizers.Adam()  #用自适应矩估计来优化
      optimizer.apply_gradients(zip(grads,trainable_var))  #zip()将对应元素打包成一个个元组
      acc = accuracy(neural_net(x_test),y_test)

      if(epoch+1)%10 == 0:  #每训练10次输出结果
          print('Epoch [%d/%d],Train loss: %.3f,Test accuraccy: %.3f'%(epoch+1,EPOCHS,loss,acc))