tensorflow兼容处理 tensorflow.compat.v1 tf.contrib
20201130
問題提出:
v1版本中tensorflow中contrib模塊十分豐富,但是發(fā)展不可控,因此在v2版本中將這個模塊集成到其他模塊中去了。在學習tensorflow經(jīng)常碰到tf.contrib的代碼,一敲就報錯。
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()weight=tf.constant([[1.0,2.0],[-3.0,-4.0]])
regularizer_l2=tf.contrib.layers.l2_regularizer(.5)
regularizer_l1=tf.contrib.layers.l1_regularizer(.5)
with tf.Session() as sess:print(sess.run(regularizer_l2(weight)))print(sess.run(regularizer_l1(weight)))
會報錯:
?
?
解決方案1:
自己寫函數(shù),這需要對原理的理解(比如上面L2正則化),如果本身有實力可以自己寫。但對于小白顯然不可取。
解決方案2:
卸載v2版本TensorFlow,重新下載v1版本TensorFlow,同時適配各類軟件及軟件包,較為麻煩。由于v2都能配置好,卸掉重新配置v1版本也不是什么問題。因此在這里不予討論。
解決方案3:
首先查看官方文檔說明:
https://tensorflow.google.cn/versions/r1.15/api_docs/python/tf/contrib?hl=en
https://tensorflow.google.cn/guide/migrate#a_note_on_slim_contriblayers
發(fā)現(xiàn)contrib的內(nèi)容可以集成到下面三個包中。
tf.keras.layers.Layer
tf.keras.Model
tf.Module
因此,嘗試以后,發(fā)現(xiàn)L2正則化存在于tf.keras里面。
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()weight=tf.constant([[1.0,2.0],[-3.0,-4.0]])
regularizer_l2=tf.keras.regularizers.l2(.5)
regularizer_l1=tf.keras.regularizers.l1(.5)
with tf.Session() as sess:print(sess.run(regularizer_l2(weight)))print(sess.run(regularizer_l1(weight)))
?
?
引言
原來引用過一個段子,這里還要再引用一次。是關于蘋果的。大意是,蘋果發(fā)布了新的開發(fā)語言Swift,有非常多優(yōu)秀的特征,于是很多時髦的程序員入坑學習。不料,經(jīng)過一段頭腦體操一般的勤學苦練,發(fā)現(xiàn)使用Swift做開發(fā),不僅要學習Swift,還要學習Swift2、Swift3、Swift4...
后來我發(fā)現(xiàn),這個段子很有普遍性,并非僅僅蘋果如此,今天的TensorFlow 2.0也有點這樣的趨勢。以至于我不得不專門寫一個課程的續(xù)集,來面對使用新版本軟件開始機器學習的讀者。
事實上大多具有革命性的公司都是這樣,一方面帶來令人興奮的新特征,另一方面則是高企不落的學習成本。
《從鍋爐工到AI專家》一文中,已經(jīng)對機器學習的基本概念做了很詳細的介紹。所以在這里我們就省掉閑言絮語,直接從TensorFlow2.0講起。
當然即便沒有看過這個系列,假設你對TensorFlow 1.x很熟悉,也可以直接通過閱讀本文,了解從TensorFlow 1.x遷移至2.x的知識。
如果你不了解機器學習的概念,試圖通過直接學習TensorFlow 2.0開始AI開發(fā),那可能比較困難。TensorFlow只是工具。沒有技能,只憑工具,你恐怕無法踏上旅程。
安裝
截至本文寫作的時候,TensorFlow 2.0尚未正式的發(fā)布。pip倉庫中仍然是1.13穩(wěn)定版。所以如果想開始TensorFlow 2.0的學習,需要指定版本號來安裝。此外由于Python2系列將于2020年元月停止官方維護,本文的示例使用Python3的代碼來演示:
$ pip3 install tensorflow==2.0.0-alpha0 (注: 上面$是Mac/Linux的提示符,假如用Windows,你看到的提示符應當類似C:\Users\Administrator>這樣子。)
如果希望使用GPU計算,安裝的預先準備會麻煩一些,請參考這篇文檔:https://www.tensorflow.org/install/gpu。主要是安裝CUDA/cuDNN等計算平臺的工具包。其中CUDA可以使用安裝程序直接安裝。cuDNN是壓縮包,如果不打算自己編譯TensorFlow的話,放置到CUDA相同目錄會比較省事。
這里提醒一下,除非自己編譯TensorFlow,否則一定使用CUDA 10.0的版本,低了、高了都不成,因為官方的2.0.0-alpha0使用了CUDA 10.0的版本編譯。
此外TensorFlow的安裝請使用如下命令:
$ pip3 install tensorflow-gpu==2.0.0-alpha0 安裝完成后,可以在Python的交互模式,來確認TensorFlow正常工作:
$ python3
Python 3.7.2 (default, Feb 13 2019, 13:59:29)
[Clang 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow as tf
>>> tf.__version__
'2.0.0-alpha0'
>>> 本文中還會用到幾個第三方的python擴展庫,也是在機器學習中非常常用的,建議一起安裝:
$ pip3 install numpy matplotlib pillow pandas seaborn sklearn 第一個例子:房價預測
本示例中的源碼來自于《從鍋爐工到AI專家》系列2,使用了最簡單的線性函數(shù)來做房價預測。原始TensorFlow 1.x/ Python 2.x代碼如下:
#!/usr/bin/env python
# -*- coding=UTF-8 -*-#本代碼在mac電腦,python2.7環(huán)境測試通過
#第一行是mac/Linux系統(tǒng)腳本程序的標志,表示從環(huán)境參量中尋找python程序解釋器來執(zhí)行本腳本
#省去了每次在命令行使用 python <腳本名> 這樣的執(zhí)行方式
#第二行表示本腳本文本文件存盤使用的代碼是utf-8,并且字符串使用的編碼也是utf-8,
#在本源碼中,這一點其實沒有什么區(qū)別,但如果需要中文輸出的時候,這一行就必須要加了。#引入TensorFlow庫
import tensorflow as tf
#引入數(shù)值計算庫
import numpy as np#使用 NumPy 生成假數(shù)據(jù)集x,代表房間的平米數(shù),這里的取值范圍是0-1的浮點數(shù),
#原因請看正文中的說明,屬于是“規(guī)范化”之后的數(shù)據(jù)
# 生成的數(shù)據(jù)共100個,式樣是100行,每行1個數(shù)據(jù)
x = np.float32(np.random.rand(100,1))
#我們假設每平米0.5萬元,基礎費用0.7萬,這個數(shù)值也是規(guī)范化之后的,僅供示例
#最終運行的結(jié)果,應當求出來0.5/0.7這兩個值代表計算成功
#計算最終房價y,x和y一同當做我們的樣本數(shù)據(jù)
# np.dot的意思就是向量x * 0.5
y = np.dot(x,0.5) + 0.7
#---------------------------------數(shù)據(jù)集準備完成
#以下使用TensorFlow構(gòu)建數(shù)學模型,在這個過程中,
#直到調(diào)用.run之前,實際上都是構(gòu)造模型,而沒有真正的運行。
#這跟上面的numpy庫每一次都是真正執(zhí)行是截然不同的區(qū)別
# 請參考正文,我們假定房價的公式為:y=a*x+b#tf.Variable是在TensorFlow中定義一個變量的意思
#我們這里簡單起見,人為給a/b兩個初始值,都是0.3,注意這也是相當于規(guī)范化之后的數(shù)值
b = tf.Variable(np.float32(0.3))
a = tf.Variable(np.float32(0.3))#這是定義主要的數(shù)學模型,模型來自于上面的公式
#注意這里必須使用tf的公式,這樣的公式才是模型
#上面使用np的是直接計算,而不是定義模型
# TensorFlow的函數(shù)名基本就是完整英文,你應當能讀懂
y_value = tf.multiply(x,a) + b# 這里是代價函數(shù),同我們文中所講的唯一區(qū)別是用平方來取代求絕對值,
#目標都是為了得到一個正數(shù)值,功能完全相同,
#平方計算起來會更快更容易,這種方式也稱為“方差“
loss = tf.reduce_mean(tf.square(y_value - y))
# TensorFlow內(nèi)置的梯度下降算法,每步長0.5
optimizer = tf.train.GradientDescentOptimizer(0.5)
# 代價函數(shù)值最小化的時候,代表求得解
train = optimizer.minimize(loss)# 初始化所有變量,也就是上面定義的a/b兩個變量
init = tf.global_variables_initializer()#啟動圖
sess = tf.Session()
#真正的執(zhí)行初始化變量,還是老話,上面只是定義模型,并沒有真正開始執(zhí)行
sess.run(init)#重復梯度下降200次,每隔5次打印一次結(jié)果
for step in xrange(0, 200):sess.run(train) if step % 5 == 0:print step, sess.run(loss),sess.run(a), sess.run(b) 代碼保留了原始的注釋,希望如果概念已經(jīng)沒有問題的話,可以讓你不用跑回原文去看詳細講解。
程序使用numpy生成了一組樣本集,樣本集是使用線性函數(shù)生成的。隨后使用TensorFlow學習這些樣本,從而得到線性函數(shù)中未知的權重(Weight)和偏移(Bias)值。
原文中已經(jīng)說了,這個例子并沒有什么實用價值,只是為了從基礎開始講解“機器學習”的基本原理。
使用2.0中的v1兼容包來沿用1.x代碼
TensorFlow 2.0中提供了tensorflow.compat.v1代碼包來兼容原有1.x的代碼,可以做到幾乎不加修改的運行。社區(qū)的contrib庫因為涉及大量直接的TensorFlow引用代碼或者自己寫的Python擴展包,所以無法使用這種模式。TensorFlow 2.0中也已經(jīng)移除了contrib庫,這讓人很有點小遺憾的。
使用這種方式升級原有代碼,只需要把原有程序開始的TensorFlow引用:
import tensorflow as tf 替換為以下兩行就可以正常的繼續(xù)使用:
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior() 其它代碼無需修改。個人覺得,如果是穩(wěn)定使用中、并且沒有重構(gòu)意愿的代碼,這種方式算的上首選。
使用遷移工具來自動遷移1.x代碼到2.0
TensorFlow 2.0中提供了命令行遷移工具,來自動的把1.x的代碼轉(zhuǎn)換為2.0的代碼。工具使用方法如下(假設我們的程序文件名稱為first-tf.py):
tf_upgrade_v2 --infile first-tf.py --outfile first-tf-v2.py 遷移工具還可以對整個文件夾的程序做升級,請參考工具自身的幫助文檔。
使用遷移工具升級的代碼,實質(zhì)上也是使用了tensorflow.compat.v1兼容包來提供在TensorFlow 2.0環(huán)境中執(zhí)行1.x的代碼。這里貼出自動轉(zhuǎn)換后的新代碼供你對比參考:
#引入TensorFlow庫
import tensorflow as tf
#import tensorflow.compat.v1 as tf
tf.compat.v1.disable_v2_behavior()#引入數(shù)值計算庫
import numpy as np#使用 NumPy 生成假數(shù)據(jù)集x,代表房間的平米數(shù),這里的取值范圍是0-1的浮點數(shù),
#原因請看正文中的說明,屬于是“規(guī)范化”之后的數(shù)據(jù)
# 生成的數(shù)據(jù)共100個,式樣是100行,每行1個數(shù)據(jù)
x = np.float32(np.random.rand(100,1))
#我們假設每平米0.5萬元,基礎費用0.7萬,這個數(shù)值也是規(guī)范化之后的,僅供示例
#最終運行的結(jié)果,應當求出來0.5/0.7這兩個值代表計算成功
#計算最終房價y,x和y一同當做我們的樣本數(shù)據(jù)
# np.dot的意思就是向量x * 0.5
y = np.dot(x,0.5) + 0.7
#---------------------------------數(shù)據(jù)集準備完成
#以下使用TensorFlow構(gòu)建數(shù)學模型,在這個過程中,
#直到調(diào)用.run之前,實際上都是構(gòu)造模型,而沒有真正的運行。
#這跟上面的numpy庫每一次都是真正執(zhí)行是截然不同的區(qū)別
# 請參考正文,我們假定房價的公式為:y=a*x+b#tf.Variable是在TensorFlow中定義一個變量的意思
#我們這里簡單起見,人為給a/b兩個初始值,都是0.3,注意這也是相當于規(guī)范化之后的數(shù)值
b = tf.Variable(np.float32(0.3))
a = tf.Variable(np.float32(0.3))#這是定義主要的數(shù)學模型,模型來自于上面的公式
#注意這里必須使用tf的公式,這樣的公式才是模型
#上面使用np的是直接計算,而不是定義模型
# TensorFlow的函數(shù)名基本就是完整英文,你應當能讀懂
y_value = tf.multiply(x,a) + b# 這里是代價函數(shù),同我們文中所講的唯一區(qū)別是用平方來取代求絕對值,
#目標都是為了得到一個正數(shù)值,功能完全相同,
#平方計算起來會更快更容易,這種方式也稱為“方差“
loss = tf.reduce_mean(input_tensor=tf.square(y_value - y))
# TensorFlow內(nèi)置的梯度下降算法,每步長0.5
optimizer = tf.compat.v1.train.GradientDescentOptimizer(0.5)
# 代價函數(shù)值最小化的時候,代表求得解
train = optimizer.minimize(loss)# 初始化所有變量,也就是上面定義的a/b兩個變量
init = tf.compat.v1.global_variables_initializer()#啟動圖
sess = tf.compat.v1.Session()
#真正的執(zhí)行初始化變量,還是老話,上面只是定義模型,并沒有真正開始執(zhí)行
sess.run(init)#重復梯度下降200次,每隔5次打印一次結(jié)果
for step in range(0, 200):sess.run(train) if step % 5 == 0:print(step, sess.run(loss),sess.run(a), sess.run(b))
轉(zhuǎn)換之后,代碼中的注釋部分會完美的保留,喜歡用代碼來代替文檔的程序員可以放心。所有2.0中變更了的類或者方法,轉(zhuǎn)換工具將使用tensorflow.compat.v1中的對應類或方法來替代,比如:
optimizer = tf.compat.v1.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)
init = tf.compat.v1.global_variables_initializer() 所以從本質(zhì)上,這種方式跟第一種方法,采用tensorflow.compat.v1包作為tensorflow替代包的方式是完全相同的。
編寫原生的TensorFlow 2.0程序
推薦的演進方式,當然還是學習TensorFlow 2.0的相關特征,重構(gòu)原有代碼為新版本代碼才是正路。平心而論,畢竟絕大多數(shù)系統(tǒng)的升級都是為了提供更多功能和降低使用門檻。TensorFlow 2.0也是大幅的降低了使用門檻的。大多數(shù)的工作比起1.x版本來,都能使用更少的代碼量來完成。
首先了解一下TensorFlow 2.0同1.x之間的重要區(qū)別:
- 在API層面的類、方法有了較大的變化,這個需要在使用中慢慢熟悉
- 取消了Session機制,每一條命令直接執(zhí)行,而不需要等到Session.run
- 因為取消了Session機制,原有的數(shù)學模型定義,改為使用Python函數(shù)編寫。原來的feed_dict和tf.placeholder,成為了函數(shù)的輸入部分;原來的fetches,則成為了函數(shù)的返回值。
- 使用keras的模型體系對原有的TensorFlow API進行高度的抽象,使用更容易
- 使用tf.keras.Model.fit來替代原有的訓練循環(huán)。
正常情況下,最后一項tf.keras.Model.fit能夠大大的降低訓練循環(huán)的代碼量。但在本例中,我們模擬了一個現(xiàn)實中并不適用的例子,keras中并未對這種情形進行優(yōu)化。所以在本例中反而無法使用tf.keras.Model.fit(實際上一定要使用也是可以的,不過要自定義模型,工作量更不劃算)。因此本例中仍然要自己編寫訓練循環(huán)。并且因為2.0中API的變化,代碼更復雜了。不過相信我,等到比較正式應用中,使用神經(jīng)網(wǎng)絡、卷積等常用算法,代碼就極大的簡化了。
使用TensorFlow 2.0原生代碼的程序代碼如下:
#!/usr/bin/env python3
#上面一行改為使用python3解釋本代碼#引入python新版本的語言特征
from __future__ import absolute_import, division, print_function#引入TensorFlow庫,版本2.0
import tensorflow as tf#引入數(shù)值計算庫
import numpy as np#使用 NumPy 生成假數(shù)據(jù)集x,代表房間的平米數(shù),這里的取值范圍是0-1的浮點數(shù),
#原因請看正文中的說明,屬于是“規(guī)范化”之后的數(shù)據(jù)
# 生成的數(shù)據(jù)共100個,式樣是100行,每行1個數(shù)據(jù)
x = np.float32(np.random.rand(100,1))
#我們假設每平米0.5萬元,基礎費用0.7萬,這個數(shù)值也是規(guī)范化之后的,僅供示例
#最終運行的結(jié)果,應當求出來0.5/0.7這兩個值代表計算成功
#計算最終房價y,x和y一同當做我們的樣本數(shù)據(jù)
y = np.dot(x,0.5) + 0.7
#---------------------------------數(shù)據(jù)集準備完成
# 請參考正文,我們假定房價的公式為:y=a*x+b
#定義tensorflow變量,a是權重,b是偏移
b = tf.Variable(np.float32(0.3))
a = tf.Variable(np.float32(0.3))#以上代碼基本同tensorflow1.x版本一致
#以下有了區(qū)別
#使用python語言定義數(shù)學模型,模型來自于上面的公式
#上面使用np的是直接計算得到訓練樣本,而不是定義模型
#模型中并非必須使用tensorflow的計算函數(shù)來代替python的乘法運算
@tf.function
def model(x):return a*x+b#定義代價函數(shù),也是python函數(shù)
def loss(predicted_y, desired_y):return tf.reduce_sum(tf.square(predicted_y - desired_y))# TensorFlow內(nèi)置Adam算法,每步長0.1
optimizer = tf.optimizers.Adam(0.1)
# 還可以選用TensorFlow內(nèi)置SGD(隨機最速下降)算法,每步長0.001
#不同算法要使用適當?shù)牟介L,步長過大會導致模型無法收斂
#optimizer = tf.optimizers.SGD(0.001)#重復梯度下降200次,每隔5次打印一次結(jié)果
for step in range(0, 200):with tf.GradientTape() as t:outputs = model(x) #進行一次計算current_loss = loss(outputs, y) #得到當前損失值grads = t.gradient(current_loss, [a, b]) #調(diào)整模型中的權重、偏移值optimizer.apply_gradients(zip(grads,[a, b])) #調(diào)整之后的值代回到模型if step % 5 == 0: #每5次迭代顯示一次結(jié)果print( "Step:%d loss:%%%2.5f weight:%2.7f bias:%2.7f " % (step,current_loss.numpy(), a.numpy(), b.numpy())) 程序在升級中所做的修改和特殊的處理,都使用注釋保留在了源碼中。我覺得這種方式比打散摘出來講解的能更透徹。
最后看一下新版程序的執(zhí)行結(jié)果:
Step:0 loss:%25.78244 weight:0.4000000 bias:0.4000000
Step:5 loss:%2.71975 weight:0.7611420 bias:0.7740188
Step:10 loss:%3.09600 weight:0.6725605 bias:0.7224629
Step:15 loss:%0.87834 weight:0.4931822 bias:0.5800986
Step:20 loss:%1.24737 weight:0.4960071 bias:0.6186275
Step:25 loss:%0.22444 weight:0.5730734 bias:0.7264798
Step:30 loss:%0.47145 weight:0.5464076 bias:0.7252067
Step:35 loss:%0.09156 weight:0.4736322 bias:0.6712209
Step:40 loss:%0.14845 weight:0.4771673 bias:0.6866464
Step:45 loss:%0.06199 weight:0.5101752 bias:0.7255269
Step:50 loss:%0.03108 weight:0.4946054 bias:0.7112849
Step:55 loss:%0.04115 weight:0.4770990 bias:0.6918764
Step:60 loss:%0.00145 weight:0.4950625 bias:0.7060429
Step:65 loss:%0.01781 weight:0.5029647 bias:0.7096580
Step:70 loss:%0.00211 weight:0.4934593 bias:0.6963260
Step:75 loss:%0.00298 weight:0.4983235 bias:0.6982682
Step:80 loss:%0.00345 weight:0.5049748 bias:0.7031375
Step:85 loss:%0.00004 weight:0.5001755 bias:0.6976562
Step:90 loss:%0.00102 weight:0.5002422 bias:0.6978318
Step:95 loss:%0.00065 weight:0.5029225 bias:0.7010939
Step:100 loss:%0.00001 weight:0.5000774 bias:0.6990223
Step:105 loss:%0.00021 weight:0.4996552 bias:0.6993059
Step:110 loss:%0.00015 weight:0.5007215 bias:0.7008768
Step:115 loss:%0.00000 weight:0.4993480 bias:0.6997767
Step:120 loss:%0.00003 weight:0.4995552 bias:0.7000407
Step:125 loss:%0.00004 weight:0.5001000 bias:0.7004969
Step:130 loss:%0.00001 weight:0.4995880 bias:0.6998325
Step:135 loss:%0.00000 weight:0.4999941 bias:0.7000810
Step:140 loss:%0.00001 weight:0.5001197 bias:0.7000892
Step:145 loss:%0.00000 weight:0.4999250 bias:0.6998329
Step:150 loss:%0.00000 weight:0.5001498 bias:0.7000451
Step:155 loss:%0.00000 weight:0.5000388 bias:0.6999565
Step:160 loss:%0.00000 weight:0.4999948 bias:0.6999494
Step:165 loss:%0.00000 weight:0.5000526 bias:0.7000424
Step:170 loss:%0.00000 weight:0.4999576 bias:0.6999717
Step:175 loss:%0.00000 weight:0.4999971 bias:0.7000214
Step:180 loss:%0.00000 weight:0.4999900 bias:0.7000131
Step:185 loss:%0.00000 weight:0.4999775 bias:0.6999928
Step:190 loss:%0.00000 weight:0.5000094 bias:0.7000152
Step:195 loss:%0.00000 weight:0.4999923 bias:0.6999906 模型通過學習后,得到的結(jié)果是很接近我們的預設值的。
程序中還可以考慮使用隨機快速下降算法(SGD),你可以把當前的Adam算法使用注釋符屏蔽上,打開SGD算法的注釋屏蔽來嘗試一下。對于本例中的數(shù)據(jù)集來講,SGD的下降步長需要的更小,同樣循環(huán)次數(shù)下,求解的精度會低一些。可以看出對于本例,Adam算法顯然是更有效率的。而在TensorFlow的支持下,對于同樣的數(shù)據(jù)集和數(shù)學模型,變更學習算法會很容易。
(待續(xù)...)
?
https://www.wandouip.com/t5i183316/
相關文章
總結(jié)
以上是生活随笔為你收集整理的tensorflow兼容处理 tensorflow.compat.v1 tf.contrib的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ImportError: No modu
- 下一篇: python if elif else