深入理解TensorFlow中的tf.metrics運算元
01 概述
本文將深入介紹Tensorflow內建的評估指標運算元,以避免出現令人頭疼的問題。
-
tf.metrics.accuracy()
-
tf.metrics.precision()
-
tf.metrics.recall()
-
tf.metrics.mean_iou()
簡單起見,本文在示例中使用tf.metrics.accuracy(),但它的模式以及它背後的原理將適用於所有評估指標。如果您只想看到有關如何使用tf.metrics的示例程式碼,請跳轉到5.1和5.2節,如果您想要了解為何使用這種方式,請繼續閱讀。
這篇文章將透過一個非常簡單的程式碼示例來理解tf.metrics
的原理,這裡使用Numpy建立自己的評估指標。這將有助於對Tensorflow中的評估指標如何工作有一個很好的直覺認識。然後,我們將給出如何採用tf.metrics快速實現同樣的功能。但首先,我先講述一下寫下這篇部落格的由來。
02 背景
這篇文章的由來是來自於我嘗試使用tf.metrics.mean_iou評估指標進行影像分割,但卻獲得完全奇怪和不正確的結果。我花了一天半的時間來弄清楚我哪裡出錯了。你會發現,自己可能會非常容易錯誤地使用tf的評估指標。截至2017年9月11日,tensorflow文件並沒有非常清楚地介紹如何正確使用Tensorflow的評估指標。
因此,這篇文章旨在幫助其他人避免同樣的錯誤,並且深入理解其背後的原理,以便了解如何正確地使用它們。
03 生成資料
import numpy as np labels = np.array([[1,1,1,0], [1,1,1,0], [1,1,1,0], [1,1,1,0]], dtype=np.uint8) predictions = np.array([[1,0,0,0], [1,1,0,0], [1,1,1,0], [0,1,1,1]], dtype=np.uint8) n_batches = len(labels)
04 建立評價指標
為了簡單起見,這裡採用的評估指標是準確度(accuracy):
如果我們想計算整個資料集上的accuracy,可以這樣計算:
n_items = labels.size accuracy = (labels == predictions).sum() / n_items print("Accuracy :", accuracy) [OUTPUT] Accuracy : 0.6875
這種方法的問題在於它不能擴充套件到大型資料集,這些資料集太大而無法一次性載入到記憶體。為了使其可擴充套件,我們希望使評估指標能夠逐步更新,每次更新一個batch中預測值和標籤。為此,我們需要跟蹤兩個值:
-
正確預測的例子總和
-
目前所有例子的總數
在Python中,我們建立兩個全域性變數:
# Initialize running variables N_CORRECT = 0 N_ITEMS_SEEN = 0
每次新來一個batch,我們將這個batch中的預測情況更新到這兩個變數中:
# Update running variables N_CORRECT += (batch_labels == batch_predictions).sum() N_ITEMS_SEEN += batch_labels.size
而且,我們可以實時地計算每個點處的accuracy:
# Calculate accuracy on updated values acc = float(N_CORRECT) / N_ITEMS_SEEN
合併前面的功能,我們建立如下的程式碼:
# Create running variables N_CORRECT = 0 N_ITEMS_SEEN = 0 def reset_running_variables(): """ Resets the previous values of running variables to zero """ global N_CORRECT, N_ITEMS_SEEN N_CORRECT = 0 N_ITEMS_SEEN = 0 def update_running_variables(labs, preds): global N_CORRECT, N_ITEMS_SEEN N_CORRECT += (labs == preds).sum() N_ITEMS_SEEN += labs.size def calculate_accuracy(): global N_CORRECT, N_ITEMS_SEEN return float(N_CORRECT) / N_ITEMS_SEEN
4.1 整體accuracy
使用上面的函式,當我們便利完所有的batch之後,可以計算出整體accuracy:
reset_running_variables() for i in range(n_batches): update_running_variables(labs=labels[i], preds=predictions[i]) accuracy = calculate_accuracy() print("[NP] SCORE: ", accuracy) [OUTPUT] [NP] SCORE: 0.6875
4.2 每個batch的accuracy
但是,如果我們想要計算每個batch的accuracy,那就要重新組織我們的程式碼了。每次更新全域性變數之前,你需要先重置它們(歸為0):
for i in range(n_batches): reset_running_variables() update_running_variables(labs=labels[i], preds=predictions[i]) acc = calculate_accuracy() print("- [NP] batch {} score: {}".format(i, acc)) [OUTPUT] - [NP] batch 0 score: 0.5 - [NP] batch 1 score: 0.75 - [NP] batch 2 score: 1.0 - [NP] batch 3 score: 0.5
05 Tensorflow中的metrics
在第4節中我們將計算評估指標的操作拆分為不同函式,這其實與Tensorflow中tf.metrics背後原理是一樣的。當我們呼叫tf.metrics.accuracy函式時,類似的事情會發生:
-
會同樣地建立兩個變數(變數會加入tf.GraphKeys.LOCAL_VARIABLES集合中),並將其放入幕後的計算圖中:
total(相當於N_CORRECT)
count(相當於N_ITEMS_SEEN)
-
返回兩個tensorflow操作。
accuracy(相當於calculate_accuracy())
update_op(相當於update_running_variables())
為了初始化和重置變數,比如第4節中的reset_running_variables函式,我們首先需要獲得這些變數(total和count)。你可以在第一次呼叫時為tf.metrics.accuracy函式顯式指定一個名稱,比如:
tf.metrics.accuracy(label, prediction, name="my_metric")
然後就可以根據作用範圍找到隱式建立的2個變數:
# Isolate the variables stored behind the scenes by the metric operation running_vars = tf.get_collection(tf.GraphKeys.LOCAL_VARIABLES, scope="my_metric") <tf.Variable 'my_metric/total:0' shape=() dtype=float32_ref>, <tf.Variable 'my_metric/count:0' shape=() dtype=float32_ref>
接下了我們可以建立一個初始化操作,以可以初始化或者重置兩個變數:
running_vars_initializer = tf.variables_initializer(var_list=running_vars)
當你需要初始化或者重置變數時,只需要在session中執行一下即可:
session.run(running_vars_initializer)
注意:除了手動分離變數,然後建立初始化op,在TF中更常用的是下面的操作:
session.run(tf.local_variables_initializer())
所以,有時候你看到上面的操作不要大驚小怪,其實只是初始化了在tf.GraphKeys.LOCAL_VARIABLES集合中的變數,但是這樣做把所以變數都初始化了,使用時要特別注意。
知道上面的東西,我們很容易計算整體accuracy和batch中的accuracy。
5.1 計算整體accuracy
在TF中要計算整體accuracy,只需要如此:
import tensorflow as tf graph = tf.Graph() with graph.as_default(): # Placeholders to take in batches onf data tf_label = tf.placeholder(dtype=tf.int32, shape=[None]) tf_prediction = tf.placeholder(dtype=tf.int32, shape=[None]) # Define the metric and update operations tf_metric, tf_metric_update = tf.metrics.accuracy(tf_label, tf_prediction, name="my_metric") # Isolate the variables stored behind the scenes by the metric operation running_vars = tf.get_collection(tf.GraphKeys.LOCAL_VARIABLES, scope="my_metric") # Define initializer to initialize/reset running variables running_vars_initializer = tf.variables_initializer(var_list=running_vars) with tf.Session(graph=graph) as session: session.run(tf.global_variables_initializer()) # initialize/reset the running variables session.run(running_vars_initializer) for i in range(n_batches): # Update the running variables on new batch of samples feed_dict={tf_label: labels[i], tf_prediction: predictions[i]} session.run(tf_metric_update, feed_dict=feed_dict) # Calculate the score score = session.run(tf_metric) print("[TF] SCORE: ", score) [OUTPUT] [TF] SCORE: 0.6875
5.2 計算每個batch的accuracy
為了分別計算各個batch的準確度,在每批新資料之前將變數重置為零:
with tf.Session(graph=graph) as session: session.run(tf.global_variables_initializer()) for i in range(n_batches): # Reset the running variables session.run(running_vars_initializer) # Update the running variables on new batch of samples feed_dict={tf_label: labels[i], tf_prediction: predictions[i]} session.run(tf_metric_update, feed_dict=feed_dict) # Calculate the score on this batch score = session.run(tf_metric) print("[TF] batch {} score: {}".format(i, score)) [OUTPUT] [TF] batch 0 score: 0.5 [TF] batch 1 score: 0.75 [TF] batch 2 score: 1.0 [TF] batch 3 score: 0.5
注意:如果每個batch計算之前不重置變數的話,其實計算的累積accuracy,就是目前已經執行資料的accuracy。
5.3 要避免的問題
不要在相同的session.run()中同時執行tf_metrics和tf_metric_update,比如這樣:
_ , score = session.run([tf_metric_update, tf_metric], feed_dict=feed_dict) score, _ = session.run([tf_metric, tf_metric_update], feed_dict=feed_dict)
在Tensorflow 1.3 (或許其它版本)中,這可能得到不一致的結果。這兩個op,update_op才是真正負責更新變數,而第一個op只是簡單根據當前變數計算評價指標,所以你應該先執行update_op,然後再用第一個op計算指標。需要注意的,update_op執行後一個作用是更新變數,另外會同時返回一個結果,對於tf.metric.accuracy,就是更新變數後實時計算的accuracy。
06 其它metrics
tf.metrics中的其他評估指標將以相同的方式工作。它們之間的唯一區別可能是呼叫tf.metrics函式時需要額外引數。例如,tf.metrics.mean_iou需要額外的引數num_classes來表示預測的類別數。另一個區別是背後所建立的變數,如tf.metrics.mean_iou建立的是一個混淆矩陣,但仍然可以按照我在本文第5部分中描述的方式收集和初始化它們。
07 結語
對於TF中所有metric,其都是返回兩個op,一個是計算評價指標的op,另外一個是更新op,這個op才是真正其更新作用的。我想之所以TF會採用這種方式,是因為metric所服務的其實是評估模型的時候,此時你需要收集整個資料集上的預測結果,然後計算整體指標,而TF的metric這種設計恰好滿足這種需求。但是在訓練模型時使用它們,就是理解它的原理,才可以得到正確的結果。
【本文轉載自:機器學習演算法工程師,作者:葉虎,原文連結:https://mp.weixin.qq.com/s/8I5Nvw4t2jT1NR9vIYT5XA】
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31542119/viewspace-2212800/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 深入理解浮點數的運算
- 【Spark篇】---SparkStreaming中運算元中OutPutOperator類運算元Spark
- 深入淺出PyTorch(運算元篇)PyTorch
- JS中運算元組的方法JS
- Dive into TensorFlow系列(2)- 解析TF核心抽象op運算元抽象
- spark-運算元-分割槽運算元Spark
- 【Spark篇】---Spark中控制運算元Spark
- 【Spark篇】---Spark中Action運算元Spark
- 使用運算元控制公式運算公式
- opcode 運算元 5 中不同的型別型別
- 使用WordPress中的wpdb類運算元據庫
- 【Spark篇】---Spark中transformations運算元二SparkORM
- Java中 使用 Math 類運算元據Java
- 3.2 Tensorflow基礎運算
- 【OpenCV】影像變換(二)邊緣檢測:梯度運算元、Sobel運算元和Laplace運算元OpenCV梯度
- 理解位運算
- Python 影像處理 OpenCV (12): Roberts 運算元、 Prewitt 運算元、 Sobel 運算元和 Laplacian 運算元邊緣檢測技術PythonOpenCV
- python中Laplacian運算元如何使用Python
- 【Spark篇】---Spark中Transformations轉換運算元SparkORM
- 運算元據庫
- 深入理解new運算子
- Java的&運算子作用於boolean運算元JavaBoolean
- lavavel 中運算元據庫查詢別名
- python中Roberts運算元是什麼Python
- 在.NET中運算元字證書(新手教程)
- Spark運算元篇 --Spark運算元之aggregateByKey詳解Spark
- Spark運算元篇 --Spark運算元之combineByKey詳解Spark
- JS中this的深入理解JS
- 深入理解Js中的thisJS
- 深入理解計算機中的原碼、補碼、反碼計算機
- 運算元據庫表
- SIFT運算元總結
- java反射——運算元組Java反射
- yii運算元據庫
- Mysqli運算元據庫MySql
- onnx 運算元定義
- MySQL DML運算元據MySql
- DDL:運算元據庫