摘要:最值得注意的一點是,整個圖都是在一個函數中定義和構造的,那么這即不可讀也不可重復使用。
在 TensorFlow 中定義你的模型,可能會導致一個巨大的代碼量。那么,如何去組織代碼,使得它是一個高可讀性和高可重用的呢?如果你剛剛開始學習代碼架構,那么這里有一個例子,不妨學習一下。
定義計算圖
當你設計一個模型的時候,從類出發是一個非常好的開始。那么如何來設計一個類的接口呢?通常,我們會為模型設計一些輸入接口和輸出目標值,并且提供訓練接口,驗證接口,測試接口等等。
class
?
Model
:
? ??
def
?__init__
(
self
,
?data
,
?target
):
? ? ? ? data_size?
=
?
int
(
data
.
get_shape
()[
1
])
? ? ? ? target_size?
=
?
int
(
target
.
get_shape
()[
1
])
? ? ? ? weight?
=
?tf
.
Variable
(
tf
.
truncated_normal
([
data_size
,
?target_size
]))
? ? ? ? bias?
=
?tf
.
Variable
(
tf
.
constant
(
0.1
,
?shape
=[
target_size
]))
? ? ? ? incoming?
=
?tf
.
matmul
(
data
,
?weight
)
?
+
?bias
? ? ? ??
self
.
_prediction?
=
?tf
.
nn
.
softmax
(
incoming
)
? ? ? ? cross_entropy?
=
?
-
tf
.
reduce_sum
(
target
,
?tf
.
log
(
self
.
_prediction
))
? ? ? ??
self
.
_optimize?
=
?tf
.
train
.
RMSPropOptimizer
(
0.03
).
minimize
(
cross_entropy
)
? ? ? ? mistakes?
=
?tf
.
not_equal
(
? ? ? ? ? ? tf
.
argmax
(
target
,
?
1
),
?tf
.
argmax
(
self
.
_prediction
,
?
1
))
? ? ? ??
self
.
_error?
=
?tf
.
reduce_mean
(
tf
.
cast
(
mistakes
,
?tf
.
float32
))
? ??
@property
? ??
def
?prediction
(
self
):
? ? ? ??
return
?
self
.
_prediction
? ??
@property
? ??
def
?optimize
(
self
):
? ? ? ??
return
?
self
.
_optimize
? ??
@property
? ??
def
?error
(
self
):
? ? ? ??
return
?
self
.
_error
基本上,我們都會使用 TensorFlow 提供的代碼塊來構建我們的模型。但是,它也存在一些問題。最值得注意的一點是,整個圖都是在一個函數中定義和構造的,那么這即不可讀也不可重復使用。
使用 @property 裝飾器
如果你不了解裝飾器,那么可以先學習這篇文章。
如果我們只是把代碼分割成函數,這肯定是行不通的,因為每次調用函數時,圖都會被新代碼進行擴展。因此,我們要確保只有當函數第一次被調用時,這個操作才會被添加到圖中。這個方式就是懶加載(lazy-loading,使用時才創建)。
class
?
Model
:
? ??
def
?__init__
(
self
,
?data
,
?target
):
? ? ? ??
self
.
data?
=
?data
? ? ? ??
self
.
target?
=
?target
? ? ? ??
self
.
_prediction?
=
?
None
? ? ? ??
self
.
_optimize?
=
?
None
? ? ? ??
self
.
_error?
=
?
None
? ??
@property
? ??
def
?prediction
(
self
):
? ? ? ??
if
?
not
?
self
.
_prediction
:
? ? ? ? ? ? data_size?
=
?
int
(
self
.
data
.
get_shape
()[
1
])
? ? ? ? ? ? target_size?
=
?
int
(
self
.
target
.
get_shape
()[
1
])
? ? ? ? ? ? weight?
=
?tf
.
Variable
(
tf
.
truncated_normal
([
data_size
,
?target_size
]))
? ? ? ? ? ? bias?
=
?tf
.
Variable
(
tf
.
constant
(
0.1
,
?shape
=[
target_size
]))
? ? ? ? ? ? incoming?
=
?tf
.
matmul
(
self
.
data
,
?weight
)
?
+
?bias
? ? ? ? ? ??
self
.
_prediction?
=
?tf
.
nn
.
softmax
(
incoming
)
? ? ? ??
return
?
self
.
_prediction
? ??
@property
? ??
def
?optimize
(
self
):
? ? ? ??
if
?
not
?
self
.
_optimize
:
? ? ? ? ? ? cross_entropy?
=
?
-
tf
.
reduce_sum
(
self
.
target
,
?tf
.
log
(
self
.
prediction
))
? ? ? ? ? ? optimizer?
=
?tf
.
train
.
RMSPropOptimizer
(
0.03
)
? ? ? ? ? ??
self
.
_optimize?
=
?optimizer
.
minimize
(
cross_entropy
)
? ? ? ??
return
?
self
.
_optimize
? ??
@property
? ??
def
?error
(
self
):
? ? ? ??
if
?
not
?
self
.
_error
:
? ? ? ? ? ? mistakes?
=
?tf
.
not_equal
(
? ? ? ? ? ? ? ? tf
.
argmax
(
self
.
target
,
?
1
),
?tf
.
argmax
(
self
.
prediction
,
?
1
))
? ? ? ? ? ??
self
.
_error?
=
?tf
.
reduce_mean
(
tf
.
cast
(
mistakes
,
?tf
.
float32
))
? ? ? ??
return
?
self
.
_error
這個代碼組織已經比第一個代碼好很多了。你的代碼現在被組織成一個多帶帶的功能。但是,由于懶加載的邏輯,這個代碼看起來還是有點臃腫。讓我們來看看如何可以改進這個代碼。
Python 是一種相當靈活的語言。所以,讓我告訴你如何去掉剛剛例子中的冗余代碼。我們將一個像 @property 一樣的裝飾器,但是只評估一次函數。它將結果存儲在一個以裝飾函數命名的成員中,并且在隨后的調用中返回該值。如果你不是很了解這個裝飾器是什么東西,你可以看看這個學習指南。
import
?functools
def
?lazy_property
(
function
):
? ? attribute?
=
?
"_cache_"
?
+
?
function
.
__name__
? ??
@property
? ??
@functools
.
wraps
(
function
)
? ??
def
?decorator
(
self
):
? ? ? ??
if
?
not
?hasattr
(
self
,
?attribute
):
? ? ? ? ? ? setattr
(
self
,
?attribute
,
?
function
(
self
))
? ? ? ??
return
?getattr
(
self
,
?attribute
)
? ??
return
?decorator
使用這個裝飾器,我們可以將上面的代碼簡化如下:
class
?
Model
:
? ??
def
?__init__
(
self
,
?data
,
?target
):
? ? ? ??
self
.
data?
=
?data
? ? ? ??
self
.
target?
=
?target
? ? ? ??
self
.
prediction
? ? ? ??
self
.
optimize
? ? ? ??
self
.
error
? ??
@lazy_property
? ??
def
?prediction
(
self
):
? ? ? ? data_size?
=
?
int
(
self
.
data
.
get_shape
()[
1
])
? ? ? ? target_size?
=
?
int
(
self
.
target
.
get_shape
()[
1
])
? ? ? ? weight?
=
?tf
.
Variable
(
tf
.
truncated_normal
([
data_size
,
?target_size
]))
? ? ? ? bias?
=
?tf
.
Variable
(
tf
.
constant
(
0.1
,
?shape
=[
target_size
]))
? ? ? ? incoming?
=
?tf
.
matmul
(
self
.
data
,
?weight
)
?
+
?bias
? ? ? ??
return
?tf
.
nn
.
softmax
(
incoming
)
? ??
@lazy_property
? ??
def
?optimize
(
self
):
? ? ? ? cross_entropy?
=
?
-
tf
.
reduce_sum
(
self
.
target
,
?tf
.
log
(
self
.
prediction
))
? ? ? ? optimizer?
=
?tf
.
train
.
RMSPropOptimizer
(
0.03
)
? ? ? ??
return
?optimizer
.
minimize
(
cross_entropy
)
? ??
@lazy_property
? ??
def
?error
(
self
):
? ? ? ? mistakes?
=
?tf
.
not_equal
(
? ? ? ? ? ? tf
.
argmax
(
self
.
target
,
?
1
),
?tf
.
argmax
(
self
.
prediction
,
?
1
))
? ? ? ??
return
?tf
.
reduce_mean
(
tf
.
cast
(
mistakes
,
?tf
.
float32
))
請注意,我們在裝飾器中只是提到了這些屬性。完整的圖還是要我們運行 tf.initialize_variables() 來定義的。
使用 scopes 來組織圖
我們現在有一個簡單的方法可以來定義我們的模型,但是由此產生的計算圖仍然是非常擁擠的。如果你想要將圖進行可視化,那么它將會包含很多互相鏈接的小節點。解決方案是我們對每一個函數(每一個節點)都起一個名字,利用 tf.namescope("name") 或者 tf.variablescope("name") 就可以實現。然后節點會在圖中自由組合在一起,我們只需要調整我們的裝飾器就可以了。
import
?functools
def
?define_scope
(
function
):
? ? attribute?
=
?
"_cache_"
?
+
?
function
.
__name__
? ??
@property
? ??
@functools
.
wraps
(
function
)
? ??
def
?decorator
(
self
):
? ? ? ??
if
?
not
?hasattr
(
self
,
?attribute
):
? ? ? ? ? ??
with
?tf
.
variable_scope
(
function
.
__name
):
? ? ? ? ? ? ? ? setattr
(
self
,
?attribute
,
?
function
(
self
))
? ? ? ??
return
?getattr
(
self
,
?attribute
)
? ??
return
?decorator
我給了裝飾器一個新的名字,因為除了我們加的懶惰緩存,它還具有特定的 TensorFlow 功能。除此之外,模型看起來和原來的是一樣的。
商業智能與數據分析群
興趣范圍包括各種讓數據產生價值的辦法,實際應用案例分享與討論,分析工具,ETL工具,數據倉庫,數據挖掘工具,報表系統等全方位知識
QQ群:81035754
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/4685.html
摘要:機器學習模型內部的組成部分,可以使用進行打包和共享。為機器學習開發者提供庫產生了庫。庫是一個在中進行發布和重用中機器學習模塊的平臺。 摘要: 本文對TensorFlow Hub庫的介紹,并舉例說明其用法。 在軟件開發中,最常見的失誤就是容易忽視共享代碼庫,而庫則能夠使軟件開發具有更高的效率。從某種意義上來說,它改變了編程的過程。我們常常使用庫構建塊或模塊,并將其連接在一起進行編程。 開...
摘要:第一個深度學習框架該怎么選對于初學者而言一直是個頭疼的問題。簡介和是頗受數據科學家歡迎的深度學習開源框架。就訓練速度而言,勝過對比總結和都是深度學習框架初學者非常棒的選擇。 「第一個深度學習框架該怎么選」對于初學者而言一直是個頭疼的問題。本文中,來自 deepsense.ai 的研究員給出了他們在高級框架上的答案。在 Keras 與 PyTorch 的對比中,作者還給出了相同神經網絡在不同框...
摘要:共字,讀完需分鐘。下面提出一種可以幫你寫出高可讀的實踐方法,這個方法并非原創,最早的實踐來自于這篇文章。本文作者王仕軍,商業轉載請聯系作者獲得授權,非商業轉載請注明出處。 showImg(https://segmentfault.com/img/remote/1460000009341335?w=1240&h=403); 共 1926 字,讀完需 4 分鐘。所有工程師都知道,代碼是編寫...
摘要:是為了大規模分布式訓練和推理而設計的,不過它在支持新機器學習模型和系統級優化的實驗中的表現也足夠靈活。本文對能夠同時兼具規模性和靈活性的系統架構進行了闡述。盡管大多數訓練庫仍然只支持,但確實能夠支持有效的推理。 TensorFlow 是為了大規模分布式訓練和推理而設計的,不過它在支持新機器學習模型和系統級優化的實驗中的表現也足夠靈活。?本文對能夠同時兼具規模性和靈活性的系統架構進行了闡述。設...
閱讀 813·2023-04-25 22:57
閱讀 3062·2021-11-23 10:03
閱讀 624·2021-11-22 15:24
閱讀 3169·2021-11-02 14:47
閱讀 2912·2021-09-10 11:23
閱讀 3130·2021-09-06 15:00
閱讀 3953·2019-08-30 15:56
閱讀 3337·2019-08-30 15:52