【构建ML驱动的应用程序】第 10 章 :为模型构建安全措施
???🔎大家好,我是Sonhhxg_柒,希望你看完之后,能對你有所幫助,不足請指正!共同學習交流🔎
📝個人主頁-Sonhhxg_柒的博客_CSDN博客?📃
🎁歡迎各位→點贊👍 + 收藏?? + 留言📝?
📣系列專欄 - 機器學習【ML】?自然語言處理【NLP】? 深度學習【DL】
?
?🖍foreword
?說明?本人講解主要包括Python、機器學習(ML)、深度學習(DL)、自然語言處理(NLP)等內容。
如果你對這個系列感興趣的話,可以關注訂閱喲👋
文章目錄
工程師圍繞失敗
輸入和輸出檢查
檢查輸入
模型輸出
模型失敗回退
過濾模型
性能工程師
擴展到多個用戶
機器學習緩存
模型和數據生命周期管理
再現性
彈力
流水線靈活性
數據處理和 DAG
尋求反饋
Chris Moody:授權數據科學家部署模型
結論
什么時候在設計數據庫或分布式系統時,軟件工程師關注的是容錯性,即系統在其某些組件發生故障時繼續工作的能力。在軟件中,問題不在于系統的給定部分是否會失敗,而是何時會失敗。相同的原則可以應用于 ML。無論模型有多好,它都會在某些示例上失敗,因此您應該設計一個能夠優雅地處理此類失敗的系統。
在本章中,我們將介紹幫助預防或減輕故障的不同方法。首先,我們將了解如何驗證我們接收和生成的數據的質量,并使用此驗證來決定如何向用戶顯示結果。然后,我們將研究如何使建模管道更加健壯,以便能夠有效地為許多用戶提供服務。之后,我們將查看利用用戶反饋的選項并判斷模型的性能。我們將以對 Chris Moody 的關于部署最佳實踐的采訪結束本章。
工程師圍繞失敗
讓我們涵蓋一些最有可能導致 ML 管道失敗的方法。細心的讀者會注意到,這些失敗案例與我們在“調試接線:可視化和測試”中看到的調試技巧有些相似。事實上,在生產環境中向用戶公開模型會帶來一系列挑戰,這些挑戰與調試模型所面臨的挑戰相似。
錯誤和錯誤可能出現在任何地方,但驗證三個領域尤為重要:管道的輸入、模型的置信度以及它產生的輸出。讓我們按順序解決每個問題。
輸入和輸出檢查
任何給定的模型是在表現出特定特征的特定數據集上訓練的。訓練數據具有一定數量的特征,并且這些特征中的每一個都屬于特定類型。此外,每個特征都遵循模型為了準確執行而學習的給定分布。
正如我們在“新鮮度和分布轉變”中看到的那樣,如果生產數據與訓練模型的數據不同,模型可能難以執行。為此,您應該檢查管道的輸入。
檢查輸入
一些當面對數據分布的微小差異時,模型可能仍然表現良好。但是,如果一個模型接收到的數據與其訓練數據有很大不同,或者如果某些特征缺失或屬于意外類型,它將難以執行。
正如我們之前看到的,即使輸入不正確(只要這些輸入的形狀和類型正確),ML 模型也能夠運行。模型會產生輸出,但這些輸出可能非常不正確。考慮圖 10-1中所示的示例。管道首先將句子矢量化并在矢量化表示上應用分類模型,從而將句子分類為兩個主題之一。如果管道接收到一串隨機字符,它仍然會將其轉換為向量,模型會進行預測。這種預測是荒謬的,但是僅僅通過觀察模型的結果是沒有辦法知道的。
圖 10-1。模型仍將輸出對隨機輸入的預測
為了防止模型在不正確的輸出上運行,我們需要在將這些輸入傳遞給模型之前檢測這些輸入是否不正確。
檢查與測試
在本節中,我們談論的是輸入檢查,而不是我們在“測試您的 ML 代碼”中看到的輸入測試。區別很微妙但很重要。測試驗證代碼在給定已知的預定輸入的情況下是否按預期運行。每次代碼或模型更改時通常都會運行測試以驗證管道是否仍然正常工作。本節中的輸入檢查是管道本身的一部分,并根據輸入質量更改程序的控制流。失敗的輸入檢查可能會導致運行不同的模型或根本不運行模型。
這些檢查涵蓋與“測試您的 ML 代碼”中的測試類似的領域。按照重要性順序,他們將:
驗證是否存在所有必要的功能
檢查每個功能類型
驗證特征值
孤立地驗證特征值可能很困難,因為特征分布可能很復雜。執行此類驗證的一種簡單方法是定義一個特征可以采用的合理值范圍,并驗證它是否落在該范圍內。
如果任何輸入檢查失敗,則模型不應運行。您應該做什么取決于用例。如果丟失的數據代表了一條核心信息,您應該返回一個錯誤,說明錯誤的來源。如果你估計你仍然可以提供一個結果,你可以用啟發式代替模型調用。這是通過構建啟發式來啟動任何 ML 項目的另一個原因;它為您提供了一個后退的選擇!
在圖 10-2中,您可以看到此邏輯的示例,其中采用的路徑取決于輸入檢查的結果。
圖 10-2。輸入檢查的示例分支邏輯
以下是來自 ML Editor 的一些控制流邏輯示例,用于檢查缺失的特征和特征類型。根據輸入的質量,它要么引發錯誤,要么運行試探法。我在這里復制了示例,但您也可以在?本書的 GitHub 存儲庫中找到它以及其余的 ML Editor 代碼。
def validate_and_handle_request(question_data):missing = find_absent_features(question_data)if len(missing) > 0:raise ValueError("Missing feature(s) %s" % missing)wrong_types = check_feature_types(question_data)if len(wrong_types) > 0:# If data is wrong but we have the length of the question, run heuristicif "text_len" in question_data.keys():if isinstance(question_data["text_len"], float):return run_heuristic(question_data["text_len"])raise ValueError("Incorrect type(s) %s" % wrong_types)return run_model(question_data)驗證模型輸入允許您縮小故障模式并識別數據輸入問題。接下來,您應該驗證模型的輸出。
模型輸出
一次模型做出預測后,您應該確定是否應將其顯示給用戶。如果預測超出模型可接受的答案范圍,您應該考慮不顯示它。
例如,如果您根據照片預測用戶的年齡,則輸出值應介于 0 到 100 多歲之間(如果您在 3000 年閱讀本書,請隨意調整界限)。如果模型輸出的值超出此范圍,則不應顯示它。
在這種情況下,可接受的結果不僅由合理的結果來定義。它還取決于您對對我們的用戶有用的結果類型的估計。
對于我們的 ML 編輯器,我們只想提供可操作的建議。如果一個模型預測用戶寫的所有內容都應該被完全刪除,這將包含一個相當無用(和侮辱)的建議。以下是驗證模型輸出并在必要時恢復為啟發式的示例片段:
def validate_and_correct_output(question_data, model_output):# Verify type and range and raise errors accordinglytry:# Raises value error if model output is incorrectverify_output_type_and_range(model_output)except ValueError:# We run a heuristic, but could run a different model hererun_heuristic(question_data["text_len"])# If we did not raise an error, we return our model resultreturn model_output當模型失敗時,您可以恢復到我們之前看到的啟發式方法,或者恢復到您之前構建的更簡單的模型。嘗試早期類型的模型通常是值得的,因為不同的模型可能有不相關的錯誤。
我已經在圖 10-3中的玩具示例中說明了這一點。在左側,您可以看到具有更復雜決策邊界的性能更好的模型。在右側,您可以看到一個更糟糕、更簡單的模型。較差的模型會犯更多的錯誤,但由于其決策邊界的形狀不同,其錯誤與復雜模型不同。正因為如此,更簡單的模型得到了一些正確的例子,而復雜的模型卻出錯了。這就是為什么在主模型失敗時使用簡單模型作為備份是一個合理想法的直覺。
如果您確實使用更簡單的模型作為備份,您還應該以相同的方式驗證其輸出并回退到啟發式或如果它們未通過您的檢查則顯示錯誤。
驗證模型的輸出是否在合理范圍內是一個好的開始,但這還不夠。在下一節中,我們將介紹我們可以圍繞模型構建的額外保護措施。
圖 10-3。更簡單的模型通常會出現不同的錯誤
模型失敗回退
我們建立了檢測和糾正錯誤輸入和輸出的安全措施。然而,在某些情況下,我們模型的輸入可能是正確的,而我們模型的輸出可能是合理的,但完全錯誤。
回到從照片預測用戶年齡的例子,保證模型預測的年齡是合理的人類年齡是一個好的開始,但理想情況下我們希望預測這個特定用戶的正確年齡。
沒有一個模型會 100% 正確,輕微的錯誤通常是可以接受的,但您應該盡可能地檢測模型何時出錯。這樣做可以讓您潛在地將給定案例標記為太難,并鼓勵用戶提供更簡單的輸入(例如,以光線充足的照片的形式)。
那里是檢測錯誤的兩種主要方法。最簡單的方法是跟蹤模型的置信度以估計輸出是否準確。第二個是構建一個附加模型,其任務是檢測主模型可能失敗的示例。
對于第一種方法,分類模型可以輸出一個概率,該概率可用作模型對其輸出的置信度的估計。如果這些概率得到很好的校準(參見“校準曲線”),它們可用于檢測模型不確定的情況并決定不向用戶顯示結果。
有時,盡管為示例分配了很高的概率,但模型還是錯誤的。這就是第二種方法的用武之地:使用模型過濾掉最難的輸入。
過濾模型
除了不總是值得信賴之外,使用模型的置信度分數還有另一個嚴重的缺點。為了獲得這個分數,無論是否使用其預測,都需要運行整個推理管道。例如,當使用需要在 GPU 上運行的更復雜的模型時,這尤其浪費。理想情況下,我們希望在不運行模型的情況下估計模型在示例上的表現如何。
這就是過濾模型背后的想法。由于您知道模型難以處理某些輸入,因此您應該提前檢測它們,而不用在它們上運行模型。過濾模型是輸入測試的 ML 版本。它是一個二元分類器,經過訓練可以預測模型是否會在給定示例上表現良好。這種模型之間的核心假設是,對于主要模型來說很難的數據點類型存在趨勢。如果這些困難的例子有足夠多的共同點,過濾模型可以學習將它們與更簡單的輸入分開。
以下是您可能希望過濾模型捕獲的一些類型的輸入:
-  
與主模型在其上表現良好的輸入在質量上不同的輸入
 -  
模型接受過訓練但遇到困難的輸入
 -  
意在愚弄主要模型的對抗性輸入
 
在圖 10-4中,您可以看到圖 10-2中邏輯的更新示例,其中現在包含一個過濾模型。如您所見,過濾模型僅在輸入檢查通過時運行,因為您只需要過濾掉可能進入“運行模型”框的輸入。
要訓??練過濾模型,您只需收集包含兩類示例的數據集;您的主要模型成功的類別和它失敗的其他類別。這可以使用我們的訓練數據來完成,不需要額外的數據收集!
圖 10-4。在我們的輸入檢查中添加過濾步驟(粗體)
在圖 10-5中,我展示了如何通過利用經過訓練的模型及其在數據集上的結果來做到這一點,如左圖所示。對模型正確預測的一些數據點和模型預測失敗的一些數據點進行采樣。然后,您可以訓練一個過濾模型來預測哪些數據點是原始模型失敗的數據點。
圖 10-5。獲取過濾模型的訓練數據
一旦你有了訓練有素的分類器,訓練過濾模型就相對簡單了。給定一個測試集和一個訓練有素的分類器,下面的函數就可以做到這一點。
def get_filtering_model(classifier, features, labels):"""Get prediction error for a binary classification dataset:param classifier: trained classifier:param features: input features:param labels: true labels"""predictions = classifier.predict(features)# Create labels where errors are 1, and correct guesses are 0is_error = [pred != truth for pred, truth in zip(predictions, labels)]filtering_model = RandomForestClassifier()filtering_model.fit(features, is_error)return filtering_model這個方法被谷歌用于他們的智能回復功能,它建議對收到的電子郵件進行一些簡短的回復(參見 A. Kanan 等人的這篇文章,“智能回復:電子郵件的自動回復建議”)。他們使用他們所謂的觸發模型,負責決定是否運行建議響應的主模型。在他們的案例中,只有大約 11% 的電子郵件適合這種模式。通過使用過濾模型,他們將基礎設施需求減少了一個數量級。
過濾模型通常需要滿足兩個標準。它應該很快,因為它的全部目的是減少計算負擔,并且應該善于消除困難的情況。
試圖識別疑難案例的過濾模型不需要能夠捕獲所有案例;它只需要檢測到足以證明在每次推理時運行它的額外成本是合理的。通常,過濾模型越快,所需的效率就越低。原因如下:
假設您僅使用一個模型的平均推理時間是i.
使用過濾模型的平均推理時間為f+i(1-b)其中f是過濾模型的執行時間,b是它過濾掉的示例的平均比例(b 代表塊)。
要通過使用過濾模型減少平均推理時間,您需要具備f+i(1-b)<i, 轉化為fi<b.
這意味著您的模型過濾掉的案例比例需要高于其推理速度與較大模型速度之間的比率。
例如,如果您的過濾模型比常規模型快 20 倍(fi=5%), 它需要阻止超過 5% 的案例 (5%<b) 在生產中有用。
當然,您還需要確保過濾模型的精度良好,這意味著它阻止的大部分輸入實際上對您的主模型來說太難了。
一種方法是定期讓一些示例通過您的過濾模型會阻止并檢查您的主要模型如何處理它們。我們將在“選擇要監控的內容”中更深入地介紹這一點。
由于過濾模型不同于推理模型,專門為預測困難案例而訓練,因此它可以比依賴主模型的概率輸出更準確地檢測這些案例。因此,使用過濾模型有助于降低出現不良結果的可能性并提高資源利用率。
由于這些原因,將過濾模型添加到現有的輸入和輸出檢查中可以顯著提高生產管道的穩健性。在下一節中,我們將通過討論如何將 ML 應用程序擴展到更多用戶以及如何組織復雜的訓練過程來解決更多使管道健壯的方法。
性能工程師
保持性能將模型部署到生產中是一項重大挑戰,尤其是當產品變得越來越流行并且模型的新版本會定期部署時。我們將通過討論允許模型處理大量推理請求的方法來開始本節。然后,我們將介紹可以更輕松地定期部署更新模型版本的功能。最后,我們將討論通過使訓練管道更具可重復性來減少模型之間性能差異的方法。
擴展到多個用戶
許多軟件工作負載是水平可擴展的,這意味著增加服務器是在請求數量增加時保持合理響應時間的有效策略。ML 在這方面沒有什么不同,因為我們可以簡單地啟動新服務器來運行我們的模型并處理額外的容量。
筆記
如果您使用深度學習模型,您可能需要 GPU 才能在可接受的時間內提供結果。如果是這種情況,并且您希望有足夠多的請求來需要多個支持 GPU 的機器,則您應該在兩個不同的服務器上運行您的應用程序邏輯和模型推理。
由于 GPU 實例通常比大多數云提供商的常規實例貴一個數量級,因此使用一個更便宜的實例擴展您的應用程序,而 GPU 實例僅處理推理將顯著降低您的計算成本。使用此策略時,您應該記住,您正在引入一些通信開銷,并確保這不會對您的用例造成太大損害。
除了增加資源分配外,機器學習還有助于采用有效的方式來處理額外的流量,例如緩存。
機器學習緩存
緩存是將結果存儲到函數調用的做法,以便將來可以通過簡單地檢索存儲的結果來更快地調用具有相同參數的此函數。緩存是加速工程流水線的常見做法,對 ML 非常有用。
緩存推理結果
一個最近最少使用 (LRU) 緩存是一種簡單的緩存方法,它需要跟蹤模型的最新輸入及其相應的輸出。在對任何新輸入運行模型之前,請在緩存中查找輸入。如果找到相應的條目,則直接從緩存中提供結果。圖 10-6顯示了此類工作流程的示例。第一行表示最初遇到輸入時的緩存步驟。第二行描述了再次看到相同輸入后的檢索步驟。
圖 10-6。圖像字幕模型的緩存
這種緩存策略適用于用戶將提供相同類型輸入的應用程序。如果每個輸入都是唯一的,這是不合適的。如果應用程序通過拍攝爪印照片來預測它們屬于哪種動物,它應該很少會收到兩張相同的照片,因此 LRU 緩存無濟于事。
使用緩存時,您應該只緩存沒有副作用的函數。例如,如果run_model函數還將結果存儲到數據庫,則使用 LRU 緩存將導致不保存重復的函數調用,這可能不是預期的行為。
在 Python 中,該functools模塊提出了 LRU 緩存的默認實現,您可以將其與簡單的裝飾器一起使用,如下所示:
from functools import lru_cache@lru_cache(maxsize=128) def run_model(question_data):# Insert any slow model inference belowpass緩存在檢索特征、處理特征時最有用,并且運行推理比訪問緩存慢。根據您的緩存方法(例如,在內存中還是在磁盤上)和您使用的模型的復雜性,緩存將具有不同程度的有用性。
通過索引緩存
盡管描述的緩存方法在接收唯一輸入時不合適,我們可以緩存可以預先計算的管道的其他方面。如果模型不僅僅依賴于用戶輸入,這是最簡單的。
假設我們正在構建一個系統,允許用戶搜索與他們提供的文本查詢或圖像相關的內容。如果我們預計查詢會發生顯著變化,那么緩存用戶查詢不太可能顯著提高性能。但是,由于我們正在構建一個搜索系統,因此我們可以訪問我們目錄中可以返回的潛在項目列表。無論我們是在線零售商還是文檔索引平臺,我們都提前知道這個列表。
這意味著我們可以預先計算僅依賴于目錄中項目的建模方面。如果我們選擇一種允許我們提前進行此計算的建模方法,我們可以更快地進行推理。
出于這個原因,構建搜索系統時的一種常見方法是首先將所有索引文檔嵌入到一個有意義的向量中(有關向量化方法的更多信息,請參閱“向量化” )。創建嵌入后,它們可以存儲在數據庫中。這在圖 10-7的第一行中進行了說明。當用戶提交搜索查詢時,它會在推理時嵌入,并在數據庫中執行查找以找到最相似的嵌入并返回與這些嵌入對應的產品。您可以在圖 10-7的底行中看到這一點。
這種方法顯著加快了推理速度,因為大部分計算都是提前完成的。嵌入已成功用于 Twitter(請參閱Twitter 博客上的這篇文章)和 Airbnb(請參閱 M. Haldar 等人的文章“Applying Deep Learning To Airbnb Search”?)等公司的大規模生產管道。
圖 10-7。帶有緩存嵌入的搜索查詢
緩存可以提高性能,但它增加了一層復雜性。緩存的大小成為一個額外的超參數,需要根據應用程序的工作負載進行調整。此外,每當更新模型或底層數據時,都需要清除緩存以防止其提供過時的結果。更一般地說,將生產中運行的模型更新到新版本通常需要小心。在下一節中,我們將介紹一些有助于簡化此類更新的域。
模型和數據生命周期管理
保持最新的緩存和模型可能具有挑戰性。許多模型需要定期重新訓練以保持其性能水平。雖然我們將在第 11 章介紹何時重新訓練您的模型,但我會喜歡簡單說一下如何給用戶部署更新的模型。
經過訓練的模型通常存儲為二進制文件,其中包含有關其類型和體系結構以及學習參數的信息。大多數生產應用程序在啟動時會在內存中加載經過訓練的模型并調用它來提供結果。用較新版本替換模型的一種簡單方法是替換應用程序加載的二進制文件。這在圖 10-8中進行了說明,其中受新模型影響的管道的唯一方面是粗體框。
然而,在實踐中,這個過程通常要復雜得多。理想情況下,ML 應用程序產生可重現的結果,對模型更新具有彈性,并且足夠靈活以處理重大的建模和數據處理更改。保證這一點涉及我們接下來將介紹的一些額外步驟。
圖 10-8。部署同一模型的更新版本似乎是一個簡單的更改
再現性
至跟蹤并重現錯誤,您需要知道哪個模型正在生產中運行。為此,需要保留經過訓練的模型和訓練它們的數據集的存檔。每個模型/數據集對都應分配一個唯一標識符。每次在生產中使用模型時都應記錄此標識符。
在圖 10-9中,我將這些要求添加到加載和保存框中,以表示這增加了 ML 管道的復雜性。
圖 10-9。在保存和加載時添加重要的元數據
除了能夠為現有模型的不同版本提供服務外,生產流水線還應該致力于在不造成重大停機的情況下更新模型。
彈力
啟用應用程序在更新后加載新模型需要構建一個進程來加載更新的模型,理想情況下不會中斷對用戶的服務。這可能包括啟動一個為更新模型提供服務的新服務器,并緩慢地將流量轉移到它,但對于更大的系統來說,它很快就會變得更加復雜。如果新模型表現不佳,我們希望能夠回滾到之前的模型。正確地完成這兩項任務具有挑戰性,并且傳統上被歸類在 DevOps 領域。雖然我們不會深入介紹這個領域,但我們將在第 11 章介紹監控。
生產變更可能比更新模型更復雜。它們可以包括對數據處理的大量更改,這些更改也應該是可部署的。
流水線靈活性
我們以前看到改進模型的最佳方法通常是通過迭代數據處理和特征生成。這意味著模型的新版本通常需要額外的預處理步驟或不同的特征。
這種變化不僅反映在模型二進制文件中,而且通常會與應用程序的新版本相關聯。因此,當模型進行預測時,還應記錄應用程序版本,以使該預測可重現。
這樣做會給我們的流水線增加另一層復雜性,如圖 10-10中添加的預處理和后處理框所示。這些現在也需要是可復制和可修改的。
部署和更新模型具有挑戰性。在構建服務基礎架構時,最重要的方面是能夠重現模型在生產中運行的結果。這意味著將每個推理調用與運行的模型、訓練模型的數據集以及為該模型提供服務的數據管道版本相關聯。
圖 10-10。添加模型和應用程序版本
數據處理和 DAG
至如前所述,為了產生可重現的結果,訓練流水線也應該是可重現的和確定性的。對于給定的數據集、預處理步驟和模型的組合,訓練流水線應該在每次訓練運行時生成相同的訓練模型。
構建模型需要許多連續的轉換步驟,因此管道通常會在不同位置中斷。這可以確保每個部分都成功運行并且它們都以正確的順序運行。
簡化這一挑戰的一種方法是將我們從原始數據到訓練模型的過程表示為有向無環圖 (DAG),每個節點代表一個處理步驟,每個步驟代表兩個節點之間的依賴關系。這個想法是數據流編程的核心,流行的 ML 庫 TensorFlow 所基于的編程范例。
DAG 是一種自然的可視化方式預處理。在圖 10-11中,每個箭頭代表一個依賴于另一個任務的任務。表示允許我們保持每個任務的簡單性,使用圖形結構來表達復雜性。
圖 10-11。我們應用程序的 DAG 示例
一旦我們有了 DAG,我們就可以保證我們對我們生產的每個模型都遵循相同的操作集。有多種解決方案可以為 ML 定義 DAG,包括活躍的開源項目,例如Apache Airflow或 Spotify 的Luigi。這兩個包都允許您定義 DAG 并提供一組儀表板,以允許您監控 DAG 和任何相關日志的進度。
首次構建 ML 管道時,使用 DAG 可能會不必要地麻煩,但一旦模型成為生產系統的核心部分,可重復性要求使 DAG 非常引人注目。一旦模型被定期重新訓練和部署,任何有助于系統化、調試和版本化管道的工具都將成為節省時間的關鍵。
作為本章的結尾,我將介紹另一種確保模型運行良好的直接方法——詢問用戶。
尋求反饋
這個本章涵蓋的系統有助于確保我們及時為每位用戶提供準確的結果。為了保證結果的質量,我們介紹了檢測模型預測是否不準確的策略。我們為什么不問用戶?
你可以通過明確要求反饋和測量隱式信號來收集用戶的反饋。您可以在顯示模型的預測時要求明確的反饋,并附上一種供用戶判斷和糾正預測的方法。這可以像詢問“這個預測有用嗎?”的對話一樣簡單。或者更微妙的東西。
例如,預算應用程序 Mint 會自動對帳戶上的每筆交易進行分類(類別包括Travel、Food等)。如圖 10-12所示,每個類別在 UI 中顯示為一個字段,用戶可以根據需要進行編輯和更正。例如,此類系統允許收集有價值的反饋,以比滿意度調查更少侵入性的方式不斷改進模型。
圖 10-12。讓用戶直接修復錯誤
用戶無法為模型所做的每個預測提供反饋,因此收集隱式反饋是判斷 ML 性能的重要方法。收集此類反饋包括查看用戶執行的操作以推斷模型是否提供了有用的結果。
隱式信號很有用,但更難解釋。您不應該希望找到一個總是與模型質量相關的隱式信號,而只能是一個整體相關的信號。例如,在推薦系統中,如果用戶點擊推薦的項目,您可以合理地假設該推薦是有效的。這并非在所有情況下都是正確的(人們有時會點擊錯誤的東西!),但只要它經常是正確的,它就是一個合理的隱含信號。
通過收集這些信息,如圖 10-13所示,您可以估計用戶發現結果有用的頻率。收集此類隱式信號很有用,但會增加收集和存儲此數據的風險,并可能引入我們在第 8 章中討論的負反饋循環。
圖 10-13。作為反饋來源的用戶操作
在你的產品中建立隱式反饋機制可能是收集額外數據的一種有價值的方式。許多動作可以被認為是隱式和顯式反饋的混合。
假設我們在 ML 編輯器的推薦中添加了一個“在 Stack Overflow 上提問”按鈕。通過分析哪些預測導致用戶點擊此按鈕,我們可以衡量足以作為問題發布的推薦的比例。通過添加這個按鈕,我們并不是直接詢問用戶這個建議是否好,而是允許他們根據它采取行動,從而給我們一個“弱標簽”(有關弱標簽數據的提醒,請參閱“數據類型”?)問質量。
除了作為訓練數據的良好來源之外,隱式和顯式用戶反饋可能是注意到 ML 產品性能下降的第一種方式。雖然理想情況下,應該在向用戶顯示之前發現錯誤,但監視此類反饋有助于更快地檢測和修復錯誤。我們將在第 11 章中更詳細地介紹這一點。
部署和更新模型的策略因團隊規模和他們的 ML 經驗而異。本章中的一些解決方案對于 ML 編輯器等原型來說過于復雜。另一方面,一些在 ML 上投入了大量資源的團隊構建了復雜的系統,使他們能夠簡化部署過程并保證為用戶提供高質量的服務。接下來,我將分享對 Chris Moody 的采訪,他是 Stitch Fix 的 AI Instruments 團隊的負責人,他將向我們介紹他們在部署 ML 模型時的理念。
Chris Moody:授權數據科學家部署模型
克里斯穆迪來自加州理工學院和 UCSC 的物理學背景,現在領導 Stitch Fix 的 AI Instruments 團隊。他對 NLP 有著濃厚的興趣,并涉足深度學習、變分方法和高斯過程。他為Chainer深度學習庫做出了貢獻,為scikit-learn的超快速 Barnes–Hut 版本的 t-SNE 做出了貢獻,并用Python編寫了(為數不多的!)稀疏張量分解庫。他還構建了自己的 NLP 模型lda2vec。
問:數據科學家在 Stitch Fix 研究模型生命周期的哪一部分?
答:在 Stitch Fix,數據科學家擁有整個建模流程。這個管道很廣泛,包括構思、原型制作、設計和調試、ETL 以及使用 scikit-learn、pytorch 和 R 等語言和框架進行的模型訓練。此外,數據科學家負責建立系統以衡量指標并為他們的模型建立“健全性檢查”。最后,數據科學家運行 A/B 測試,監控錯誤和日志,并根據他們觀察到的情況根據需要重新部署更新的模型版本。為了能夠做到這一點,他們利用了平臺和工程團隊所做的工作。
問:平臺團隊如何使數據科學工作更輕松?
答:平臺團隊工程師的目標是找到正確的建模抽象。這意味著他們需要了解數據科學家的工作方式。工程師不會為從事給定項目的數據科學家構建單獨的數據管道。他們構建解決方案,使數據科學家能夠自己這樣做。更一般地說,他們構建工具以使數據科學家能夠擁有整個工作流程。這使工程師能夠花更多時間改進平臺,減少構建一次性解決方案的時間。
Q:你如何判斷模型部署后的性能?
答:Stitch Fix 的很大一部分優勢在于讓人類和算法協同工作。例如,Stitch Fix 花費大量時間思考向其造型師呈現信息的正確方式。從根本上說,如果您有一個 API,一方面公開您的模型,另一方面公開用戶(例如造型師或商品買家),您應該如何設計他們之間的交互?
乍一看,您可能很想構建一個前端來簡單地向用戶展示您的算法結果。不幸的是,這會讓用戶覺得他們無法控制算法和整個系統,并且當它表現不佳時會導致沮喪。相反,您應該將此交互視為一個反饋循環,允許用戶更正和調整結果。這樣做可以讓用戶訓練算法,并通過提供反饋對整個過程產生更大的影響。此外,這使您可以收集標記數據來判斷模型的性能。
為了做好這一點,數據科學家應該問問自己,他們如何才能將模型暴露給用戶,以便讓他們的工作更輕松,并使他們能夠使模型變得更好。這意味著,由于數據科學家最清楚什么樣的反饋對他們的模型最有用,因此他們擁有端到端的流程是不可或缺的。他們可以發現任何錯誤,因為他們可以看到整個反饋循環。
問:您如何監控和調試模型?
答:當您的工程團隊構建出出色的工具時,監控和調試就會變得容易得多。Stitch Fix 構建了一個內部工具,該工具接受建模管道并創建 Docker 容器、驗證參數和返回類型、將推理管道公開為 API、將其部署在我們的基礎設施上,并在其上構建儀表板。該工具允許數據科學家直接修復部署期間或之后發生的任何錯誤。由于數據科學家現在負責對模型進行故障排除,我們還發現這種設置會激勵簡單而強大的模型,這些模型往往很少出現故障。整個管道的所有權導致個人優化影響和可靠性,而不是模型復雜性。
問:你們如何部署新的模型版本?
答:此外,數據科學家使用定制的 A/B 測試服務運行實驗,該服務允許他們定義粒度參數。然后他們分析測試結果,如果團隊認為他們是決定性的,他們就會自己部署新版本。
在部署方面,我們使用類似于金絲雀開發的系統,我們首先將新版本部署到一個實例,然后在監控性能的同時逐步更新實例。數據科學家可以訪問一個儀表板,該儀表板顯示每個版本下的實例數量以及部署過程中的連續性能指標。
結論
在本章中,我們介紹了通過主動檢測模型的潛在故障并找到減輕故障的方法來使我們的響應更具彈性的方法。這包括確定性驗證策略和過濾模型的使用。我們還介紹了使生產模型保持最新所帶來的一些挑戰。然后,我們討論了一些可以估計模型性能的方法。最后,我們查看了一個經常大規模部署 ML 的公司的實際示例,以及他們為此構建的流程。
在第 11 章中,我們將介紹其他方法來關注模型的性能并利用各種指標來診斷 ML 驅動的應用程序的健康狀況。
總結
以上是生活随笔為你收集整理的【构建ML驱动的应用程序】第 10 章 :为模型构建安全措施的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 论文写作 2: 常见的 Latex 格式
 - 下一篇: Bin文件夹下的DLL可以做什么?