tensorflow练习1-DNN

首先来一个最传统的网络, 最简单的练习, 预测一个两段的函数:
X> 0.5 ? X * 0.8 - 0.5 : -X * 0.6 + 0.2

import tensorflow as tf
import numpy as np

X = np.linspace(0, 0.99, 100).reshape(100, 1).astype(np.float32)
y = np.where(X> 0.5, X * 0.8 - 0.5, -X * 0.6 + 0.2)

plt.plot(y)
plt.show()

输出


image.png

定义构成网络的一些通用的函数:

def weight_variable(shape):
  initial = tf.truncated_normal(shape, stddev=0.1)
  return tf.Variable(initial)

def bias_variable(shape):
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)

def variable_summaries(var):
    pass

def nn_layer(input_tensor, input_dim, output_dim, layer_name, act=tf.nn.relu):
  with tf.name_scope(layer_name):
    # This Variable will hold the state of the weights for the layer
    with tf.name_scope('weights'):
      weights = weight_variable([input_dim, output_dim])
      variable_summaries(weights)
    with tf.name_scope('biases'):
      biases = bias_variable([output_dim])
      variable_summaries(biases)
    with tf.name_scope('Wx_plus_b'):
      preactivate = tf.matmul(input_tensor, weights) + biases
      tf.summary.histogram('pre_activations', preactivate)
    if act == None:
        activations = preactivate
    else:
        activations = act(preactivate, name='activation')
    tf.summary.histogram('activations', activations)
    return activations

定义网络:

x = tf.placeholder(dtype=tf.float32, shape=[None, 1], name="input")
label = tf.placeholder(tf.float32, [None, 1], name="label")

x_l2 = tf.nn.l2_normalize(x, dim=0)
hidden = None
hidden1 = hidden = nn_layer(x_l2, 1, 10, "layer1")
# hidden2 = nn_layer(hidden1, 10, 20, "layer2")
output = nn_layer(hidden, 10, 1, "layer2", act=None)

with tf.name_scope("loss"):
    loss = tf.reduce_mean(tf.square(output-label))

optimizer = tf.train.AdamOptimizer(learning_rate=0.05)
train = optimizer.minimize(loss)

# print(day.shape, label.shape)
tf.summary.scalar("loss", loss)
merged = tf.summary.merge_all()

训练网络,注意这个地方, 最外面是多次训练网络, 其原因在于最开始写的代码会导致结果收敛于局部最优解:

predicts = []
for j in range(2):
    with tf.Session() as sess: 
        train_writer = tf.summary.FileWriter('./summary/train_time1', sess.graph)
        tf.global_variables_initializer().run()

        for i in range(1000):
            if i % 50 == 0:
                _, summary, train_loss = sess.run([train, merged, loss], feed_dict={x: X, label: y})
                train_writer.add_summary(summary, i)
                print("step %d loss=%f"%(i, train_loss))
            else : 
                _, summary = sess.run([train, merged], feed_dict={x: X, label: y})
                train_writer.add_summary(summary, i)

        _loss, predict = sess.run([loss, output], feed_dict={x:X, label: y})
        print("try %d loss=%f"%(j, _loss))
        predicts.append(predict)

如果结果正常收敛: 画出结果

predict = predicts[0]
plt.figure()
plt.plot(predict, 'b')
plt.plot(y, 'r')
plt.show()

plt.figure(1)
plt.plot((predict - y))
plt.show()

print("loss", np.square(predict - y).T)
image.png

image.png

到现在为止, 小结一些遇到的问题:

  1. 最好按照一个通用俗称的代码习惯来命令一些入口, 和出口, 比如统一名称X, y, input, output, label什么的
  2. 这次是完全自己定义的结构和数据, 结果遇到一个问题, 出来的预测曲线始终是一条直线, 后来查了很久, 才发现是自己把自己坑了, 最后一个也使用了relu作为激活函数, 其直接结果就是relu只能输出正数或者0, 如何能输出负数部分的结果呢?
  3. 问题接踵而至, 预测结果总是还是输出一条直线, 只是偶尔会是正确的结果, 最开始把其倒数第二层的激活函数换成了tanh, 发现收敛速度大大变慢? 而且很大的几率出现直线的结果, 应该是陷入局部最优解, 或者参数都变成0, 无法继续学习了。后来找了一圈, 最后发现其实是网络太深了, 造成的, 试着把网络改成2层隐含层, 一层relu, 另外一层无激活函数, 结果ok, 而且训练速度大大加快。至于为什么, 我也是模模糊糊的感觉, 先不误导大家了, 自己思考下。
  4. 中间遇到过一个问题merged = tf.summary.merge_all()这句代码, 在jupyter notebook里面第二次运行的时候, 会把以前的x也统计进来, 导致后面_, summary = sess.run([train, merged], feed_dict={x: X, label: y})这句的时候, 并没有输入原来的placeholder对应的值, 自然就会失败, 提示错误, 目前看来重启整个kernel是最简单的解决方法。
  5. 那么留一个问题, 假设我的网络就是很深, 有没有好的办法避免出现局部最优解呢?

2017.11.24更新

batch norm

接着上面一个问题, 如何让网络比较深的时候, 也能成功收敛呢?
答案就是batch norm, 引入batch norm后, 哪怕网络再深一点, 也基本能成功收敛。
原理暂时不讲, 每个人都有自己的理解, 我的理解还很模糊。

直接上代码, 注意和前面的代码稍有不同的是, 我加了一些功能函数, 要模拟的数据变成了周期的数据, 也加入了噪音

import datetime
import time
import os
import shutil

def clear_summary():
    for root, dirs, files in os.walk("./summary/"):
        for d in dirs: 
            if d[:len('train_time')] == 'train_time':
                shutil.rmtree(os.path.join(root, d))

def get_time():
    ts = time.time()
    return datetime.datetime.fromtimestamp(ts).strftime('%Y%m%d-%H:%M:%S')

import tensorflow as tf
import numpy as np
from tensorflow.contrib.rnn import BasicLSTMCell
from matplotlib import pyplot as plt
import pandas as pd
from sklearn import preprocessing
import tensorflow as tf
import numpy as np

X = np.linspace(0, 99, 100).reshape(100, 1).astype(np.float32)
X_week = X % 7
# print(X_week)
X = np.hstack([X, X_week])
print(X.shape)
X_raw = X
scalerX = preprocessing.StandardScaler()
X_ = scalerX.fit_transform(X)

week_rate = [1.1, 1.3, 1.2, 1.1, 1.2, 2.8, 1.9]
y = np.linspace(3, 6, 100).reshape(100, 1)
for i in range(0, 100):
    y[i] = y[i] * week_rate[i%7]

noise = np.random.normal(0, 1, y.shape)
y = y + noise

# day = np.hstack([day, day_w])
scaler = preprocessing.StandardScaler()
y_raw = y
y = scaler.fit_transform(y)

plt.figure()
plt.plot(y_raw)
plt.plot(y)
plt.show()

X = X_
# print(X[:20])

def weight_variable(shape):
  initial = tf.truncated_normal(shape, stddev=0.1)
  return tf.Variable(initial)

def bias_variable(shape):
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)

def variable_summaries(var):
    pass

def nn_layer(input_tensor, input_dim, output_dim, layer_name, norm=True, act=tf.nn.relu):
  with tf.name_scope(layer_name):
    # This Variable will hold the state of the weights for the layer
    with tf.name_scope('weights'):
      weights = weight_variable([input_dim, output_dim])
      variable_summaries(weights)
    if norm != None: 
        with tf.name_scope('biases'):
          biases = bias_variable([output_dim])
          variable_summaries(biases)
    else:
        biases = 0
        
    with tf.name_scope('Wx_plus_b'):
      wx_b = tf.matmul(input_tensor, weights) + biases
      tf.summary.histogram('wx_b', wx_b)
        
    if norm:
        with tf.name_scope("norm"):
            fc_mean, fc_var = tf.nn.moments(wx_b,axes=[0])
            ema = tf.train.ExponentialMovingAverage(decay=0.5)  # exponential moving average 的 decay 度
            def mean_var_with_update():
                ema_apply_op = ema.apply([fc_mean, fc_var]) #TODO : what's this???
                with tf.control_dependencies([ema_apply_op]):
                    return tf.identity(fc_mean), tf.identity(fc_var)
            mean, var = mean_var_with_update()      # 根据新的 batch 数据, 记录并稍微修改之前的 mean/var
            epsilon = 0.001
            scale = tf.Variable(tf.ones([1]), name="norm_scale")
            shift = tf.Variable(tf.zeros([1]), name="norm_shift")
            # 将修改后的 mean / var 放入下面的公式
            preactivate = tf.nn.batch_normalization(wx_b, mean, var, shift, scale, epsilon)
    else:
        preactivate = wx_b
        
    if act == None:
        activations = preactivate
    else:
        activations = act(preactivate, name='activation')
    tf.summary.histogram('activations', activations)
    return activations

def add_fc():
    pass # 获得链式的写法
    
_layer_number = 0
def make_name():
    global _layer_number
    try :
        return "layer%d"%_layer_number    
    finally:
         _layer_number += 1


x = tf.placeholder(dtype=tf.float32, shape=[None, 2], name="input")
label = tf.placeholder(tf.float32, [None, 1], name="label")

hidden = None
hidden = nn_layer(x, 2, 10, make_name())
hidden = nn_layer(hidden, 10, 20, make_name())
hidden = nn_layer(hidden, 20, 10, make_name())
output = nn_layer(hidden, 10, 1, make_name(), act=None)

with tf.name_scope("loss"):
    loss = tf.reduce_mean(tf.square(output-label))

optimizer = tf.train.AdamOptimizer(learning_rate=0.05)
train = optimizer.minimize(loss)

# print(day.shape, label.shape)
tf.summary.scalar("loss", loss)
merged = tf.summary.merge_all()


predicts = []
clear_summary()
for j in range(1):
    with tf.Session() as sess: 
        train_writer = tf.summary.FileWriter('./summary/train_time' + get_time(), sess.graph)
        tf.global_variables_initializer().run()

        for i in range(1000):
            if i % 50 == 0:
                _, summary, train_loss = sess.run([train, merged, loss], feed_dict={x: X, label: y})
                train_writer.add_summary(summary, i)
                print("step %d loss=%f"%(i, train_loss))
            else : 
                _, summary = sess.run([train, merged], feed_dict={x: X, label: y})
                train_writer.add_summary(summary, i)

        _loss, predict = sess.run([loss, output], feed_dict={x:X, label: y})
        print("try %d loss=%f"%(j, _loss))
        predicts.append(predict)

print(X_raw[:, 0].shape, y_raw.shape)

for i in range(len(predicts)):
    plt.plot(scaler.inverse_transform(predicts[i]), 'b')
# plt.scatter(X_raw[:, 0].reshape(100, 1), y_raw, c='r')
plt.plot(y_raw, c='r')
plt.show()



# plt.figure()
# plt.plot(scaler.inverse_transform(predicts[1]), 'b')
# # plt.plot(predicts[0], 'b')
# plt.plot(y_raw, 'r')
# plt.show()


# print("loss", np.square(predict - y).T)
预测结果

遗留的问题:

  1. 如何不手动引入7的周期的情况下, 让网络自己学习到周期的问题呢?之前没有引入周期的时候, 网络只能学习到平均数, 不会学习到其中的周期变化。加深网络估计可以得到周期?只是我怀疑, 我加深网络的时候, 是否会过拟合?
  2. 没有分train&test

参考链接

原理解读:
深度学习(二十九)Batch Normalization 学习笔记
官网解读
batch_normalization
代码参考:
莫烦Python

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容