TensorFlow 筆記 ——1 —— GraphKeys,等待補充
https://tensorflow.google.cn/versions/r1.15/api_docs/python/tf/GraphKeys?hl=zh_cn
Class GraphKeys
用於graph collections的標準名稱
別名:
- Class
tf.compat.v1.GraphKeys
標準庫使用各種眾所周知的名稱來收集和檢索與圖關聯的值。例如,如果指定為none,tf.Optimizer子類預設優化在tf.GraphKeys.TRAINABLE_VARIABLES下收集的變數,但是也可以傳遞顯式的變數列表。
所以這個類下面的變數就是各種collections的keys值,通過這些值為String變數的名稱,能夠通過get_collection()方法來得到對應的值
tf.get_collection
Graph.get_collection()的封裝,使用預設graph
tf.get_collection( key, scope=None )
引數:
- key: collection的key值。例如,GraphKeys類包含許多集合的標準名稱。
- scope:(Optional):如果提供了此選項,則對結果列表進行篩選,以只包含名稱屬性使用re.match匹配的項。如果提供了scope值,並且choice或re.match表示沒有特殊標記的作用域通過字首篩選,則不返回沒有name屬性的項。
返回:
具有給定name的集合中的值列表,或者如果沒有向該集合中新增值,則為空列表。該列表按收集值的順序包含值。
定義瞭如下的標準keys:
- GLOBAL_VARIABLES:變數物件的預設集合,跨分散式環境共享(模型變數(model variable)是其中的子集)。更多細節請參見tf.compat.v1.global_variables。通常,所有TRAINABLE_VARIABLES變數都在MODEL_VARIABLES中,而所有MODEL_VARIABLES變數都在GLOBAL_VARIABLES中。
- LOCAL_VARIABLES:位於每臺機器區域性的變數物件的子集。通常用於臨時變數,如計數器。注意:使用tf.contrib.framework.local_variable將其新增到此集合中。
- MODEL_VARIABLES:模型中用於推理(前向傳播)的變數物件的子集。注意:使用tf.contrib.framework.model_variable將其新增到這個集合中。
- TRAINABLE_VARIABLES:將由優化器訓練的變數物件的子集。更多細節請參見tf.compat.v1.trainable_variables。
- SUMMARIES:在graph中建立的summary張量物件。更多細節見tf.compat.v1.summary.merge_all。
- QUEUE_RUNNERS:用於為計算生成輸入的QueueRunner物件。參見tf.compat.v1.train.start_queue_runners瞭解更多細節。
- MOVING_AVERAGE_VARIABLES:保持移動平均值的可變物件的子集。更多細節請參見tf.compat.v1.moving_average_variables。
- REGULARIZATION_LOSSES:在graph構造過程中收集的正則化損失。
還定義了以下標準keys,但是它們的集合不會像其他的那樣自動填充,就是你可以手動使用add_to_collection()手動填充:
WEIGHTS
BIASES
ACTIVATIONS
tf.add_to_collection
Graph.add_to_collection()的封裝,其使用了預設graph
別名:
tf.compat.v1.add_to_collection
tf.add_to_collection(
name,
value
)
根據給定的name值將value值儲存在對應的collection中
引數:
- name:集合collection的鍵key。例如,GraphKeys類中包含的許多集合的標準名稱。
- value:要新增到該collection的值
tf.add_to_collections
Graph.add_to_collections()的封裝,其使用了預設graph
別名:
tf.compat.v1.add_to_collections
tf.add_to_collections(
names,
value
)
將值儲存在由name給出的集合中。
注意,collections不是集合,因此可以多次向collection新增值。此函式確保忽略名稱中的重複項,但它不會檢查names中任何collections中value的預先存在的成員關係。
names可以是任何可迭代的,但如果names是字串,則將其視為單個集合名稱。
引數:
- names:集合collection的鍵keys。例如,GraphKeys類中包含的許多集合的標準名稱。
- value:要新增到該collection的值
其他的標準名稱如下:
ACTIVATIONS = 'activations'
ASSET_FILEPATHS = 'asset_filepaths'
BIASES = 'biases'
CONCATENATED_VARIABLES = 'concatenated_variables'
COND_CONTEXT = 'cond_context'
EVAL_STEP = 'eval_step'
GLOBAL_STEP = 'global_step'
GLOBAL_VARIABLES = 'variables'
INIT_OP = 'init_op'
LOCAL_INIT_OP = 'local_init_op'
LOCAL_RESOURCES = 'local_resources'
LOCAL_VARIABLES = 'local_variables'
LOSSES = 'losses'
METRIC_VARIABLES = 'metric_variables'
MODEL_VARIABLES = 'model_variables'
MOVING_AVERAGE_VARIABLES = 'moving_average_variables'
QUEUE_RUNNERS = 'queue_runners'
READY_FOR_LOCAL_INIT_OP = 'ready_for_local_init_op'
READY_OP = 'ready_op'
REGULARIZATION_LOSSES = 'regularization_losses'
RESOURCES = 'resources'
SAVEABLE_OBJECTS = 'saveable_objects'
SAVERS = 'savers'
SUMMARIES = 'summaries'
SUMMARY_OP = 'summary_op'
TABLE_INITIALIZERS = 'table_initializer'
TRAINABLE_RESOURCE_VARIABLES = 'trainable_resource_variables'
TRAINABLE_VARIABLES = 'trainable_variables'
TRAIN_OP = 'train_op'
UPDATE_OPS = 'update_ops'
VARIABLES = 'variables'
WEIGHTS = 'weights'
WHILE_CONTEXT = 'while_context'
下面舉例說明幾個常用的:
1. tf.GraphKeys.GLOBAL_VARIABLES
1) tf.global_variables
別名:
tf.compat.v1.global_variables
tf.global_variables(scope=None)
全域性變數是分散式環境中跨機器共享的變數。Variable()建構函式或get_variable()函式自動向Graph集合GraphKeys.GLOBAL_VARIABLES中新增新變數。這個方便的函式tf.global_variables()返回該集合的內容。
區域性變數是全域性變數的替代品。看到tf.compat.v1.local_variables
引數:
- scope : (optional)一個字串。如果提供了,則對結果列表進行篩選,以使用re.match返回只包含名稱屬性與作用域匹配的項。如果提供了作用域,則不會返回沒有name屬性的項。match的選擇意味著沒有特殊標記的範圍通過字首進行篩選。
返回:
- 變數物件列表
我們熟悉的tf.global_variables_initializer()就是初始化這個集合內的Variables。
2) tf.local_variables
別名:
tf.compat.v1.local_variables
tf.local_variables(scope=None)
區域性變數——每個程序變數,通常不儲存/恢復到checkpoint,用於臨時或中間值。例如,它們可以用作度量計算的計數器,或者機器讀取資料的epoch數。函式的作用是:將新變數自動新增到GraphKeys.LOCAL_VARIABLES中。這個方便的函式返回該集合的內容。
區域性變數的替代方法是全域性變數。看到tf.compat.v1.global_variables
引數:
- scope(optional):一個字串。如果提供了,則對結果列表進行篩選,以使用re.match返回只包含名稱屬性與作用域匹配的項。如果提供了作用域,則不會返回沒有name屬性的項。match的選擇意味著沒有特殊標記的範圍通過字首進行篩選。
返回:
- 區域性變數物件列表
例子:
import tensorflow as tf sess = tf.Session() #這裡沒有指定collections引數的值,則collections=None,等價於 collection=[tf.GraphKeys.GLOBAL_VARIABLES] a = tf.get_variable("a", [3,112,112]) b = tf.get_variable("b", [64]) print("a is ", a) print("b is ", b)
返回:
a is <tf.Variable 'a:0' shape=(3, 112, 112) dtype=float32_ref> b is <tf.Variable 'b:0' shape=(64,) dtype=float32_ref>
可見生成了兩個變數a和b,名字分別為'a:0'和'b:0'
print("tf.GraphKeys.GLOBAL_VARIABLES = ", tf.GraphKeys.GLOBAL_VARIABLES) global_variables_list = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES) print("global_variables_list is ", global_variables_list)
返回:
tf.GraphKeys.GLOBAL_VARIABLES = variables global_variables_list is [<tf.Variable 'a:0' shape=(3, 112, 112) dtype=float32_ref>, <tf.Variable 'b:0' shape=(64,) dtype=float32_ref>]
可見tf.GraphKeys.GLOBAL_VARIABLES對應的字串名稱為"variables",且其對應的collections中果然有a和b兩個變數
使用自定義的collections
c = tf.get_variable("c", [10], collections=["my_collections"]) d = tf.get_variable("d", [20], collections=["my_collections"]) my_variables_list = tf.get_collection("my_collections") print("my_variables_list is ", my_variables_list)
返回:
my_variables_list is [<tf.Variable 'c:0' shape=(10,) dtype=float32_ref>, <tf.Variable 'd:0' shape=(20,) dtype=float32_ref>]
tf.GraphKeys.REGULARIZATION_LOSSES
在使用tf.get_variable()時如果使用的了引數regularizer指定使用的正則化函式,則將新建立的變數應用正則化後的結果將新增到
tf.GraphKeys.REGULARIZATION_LOSSES
集合中,可用於正則化。
其實就是損失中添加了正則化項,輸入即這些變數權重weight值
接著上面的例子:
weight_decay = 0.1 l2_reg = tf.contrib.layers.l2_regularizer(weight_decay) tmp = tf.constant([0,1,2,3], dtype=tf.float32) k = tf.get_variable('k', regularizer=l2_reg, initializer=tmp) global_variables_list = tf.get_collection("variables") print("global_variables_list is ", global_variables_list) #regularizer定義會將k加入REGULARIZATION_LOSSES集合 regular_variables_list = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) print("regular_variables_list is ", regular_variables_list) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) print(sess.run(k)) l2_loss = tf.add_n(regular_variables_list)#實現一個列表的元素的相加 print("loss is ", sess.run(l2_loss))
返回:
global_variables_list is [<tf.Variable 'a:0' shape=(3, 112, 112) dtype=float32_ref>, <tf.Variable 'b:0' shape=(64,) dtype=float32_ref>, <tf.Variable 'k:0' shape=(4,) dtype=float32_ref>] regular_variables_list is [<tf.Tensor 'k/Regularizer/l2_regularizer:0' shape=() dtype=float32>] [0. 1. 2. 3.] loss is 0.7
L2正則化的操作等價於:
tf.reduce_sum(a*a)*weight_decay/2 = 0.1*(0*0+1*1+2*2+3*3)/2=0.7
如果有多個變數都定義了regularizations引數,則:
weight_decay = 0.1 l2_reg = tf.contrib.layers.l2_regularizer(weight_decay) tmp = tf.constant([0,1,2,3], dtype=tf.float32) tmp2 = tf.constant([1,2,3,4], dtype=tf.float32) k = tf.get_variable('k', regularizer=l2_reg, initializer=tmp) k2 = tf.get_variable('k2', regularizer=l2_reg, initializer=tmp2) global_variables_list = tf.get_collection("variables") print("global_variables_list is ", global_variables_list) #regularizer定義會將k加入REGULARIZATION_LOSSES集合 regular_variables_list = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) print("regular_variables_list is ", regular_variables_list) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) l2_loss = tf.add_n(regular_variables_list) #實現一個列表的元素的相加 print("loss is ", sess.run(l2_loss))
返回:
global_variables_list is [<tf.Variable 'a:0' shape=(3, 112, 112) dtype=float32_ref>, <tf.Variable 'b:0' shape=(64,) dtype=float32_ref>, <tf.Variable 'k:0' shape=(4,) dtype=float32_ref>, <tf.Variable 'k2:0' shape=(4,) dtype=float32_ref>] regular_variables_list is [<tf.Tensor 'k/Regularizer/l2_regularizer:0' shape=() dtype=float32>, <tf.Tensor 'k2/Regularizer/l2_regularizer:0' shape=() dtype=float32>] loss is 2.2
L2正則化的操作等價於:
tf.reduce_sum(k*k)*weight_decay/2 = 0.1*(0*0+1*1+2*2+3*3)/2=0.7 tf.reduce_sum(k2*k2)*weight_decay/2 = 0.1*(1*1+2*2+3*3+4*4)/2=1.5
所以:
l2_loss = tf.add_n([0.7, 1.5]) = 2.2
tf.GraphKeys.UPDATE_OPS
用來將一些在執行過程中需要更新,但是有不是隨著梯度後向傳播更新的引數新增到該collection中,然後用於更新引數
比如AM_softmax實現中:
def diam_softmax(prelogits, label, num_classes, scale='auto', m=1.0, alpha=0.5, reuse=None): ''' Implementation of DIAM-Softmax, AM-Softmax with Dynamic Weight Imprinting (DWI), proposed in: Y. Shi and A. K. Jain. DocFace+: ID Document to Selfie Matching. arXiv:1809.05620, 2018. The weights in the DIAM-Softmax are dynamically updated using the mean features of training samples. ''' num_features = prelogits.shape[1].value batch_size = tf.shape(prelogits)[0] with tf.variable_scope('AM-Softmax', reuse=reuse): weights = tf.get_variable('weights', shape=(num_classes, num_features), initializer=slim.xavier_initializer(), trainable=False, dtype=tf.float32) _scale = tf.get_variable('_scale', shape=(), regularizer=slim.l2_regularizer(1e-2), initializer=tf.constant_initializer(0.0), trainable=True, dtype=tf.float32) # Normalizing the vecotors prelogits_normed = tf.nn.l2_normalize(prelogits, dim=1) weights_normed = tf.nn.l2_normalize(weights, dim=1) # Label and logits between batch and examplars label_mat_glob = tf.one_hot(label, num_classes, dtype=tf.float32) label_mask_pos_glob = tf.cast(label_mat_glob, tf.bool) #將0轉成False,1轉成True,只有對應的那個類是True,其他類對應為False label_mask_neg_glob = tf.logical_not(label_mask_pos_glob) #取反操作,其他類為True logits_glob = tf.matmul(prelogits_normed, tf.transpose(weights_normed)) # logits_glob = -0.5 * euclidean_distance(prelogits_normed, tf.transpose(weights_normed)) logits_pos_glob = tf.boolean_mask(logits_glob, label_mask_pos_glob) logits_neg_glob = tf.boolean_mask(logits_glob, label_mask_neg_glob) logits_pos = logits_pos_glob logits_neg = logits_neg_glob if scale == 'auto': # Automatic learned scale scale = tf.log(tf.exp(0.0) + tf.exp(_scale)) else: # Assigned scale value assert type(scale) == float # Losses _logits_pos = tf.reshape(logits_pos, [batch_size, -1]) _logits_neg = tf.reshape(logits_neg, [batch_size, -1]) _logits_pos = _logits_pos * scale _logits_neg = _logits_neg * scale _logits_neg = tf.reduce_logsumexp(_logits_neg, axis=1)[:,None] loss_ = tf.nn.softplus(m + _logits_neg - _logits_pos) loss = tf.reduce_mean(loss_, name='diam_softmax') # Dynamic weight imprinting # We follow the CenterLoss to update the weights, which is equivalent to # imprinting the mean features # 如temp = [1,11,21,31,41,51,61], indice=[0,3,5] # tf.gather(temp, indice)返回[1,31,51] weights_batch = tf.gather(weights, label) #根據label指向的類去得到對應的weight diff_weights = weights_batch - prelogits_normed # x=[1, 1, 2, 4, 4, 4, 7, 8, 8] # y, idx, count = unique_with_counts(x) # y ==> [1, 2, 4, 7, 8] # idx ==> [0, 0, 1, 2, 2, 2, 3, 4, 4] # count ==> [2, 1, 3, 1, 2] unique_label, unique_idx, unique_count = tf.unique_with_counts(label) appear_times = tf.gather(unique_count, unique_idx) appear_times = tf.reshape(appear_times, [-1, 1]) diff_weights = diff_weights / tf.cast(appear_times, tf.float32) diff_weights = alpha * diff_weights #將weights中特定位置label的數與diff_weights對應的值分別進行減法運算 #沒指定的位置值不變,來更新在mini_batch中出現的類的weight weights_update_op = tf.scatter_sub(weights, label, diff_weights)#將weights中特定位置label的數分別與diff_weights進行減法運算 #tf.control_dependencies()此函式指定某些操作執行的依賴關係 #即tf.assign()操作要在tf.control_dependencies([weights_update_op])指定的weights_update_op操作後才能執行 with tf.control_dependencies([weights_update_op]): #weight權值通過weights_update_op操作更新後才執行下面的賦值操作 # 之後sess.run(weights_update_op)後weights的值才變 weights_update_op = tf.assign(weights, tf.nn.l2_normalize(weights,dim=1)) #將weights歸一化後的值賦值給weights,返回的結果就是引數中歸一化的weight tf.add_to_collection(tf.GraphKeys.UPDATE_OPS, weights_update_op) #將元素weights_update_op新增到列表tf.GraphKeys.UPDATE_OPS中 return loss
這樣後面通過:
update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
sess.run([update_ops])
進行更新
tf.GraphKeys.TRAINABLE_VARIABLES
由優化器Optimizer訓練的變數物件的子集
使用tf.get_variable()和tf.Variable()宣告的變數(即trainable=True,預設就為True)就會預設加入該子集中