客戶的網站有提供部落格的功能,讓會員可以在上面寫一些文章,經營得算是頗有流量,有流量就容易吸引一些蹭流量的人,色情廣告就是其中之一,目前客戶在色情廣告上的處理仍然是採用人工封鎖的方式,成本高又反應慢,所以打算引入 Azure Cognitive Services(認知服務)的 Custom Text Classification(自訂文字分類),來讓阻擋色情廣告這件事情可以更有效率一些。
原本是想要嘗試用 Content Moderator(內容仲裁)當中的文字分類功能,看看效果好不好?它預設就能偵測三種分類:明顯色情或成人內容
、具性暗示或成人內容
、具冒犯性的內容
,可惜目前只支援英文
,所以改用 Custom Text Classification 自己做資料標記來訓練 AI,產生屬於自己的模型。
建立自訂文字分類服務
首先把資源建立起來,在 Azure 的「AI + 機器學習服務
」當中,找到「認知服務
」。
點擊進去之後,我們可以看到認知服務底下的各類子服務,找到語言服務
後,點擊「建立
」
在右邊「自訂功能
」這一區塊,選取「自訂文字分類和自訂命名實體辨識
」,然後點擊「繼續建立您的資源
」。
在資源建立的畫面中,必填的欄位有以下這些:
訂用帳戶
資源群組
區域
:目前支援自訂文字分類服務的區域只有 10 個,大都在美洲地區,少數在歐洲,澳洲及亞洲地區則各有一個區域。名稱
定價層
新的/現有的儲存體帳戶
:儲存體帳戶是用來存放樣本資料,可以用現有的或是新建一個,我這邊是新建一個給自訂文字分類服務來使用。核取此方塊代表本人確認已詳閱並知悉「負責任 AI 注意事項」中的相關條款
:關於負責任 AI,在 2021 iThome 鐵人賽有一篇文章有做介紹,大家可以移駕過去看一下。
其他頁籤的設定就暫時保持預設值即可,重新檢視一下設定值,沒問題就按下「建立
」。
準備資料
再來,我們要來準備餵給 AI 的樣本資料,我們在使用這種內容分類工具的時候,要先有一個認知,就是說我們要分類的內容要有一定的鑑別度,這樣子訓練出來的模型,跑出來的信賴度會比較高。
反之,比如說最近求職詐騙很猖獗,如果我們本身是做求職刊登服務的網站,那我們要訓練 AI 分類出求職詐騙的刊登內容,那個訓練出來的模型的信賴度就不會太漂亮,誤判率會提高,因為正常的刊登內容與詐騙的刊登內容差別不大,所以說我們要讓 AI 訓練出來的模型是可信的,那麼在一開始的資料整理跟分析就不能隨便。
我從客戶那邊針對色情廣告及正常文章各整理了 100 個樣本,我們在儲存體帳戶建立容器之後,就把這些樣本上傳到容器內。
Language Studio
Azure 有一個工具 - Language Studio,它提供了 GUI 的介面,方便我們使用語言相關的認知服務,我們用 Azure 的帳號就可以直接登入了。
登入之後,先要連結一個語言資源,這邊就選擇我們剛剛建立的語言資源。
將畫面往下捲,我們可以看到一個「Custom text classification
」,點進去之後我們要先建立一個「Project
」。
建立專案的步驟其實就是一直下一步,把必填的欄位填一填就能建立成功了,其中要特別說明的是在「Select project type
」這個步驟,我要訓練的模型是要能分類出來色情廣告跟正常文章,就這兩個類別而已,所以我選擇「Single label classification
」,一份資料一個類別。
如果我們訓練出來的模型要能針對一份資料分類出來多個類別,就要選擇「Multi label classification
」,但是相對地,在做資料標記的時候就會比較辛苦一些。
資料標記(Data labeling)
專案建立好後,接下來要進入的是資料標記(Data labeling)
的階段,從下面的畫面已經可以看到我們上傳的樣本資料,我們先點擊「Add class
」建立類別
,這邊要注意的是,樣本資料至少要 10 份,類別至少要 2 組。
標記資料的方式就是把資料選取起來,然後點選一個右手邊的類別,最後按下「Save labels
」,過程中我們還可以透過關鍵字
及過濾器
來篩選樣本資料。
訓練模型(Training)
資料都標記好分類之後,下一步是要訓練 AI 產生我們要的模型,其中 Data splitting
的部分,就是說要拿樣本資料的多少比例來訓練模型?多少比例來做模型的測試?微軟也已經設好建議的預設值 80% for traning
、20% for testing
,那當然我們也可以按照需求自己來調整,在所有參數都設定完後,按下「Train
」就開始了。
部署模型(Deploying)
模型訓練完成後,再來就是要進行部署
,點擊「Add deployment
」,填入部署名稱,選擇剛剛訓練好的模型,按下「Deploy
」就可以了。
測試模型(Testing)
模型部署後,我們就可以再拿樣本資料以外的資料,來測試看看模型的信賴度如何?那這邊我拿一篇色情廣告來跑跑看,選擇我們剛剛部署的模型,貼上要測試的資料內容,按下「Run the test
」,結果顯示分類是 porn
,可信度 100%。
我再拿一篇正常文章來測試,結果顯示分類是 normal
,可信度 95%。
這樣的結果其實還算可以,後續要再多拿一些資料來測試,看誤判率高不高?可信度能不能接受?如果不滿意的話,就從準備資料開始,重新跑一次訓練模型的流程,直到滿意為止。
REST API
除了 Language Studio 提供的介面讓我們用來分析資料之外,還有其他兩種方式,第一種是呼叫 REST API,在部署模型的介面當中,選取其中一個部署,點擊「Get prediction URL
」,可以找到 curl
的範例,從範例中我們就能知道發送 HTTP Request 需要的資訊。
下面我就用 C# 搭配 HttpClient
,來撰寫發送資料分析的程式,其中有幾個參數需要說明一下。
Ocp-Apim-Subscription-Key
:這個是我們的金鑰,在資源管理介面中的金鑰與端點
裡面可以找得到,就連端點也在裡面。
api-version
:API 的版本關乎到有支援的服務,這個在官方文件 Model lifecycle 裡面找得到,而自訂文字分類服務的 API 版本是2022-05-01
。Language
:這個要填入 Language Code,繁體中文是zh-hant
。
完整程式碼如下:
var client = new HttpClient
{
BaseAddress = new Uri("https://cog-ctc-mytest.cognitiveservices.azure.com")
};
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "my-subscription-key");
var analysisRequest = new HttpRequestMessage(HttpMethod.Post, "/language/analyze-text/jobs?api-version=2022-05-01");
var content = JsonSerializer.Serialize(
new
{
DisplayName = "my-display-name",
AnalysisInput = new { Documents = new[] { new { Id = "my-id", Language = "zh-Hant", Text = File.ReadAllText(@"D:\Downloads\my-data\test\268763.txt") } } },
Tasks = new[]
{
new
{
Kind = "CustomSingleLabelClassification",
Parameters = new { ProjectName = "porn-classification", DeploymentName = "article-classification" }
}
}
},
new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
analysisRequest.Content = new StringContent(content, Encoding.UTF8, "application/json");
var analysisResponse = await client.SendAsync(analysisRequest);
然後,我們就會發現收到的 Response 的 Status Code 是 202
,而不是我們常見的 200
,Content 也是空的,這是因為整個分析作業是非同步的,我們必須藉由 Response Headers 中的 operation-location
來取得分析結果。
var operationLocation = new Uri(analysisResponse.Headers.GetValues("operation-location").First());
var resultRequest = new HttpRequestMessage(HttpMethod.Get, operationLocation.PathAndQuery);
var resultResponse = await client.SendAsync(resultRequest);
var resultContent = await resultResponse.Content.ReadAsStringAsync();
由於是非同步作業的關係,沒有人知道它何時會分析好?所以我們必須輪詢 operation-location,直到看到 status
為 succeeded
時,才會得到我們要的分析結果。
Azure.AI.TextAnalytics
第二種分析資料的方式是使用 Azure.AI.TextAnalytics 這個套件,但是要注意的是目前這個時間點必須使用 beta 版本才有支援 SingleLabelClassifyAction
,對於這點如果有顧慮的朋友就自行斟酌。
var client = new TextAnalyticsClient(new Uri("https://cog-ctc-mytest.cognitiveservices.azure.com"), new AzureKeyCredential("my-subscription-key"));
var documents = new List<TextDocumentInput>
{
new TextDocumentInput("my-id", File.ReadAllText(@"D:\Downloads\my-data\test\268786.txt"))
{
Language = "zh-hant"
}
};
var singleLabelClassifyAction = new SingleLabelClassifyAction("porn-classification", "article-classification");
var actions = new TextAnalyticsActions()
{
SingleLabelClassifyActions = new List<SingleLabelClassifyAction> { singleLabelClassifyAction }
};
var operation = await client.StartAnalyzeActionsAsync(documents, actions);
await operation.WaitForCompletionAsync();
await foreach (AnalyzeActionsResult operationResults in operation.Value)
{
var actionResults = operationResults.SingleLabelClassifyResults;
foreach (var actionResult in actionResults)
{
foreach (var documentResult in actionResult.DocumentsResults)
{
var classification = documentResult.ClassificationCategories.First();
Console.WriteLine($"Category: \"{classification.Category}\", Confidence {classification.ConfidenceScore:P}.");
}
}
}
身處在這個科技時代,不知道是幸或不幸,我們常聽到一句俗話「做自己力所能及的事」,在 30 年前要用 AI 做這種文字分析的工作,不是一件容易的事情,但是時序到了現在,只要滑鼠點一點,再寫個幾行程式碼就有了,事情變得容易了,力所能及的事也跟著變多了,想要跟其他人競爭,就不能說不會了,那麼以上的內容就分享給大家,希望對有需求的朋友能夠有一點幫助。