机器学习(六),使用tensorflow 训练抛物线

本文通过TensorFlow构建深度学习模型来拟合一元二次函数(抛物线)的数据。首先,利用numpy生成带噪声的抛物线数据,然后修改模型结构,引入ReLU激活函数,训练模型。在训练过程中,通过回调函数实时绘制学习曲线,展示模型的拟合过程。最后,探讨了改变神经元数量和层数对模型的影响,并指出模型的最后一层必须为1以输出单个结果。
摘要由CSDN通过智能技术生成


前言

镇楼:茴字有13种写法其实才是深入学习的有效方式

上篇文章我们基本完成了一个机器学习的标准模板,后续就是如何使用这个模板去解决实际问题。
本章我们尝试把数据复杂一点,先做成一元二次函数(抛物线)试试。


提示:以下是本篇文章正文内容,下面案例可供参考

一、抛物线数据生成

公式 y=-2xx + b , 生成一个100行一列的X二维数组,代码如下:


import numpy as np
import matplotlib.pyplot as plt

# fake data
x = np.linspace(-1, 1, 100)[:, np.newaxis]          # shape (100, 1)
noise = np.random.normal(0, 0.2, size=x.shape)
y = -2 *np.power(x, 2) + noise                          # shape (100, 1) + some noise

plt.scatter(x, y)

运行返回结果如下:
在这里插入图片描述

二、机器学习

1.模型修改

这里做一下说明,Dense是机器学习的隐藏层,实质等于 y=wx+b + activeFunc, 之前做一次函数的训练的时候,我们没有给 Dense指定activation参数,因此默认没有激活函数,所以训练的结果就是直线 y=ax+b, 现在要求不必要是直线,所以给予通用的 relu激活函数,后续可以自行体验 不同激活函数对于学习的效果。

机器学习的目的是 拟合数据,并且不需要知道如何拟合,数据公式是什么,这里我们把模型做如下修改:

#构建模型
model = tf.keras.models.Sequential([
            tf.keras.layers.Dense(10, activation=tf.nn.relu),
            tf.keras.layers.Dense(1)
        ])

这里我们添加了两个隐藏层, 第一个层有10个神经元,第二层只有1个神经元。神经元的数量,隐藏层的数量都属于超参,可以凭喜好任意决定。由于我们输出的结果只有一个y值,因此最后一层必须是1 。

为展示训练效果,对于PrintDot 函数做如下修改,使得可以展现学习效果的动态变化,代码中,每训练10次,使用model.predict 生成 预测的y值,重新打印一次曲线,我们可以看到曲线跟 原始数据点的拟合程度。

# 最多训练次数
max_num_epoch = 20000
# 当前训练次数
index_epoch = 0

# 在训练的时候输出进度图
class PrintDot(tf.keras.callbacks.Callback):
  def on_epoch_end(self, epoch, logs):
      global index_epoch, max_num_epoch
      if (epoch+1) % 10 == 0 or epoch==max_num_epoch-1:
        print(epoch, logs['loss'])   
        y_pred = model.predict(x)
        plt.cla()
        plt.scatter(x, y)
        plt.plot(x, y_pred, 'r-', lw=5)
        plt.pause(0.1)
      index_epoch = epoch
  def on_train_end(self, logs=None):
     print(index_epoch, logs)

2.完整代码

完整代码如下:

# -*- coding: utf-8 -*-
"""
Created on Wed Feb 24 14:02:24 2021

@author: huwp001

Dependencies:
tensorflow: 2.0
matplotlib
numpy

构造抛物线数据进行测试

"""

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# fake data
x = np.linspace(-1, 1, 100)[:, np.newaxis]          # shape (100, 1)
noise = np.random.normal(0, 0.2, size=x.shape)
y = -2 *np.power(x, 2) + noise                          # shape (100, 1) + some noise


#plt.scatter(x, y)


x = tf.constant(x, dtype=tf.float32)
y = tf.constant(y, dtype=tf.float32)

# 最多训练次数
max_num_epoch = 20000
# 当前训练次数
index_epoch = 0

# 在训练的时候输出进度图
class PrintDot(tf.keras.callbacks.Callback):
  def on_epoch_end(self, epoch, logs):
      global index_epoch, max_num_epoch
      if (epoch+1) % 10 == 0 or epoch==max_num_epoch-1:
        print(epoch, logs['loss'])   
        y_pred = model.predict(x)
        plt.cla()
        plt.scatter(x, y)
        plt.plot(x, y_pred, 'r-', lw=5)
        plt.pause(0.1)
      index_epoch = epoch
  def on_train_end(self, logs=None):
     print(index_epoch, logs)
        
        
# patience 值用来检查改进 epochs 的数量 
# 大约意思是 如果 每次训练 loss的变动 小于 0.0001 ,则为学习没有进展
# 如果连续100次没有进展,结束训练
early_stop = tf.keras.callbacks.EarlyStopping(monitor='loss', min_delta=0.0001, patience=100)


#构建模型
model = tf.keras.models.Sequential([
            tf.keras.layers.Dense(10, activation=tf.nn.relu),
            tf.keras.layers.Dense(1)
        ])

# 编译模型,设置了损失函数,优化器,评估工具
model.compile(
        optimizer=tf.keras.optimizers.SGD(learning_rate=5e-2),
        loss=tf.losses.MeanSquaredError(),
        metrics=['mae', 'mse']
    )

# 训练模型 
#  validation_split 表示边训练,边验证的比例。 Fraction of the training data to be used as validation data
history = model.fit(x, y, epochs=max_num_epoch, 
                   # validation_split=0.2,
        callbacks=[early_stop, PrintDot()],
        use_multiprocessing=True,
        verbose=0)

hist = pd.DataFrame(history.history)
hist['epoch'] = history.epoch
hist.tail()

def plot_history(history):
  hist = pd.DataFrame(history.history)
  hist['epoch'] = history.epoch

  plt.figure()
  
  plt.xlabel('Epoch')
  plt.ylabel('Mean Abs Error [MPG]')
  plt.plot(hist['epoch'], hist['mae'],
           label='mae Train Error')
  if 'val_mae' in hist.columns:
      plt.plot(hist['epoch'], hist['val_mae'],
           label = 'mae Val Error')

  plt.legend()

  plt.xlabel('Epoch')
  plt.ylabel('Mean Square Error [$MPG^2$]')
  plt.plot(hist['epoch'], hist['mse'],
           label='mse Train Error')
  if 'val_mse' in hist.columns:
      plt.plot(hist['epoch'], hist['val_mse'],
           label = 'mse Val Error')
  #plt.ylim([0,20])
  plt.legend()
  
  plt.show()


plot_history(history)





3.运行源码

训练后,得到如下两个图。

在这里插入图片描述

在这里插入图片描述


4.其他

尝试修改下模型的神经元数量和层数,发现基本都能训练出来,结果差距不大。
注意最后一个层,必须是 1, 表示只输出一个结果。

#构建模型v2
model = tf.keras.models.Sequential([
            tf.keras.layers.Dense(20, activation=tf.nn.relu),
            tf.keras.layers.Dense(1)
        ])
#构建模型v3
model = tf.keras.models.Sequential([
            tf.keras.layers.Dense(30, activation=tf.nn.relu),
            tf.keras.layers.Dense(20, activation=tf.nn.relu),
            tf.keras.layers.Dense(1)
        ])

tensorflow 开发环境安装 前往

总结

本章内容完成了抛物线的测试,三次甚至多次函数这样处理基本都一样,下一章我们考虑随意手绘数据进行测试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值