CH5 用神经网络解决线性问题

  • 了解非线性问题、分类问题
  • 掌握神经网络解决二分类问题
  • 掌握随机生成训练数据的方法

非线性问题

三好学生问题:家长们再次凑到一起,但这次情况不一样了,孩子们的总分不知道,仅知道是否评选上三好学生的结果。

计算总分的规则仍然是:总分 = 德育分*60% + 智育分*30% + 体育分*10%
评选三好学生的标准是:总分 ≥ 95

家长不知道这两条规则。

这是一个典型的分类问题。学校一定是以德育分、智育分和体育分三项分数为依据,把学生们分成两类:三好学生和非三好学生。因此,这是一个常见的二分类问题。下图是用神经网络简述二分类问题。

image

分类问题一般是非线性的。

  • 可以看出,当总分达到95之后,y值有一个跳变,并非线性的(一条直线)
  • y=f(xA),跳变函数/阶跃函数
  • “一票否决制”

image

设计神经网络模型

总分(0~100)= 德育分60% + 智育分30% + 体育分*10% -> 评选结果(0、1)

激活函数:把线性关系转换成非线性关系的函数。激活函数 sigmoid 函数的作用是把参数转换成为 0 到 1 之间的一个小数。

image

使用激活函数后的神经网络模型:

image

实现该网络模型的代码:

# import tensorflow as tf
import tensorflow.compat.v1 as tf

tf.compat.v1.disable_eager_execution()

x = tf.placeholder(dtype=tf.float32)
yTrain = tf.placeholder(dtype=tf.float32)
w = tf.Variable(tf.zeros([3]), dtype=tf.float32)

n1 = w * x
n2 = tf.reduce_sum(n1)

y = tf.nn.sigmoid(n2)

准备训练数据

使用 random 产生随机数

import random

random.seed() # 初始化随机数种子,增加随机性
random.random() # 产生一个 [0,1) 范围内的小数

r = random.random() * 10 # 通过乘以一个整数,使产生的随机数的范围增大,此处范围为 [0,10)

产生随机训练数据

import random

random.seed()

# 产生一个 [0,100] 范围内的整数代表某一科分数
xData = [int(random.random() * 101),int(random.random() * 101),int(random.random() * 101)]

# 按规则生成总分
xAll = xData[0] * 0.6 + xData[1] * 0.3 + xData[2] * 0.1

# 按规则生成评选结果
if xAll >= 95:
    yTrainData = 1
else:
    yTrainData = 0

print("xData: %s" %xData)
print("yTrainData: %s" %yTrainData)

image

优化产生的训练数据,产生一个[60,101) 范围内的更合理的分数:

xData = [
    int(random.random() * 41 + 60),
    int(random.random() * 41 + 60),
    int(random.random() * 41 + 60)
]

image

产生更多结果为 1 的训练数据,产生一个[93,101)范围内的符合三好学生要求的分数:

xData = [
    int(random.random() * 8 + 93),
    int(random.random() * 8 + 93),
    int(random.random() * 8 + 93)
]

为什么要使用随机数据来训练神经网络:

  • 并非“剧透”,用于演示和验证
  • 符合人工收集的规贝
  • 满足神经网络大规模训练的需要

训练

# import tensorflow as tf
import tensorflow.compat.v1 as tf
import random

tf.compat.v1.disable_eager_execution()

random.seed()

x = tf.placeholder(dtype=tf.float32)
yTrain = tf.placeholder(dtype=tf.float32)
w = tf.Variable(tf.zeros([3]), dtype=tf.float32)

wn = tf.nn.softmax(w)

n1 = wn * x

n2 = tf.reduce_sum(n1)
y = tf.nn.sigmoid(n2)
loss = tf.abs(yTrain - y)

optimizer = tf.train.RMSPropOptimizer(0.1)
train = optimizer.minimize(loss)

sess = tf.Session()
sess.run(tf.global_variables_initializer())

for i in range(5):
    xData = [
        int(random.random() * 8 + 93),
        int(random.random() * 8 + 93),
        int(random.random() * 8 + 93)
    ]

    xAll = xData[0] * 0.6 + xData[1] * 0.3 + xData[2] * 0.1

    if xAll >= 95:
        yTrainData = 1
    else:
        yTrainData = 0

    result = sess.run(
        [train, x, yTrain, w, n2, y, loss], 
        feed_dict={x:xData, yTrain:yTrainData}
    )

    print(result)

    xData = [
        int(random.random() * 41 + 60),
        int(random.random() * 41 + 60),
        int(random.random() * 41 + 60)
    ]

    xAll = xData[0] * 0.6 + xData[1] * 0.3 + xData[2] * 0.1

    if xAll >= 95:
        yTrainData = 1
    else:
        yTrainData = 0

    result = sess.run(
        [train, x, yTrain, w, n2, y, loss],
        feed_dict={x:xData, yTrain:yTrainData}
    )

    print(result)

观察训练结果:

image

增加偏移量 b 来加速训练:

+ b = tf.Variable(80, dtype=tf.float32)
- n2 = tf.reduce_sum(n1)
+ n2 = tf.reduce_sum(n1) - b
# import tensorflow as tf
import tensorflow.compat.v1 as tf
import random

tf.compat.v1.disable_eager_execution()

random.seed()

x = tf.placeholder(dtype=tf.float32)
yTrain = tf.placeholder(dtype=tf.float32)
w = tf.Variable(tf.zeros([3]), dtype=tf.float32)
b = tf.Variable(80, dtype=tf.float32)

wn = tf.nn.softmax(w)

n1 = wn * x
n2 = tf.reduce_sum(n1) - b

y = tf.nn.sigmoid(n2)
loss = tf.abs(yTrain - y)

optimizer = tf.train.RMSPropOptimizer(0.1)
train = optimizer.minimize(loss)

sess = tf.Session()
sess.run(tf.global_variables_initializer())

for i in range(5):
    xData = [
        int(random.random() * 8 + 93),
        int(random.random() * 8 + 93),
        int(random.random() * 8 + 93)
    ]

    xAll = xData[0] * 0.6 + xData[1] * 0.3 + xData[2] * 0.1

    if xAll >= 95:
        yTrainData = 1
    else:
        yTrainData = 0

    result = sess.run(
        [train, x, yTrain, w, n2, y, loss], 
        feed_dict={x:xData, yTrain:yTrainData}
    )

    print(result)

    xData = [
        int(random.random() * 41 + 60),
        int(random.random() * 41 + 60),
        int(random.random() * 41 + 60)
    ]

    xAll = xData[0] * 0.6 + xData[1] * 0.3 + xData[2] * 0.1

    if xAll >= 95:
        yTrainData = 1
    else:
        yTrainData = 0

    result = sess.run(
        [train, x, yTrain, w, n2, y, loss],
        feed_dict={x:xData, yTrain:yTrainData}
    )

    print(result)

image

- b = tf.Variable(80, dtype=tf.float32)
+ b = tf.Variable(95, dtype=tf.float32)

image

批量产生随机训练数据:

import random
import numpy as np

tf.compat.v1.disable_eager_execution()

random.seed()

rowCount = 5

xData = np.full(
    shape=(rowCount, 3),
    fill_value=0,
    dtype=np.float32
)

yTrainData = np.full(
    shape=rowCount,
    fill_value=0,
    dtype=np.float32
)

for i in range(rowCount):
    xData[i][0] = int(random.random() * 11 + 90)
    xData[i][1] = int(random.random() * 11 + 90)
    xData[i][2] = int(random.random() * 11 + 90)

    xAll = xData[i][0] * 0.6 + xData[i][0] * 0.3 + xData[i][2] * 0.1
  • numpy 是常用于数学计算的类库
  • npful 函数用于向数组中填充初始数值
  • 使用循环来生成批量的数据
# import tensorflow as tf
import tensorflow.compat.v1 as tf
import random
import numpy as np

tf.compat.v1.disable_eager_execution()

random.seed()

rowCount = 5

xData = np.full(
    shape=(rowCount, 3),
    fill_value=0,
    dtype=np.float32
)

yTrainData = np.full(
    shape=rowCount,
    fill_value=0,
    dtype=np.float32
)

goodCount = 0

for i in range(rowCount):
    xData[i][0] = int(random.random() * 11 + 90)
    xData[i][1] = int(random.random() * 11 + 90)
    xData[i][2] = int(random.random() * 11 + 90)

    xAll = xData[i][0] * 0.6 + xData[i][1] * 0.3 + xData[i][2] * 0.1

    if xAll >= 95:
        yTrainData[i] = 1
        goodCount = goodCount + 1
    else:
        yTrainData[i] = 0

print("xData=%s" %xData)
print("yTrainData=%s" %yTrainData)
print("goodCount=%s" %goodCount)

x = tf.placeholder(dtype=tf.float32)
yTrain = tf.placeholder(dtype=tf.float32)
w = tf.Variable(tf.zeros([3]), dtype=tf.float32)
b = tf.Variable(80, dtype=tf.float32)

wn = tf.nn.softmax(w)

n1 = wn * x
n2 = tf.reduce_sum(n1) - b

y = tf.nn.sigmoid(n2)
loss = tf.abs(yTrain - y)

optimizer = tf.train.RMSPropOptimizer(0.1)
train = optimizer.minimize(loss)

sess = tf.Session()
sess.run(tf.global_variables_initializer())

for i in range(2):
    for j in range(rowCount):
        result = sess.run(
            [train, x, yTrain, wn, b, n2, y, loss],
            feed_dict={x:xData[j], yTrain:yTrainData[j]}
        )
        print(result)

image

可以看到,xData 是一个二维数组,其中包含了 5 条数据,每条是 3 项符合定义范围的分数。tTrainData 中包含 3 个 1,也就是说有 3 位学生符合三好学生的条件,接下来输出的 goodCount 也确实等于 3,再往下的训练也一切正常。

练习

  1. 编程生成 5 [-20,20) 范围内的随机数,并用 TensorFlow 设法求出这些数字进行 sigmoid 操作后的结果。

    import tensorflow as tf
    import random
    
    a = tf.placeholder(dtype=tf.float32)
    b = tf.nn.sigmoid(a)
    sess = tf.Session()
    
    for i in range(5):
    	print(sess.run(b, feed_dict={a: random.random() * 40 - 20}))
    
  2. 编程解决下述非线性问题

    • 输入数据 [1,1,1],输出目标值:2
    • 输入数据 [1,0,1],输出目标值:1
    • 输入数据 [1,2,3],输出目标值:3
    import tensorflow as tf
    
    x = tf.placeholder(shape=[3], dtype=tf.float32)
    yTrain = tf.placeholder(shape=[], dtype=tf.float32)
    
    w = tf.Variable(tf.zeros([3]), dtype=tf.float32)
    b = tf.Variable(0, dtype=tf.float32)
    y = tf.reduce_sum(tf.nn.sigmoid(x * w + b))
    
    loss = tf.abs(y - yTrain)
    optimizer = tf.train.RMSPropOptimizer(0.1)
    train = optimizer.minimize(loss)
    
    sess = tf.Session()
    sess.run(tf.global_variables_initializer())
    
    for i in range(1000):
    	print(sess.run([train, y, yTrain, loss], feed_dict={x: [1, 1, 1], yTrain: 2}))
    	print(sess.run([train, y, yTrain, loss], feed_dict={x: [1, 0, 1], yTrain: 1}))
    	print(sess.run([train, y, yTrain, loss], feed_dict={x: [1, 2, 3], yTrain: 3}))
    
posted @ 2021-10-04 20:30  guangzan  阅读(499)  评论(0编辑  收藏  举报