如何用神经网络解决CH5的线性问题?

摘要:了解非线性问题、分类问题 掌握神经网络解决二分类问题 掌握随机生成训练数据的方法 非线性问题 三好学生问题:家长们再次凑到一起,但这次情况不一样了,孩子们的总分不知道,仅知道是否评选上三好学生的结果。 计算总分的规则仍然是:总分 = 德育分
了解非线性问题、分类问题 掌握神经网络解决二分类问题 掌握随机生成训练数据的方法 非线性问题 三好学生问题:家长们再次凑到一起,但这次情况不一样了,孩子们的总分不知道,仅知道是否评选上三好学生的结果。 计算总分的规则仍然是:总分 = 德育分*60% + 智育分*30% + 体育分*10% 评选三好学生的标准是:总分 ≥ 95 家长不知道这两条规则。 这是一个典型的分类问题。学校一定是以德育分、智育分和体育分三项分数为依据,把学生们分成两类:三好学生和非三好学生。因此,这是一个常见的二分类问题。下图是用神经网络简述二分类问题。 分类问题一般是非线性的。 可以看出,当总分达到95之后,y值有一个跳变,并非线性的(一条直线) y=f(xA),跳变函数/阶跃函数 “一票否决制” 设计神经网络模型 总分(0~100)= 德育分60% + 智育分30% + 体育分*10% -> 评选结果(0、1) 激活函数:把线性关系转换成非线性关系的函数。激活函数 sigmoid 函数的作用是把参数转换成为 0 到 1 之间的一个小数。 使用激活函数后的神经网络模型: 实现该网络模型的代码: # 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) 优化产生的训练数据,产生一个[60,101) 范围内的更合理的分数: xData = [ int(random.random() * 41 + 60), int(random.random() * 41 + 60), int(random.random() * 41 + 60) ] 产生更多结果为 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) 观察训练结果: 增加偏移量 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) - b = tf.Variable(80, dtype=tf.float32) + b = tf.Variable(95, dtype=tf.float32) 批量产生随机训练数据: 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) 可以看到,xData 是一个二维数组,其中包含了 5 条数据,每条是 3 项符合定义范围的分数。tTrainData 中包含 3 个 1,也就是说有 3 位学生符合三好学生的条件,接下来输出的 goodCount 也确实等于 3,再往下的训练也一切正常。 练习 编程生成 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})) 编程解决下述非线性问题 输入数据 [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}))