tensorflow1迁移2尝试

最近跟着看了一篇博文《深度学习之卷积神经网络CNN及tensorflow代码实现示例》,学习着里面的代码,但是遇到了问题,那就是发现里面很多是tensorflow1的代码,而我用的是tensorflow2。以这个为例子,研究tensorflow1到2的转换。

简单方法-直接用tf1兼容

tf2直接全局转为tf1,这样代码很快就跑起来了。

import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()

但是,这样没有办法真正让我们掌握tf2,也无法了解其精髓。因此,考虑完全将代码转为tf2。

tf_upgrade_v2转换工具

听说有个tf_upgrade_v2的工具可以快速转换,目前正在研究中。
不过目前经常报错:
‘gbk’ codec can’t decode byte 0x89 in position 561: illegal multibyte sequence
而且根据博文《使用 tf_upgrade_v2 命令把 tensorflow1.x 的代码快速转换成 tensorflow2.0》的转化结果,这里转化的方法,很多函数也只是自动帮你加入了tf.compat.v1,并没有办法真正把你的代码变为tf2的,只能说暂时过渡。
因此,最好还是慢慢搞懂里面的函数,学习经验,彻底代替。

函数API手动替换

学习了《tensorflow 1.X迁移至tensorflow2 的代码写法》,觉得可以逐步替换函数,同时真正了解tf1与tf2的区别。
tf1基于图模式,tf2基于eager模式,tf2更便于我们编程和调试,尽管目前tf1的代码很多,学习tf1的代码时,应该学习其思想,将其以tf2重新实现。

语法的基本改变

首先,print函数这个会报错,因为旧版本python不用加括号,新版本应该加上括号。
诸如此类的代码:

print X_data.shape

改为:

print (X_data.shape)

采用兼容性语句

有许多函数数,由于学习时间短,我暂时没有好的解决方法,只能是加上tf.compat.v1.这样用了

tf.compat.v1.function()

像tf.reset_default_graph函数,h函数用于清除默认图形堆栈并重置全局默认图形

tf.reset_default_graph()

优化器的选择函数

train_step = tf.train.AdamOptimizer(1e-3).minimize(loss)

值得注意的是,这里还得关闭eager模式

tf.compat.v1.disable_eager_execution()

当然,等后面完全迁移成功后,自然我们要转入这一模式的,但是前期一步步来,慢慢学习如何兼容。

更换为最新的函数

自然,有许多函数我们是可以找到最新的名称的,使用上新的名字或者功能。
tf.placeholder函数,生成占位符

tf_X = tf.placeholder(tf.float32,[None,8,8,1])

考虑采用keras的input函数代替。

tf_X = keras.Input(dtype=tf.float32,shape=[8,8,1])

tf.random_normal用于从“服从指定正态分布的序列”中随机取出指定个数的值

conv_filter_w1 = tf.Variable(tf.random_normal([3, 3, 1, 10]))

这个随机数生成,改起来较为容易

conv_filter_w1 = tf.Variable(tf.random.normal([3, 3, 1, 10]))

tf.nn.moments()函数用于计算均值和方差

 tf.nn.moments(conv_out2, [0, 1, 2], keep_dims=True)

它变动的只是入口参数:

batch_mean, batch_var = tf.nn.moments(conv_out2, [0, 1, 2], shift=None,keepdims=True,name=None)

数学函数,如像计算对数的tf.log、tf.arg_max(input,axis)根据axis取值的不同返回每行或者每列最大值的索引,主要是都归于math之下了。

tf.math.log()
tf.math.argmax(pred,1)

基本思想的改变

到目前为止,也只是简单的函数名改换,还没有涉及tf1和tf2的根本区别。
目前,暂时还无法对session这一块进行改造,因为对于eager模式和图模式的了解还有限,而这也是讲tf1升级为tf2中,感觉是最重要的地方。
tf2的eager模式,让我们很多函数的执行可以无需借助sess.run。

tf.Session() 创建一个新的TensorFlow会话

with tf.Session() as sess

tf.global_variables_initializer()函数

tf.global_variables_initializer()

另外,程序中仍然充斥着大量的sess.run,改完后的训练部分代码如下:

#with tf.Session() as sess:
with tf.compat.v1.Session() as sess:    
    #sess.run(tf.global_variables_initializer())
    sess.run(tf.compat.v1.global_variables_initializer())
    for epoch in range(1000): # 迭代1000个周期
        for batch_xs,batch_ys in generatebatch(X,Y,Y.shape[0],batch_size): # 每个周期进行MBGD算法
            sess.run(train_step,feed_dict={tf_X:batch_xs,tf_Y:batch_ys})
        if(epoch%100==0):
            res = sess.run(accuracy,feed_dict={tf_X:X,tf_Y:Y})
            print (epoch,res)
    res_ypred = y_pred.eval(feed_dict={tf_X:X,tf_Y:Y}).flatten() # 只能预测一批样本,不能预测一个样本
    print (res_ypred) 

实际上,tf2中,sess.run根本无需使用,期望写成的代码是:


for epoch in range(1000): # 迭代1000个周期
    for batch_xs,batch_ys in generatebatch(X,Y,Y.shape[0],batch_size): # 每个周期进行MBGD算法
        train_step=model.cal_train_step(batch_xs,batch_ys)
    if(epoch%100==0):
        res = accuracy=model.cal_accuray(X,Y)
        print (epoch,res)
res_ypred = y_pred.eval(feed_dict={tf_X:X,tf_Y:Y}).flatten() # 只能预测一批样本,不能预测一个样本
print (res_ypred) 

这里的model这个类还没有建立好,但是目前的设计思想是这样,可以把整个网络封装为一个类,步长和精度的计算作为其中一个方法,在循环中调用,让代码变得面向对象,真正发挥tf2的优势。

你可能感兴趣的:(深度学习,tensorflow,迁移学习,python)