從軟件開發到 AI 領域工程師:模型訓練篇_如何寫文案

※別再煩惱如何寫文案,掌握八大原則!

什麼是銷售文案服務?A就是幫你撰寫適合的廣告文案。當您需要販售商品、宣傳活動、建立個人品牌,撰寫廣告文案都是必須的工作。

前言

4 月熱播的韓劇《王國》,不知道大家有沒有看?我一集不落地看完了。王子元子出生時,正逢宮內殭屍作亂,元子也被咬了一口,但是由於大腦神經元尚未形成,寄生蟲無法控制神經元,所以醫女在做了簡單處理后,判斷不會影響大腦。這裏提到了人腦神經元,它也是 AI 神經網絡的研究起源,具體展開講講。

人腦中總共有 860 億個神經元,其中大腦皮層有 160 億個神經元。大腦皮層的神經元數量決定了動物的智力水平,人的大腦皮層中神經元數量遠高於其他物種,所以人類比其他物種更聰明。大象的腦子總共有 2570 億個神經元,但是其中 98% 的神經元都存在於大象的小腦中,而大象的大腦皮層只有 56 億個神經元,無法與人類相比。大腦皮層中的神經元數量越大,能耗也越大。人腦每天消耗的能量占人體全部耗能的 25%,這也就是為什麼我們每天都要吃多餐,很容易餓的原因。人之所以能夠很快超越其他物種,主要是因為人類掌握了烹飪技術,能夠在短時間內攝入大量卡路里以支持大腦運轉,其他物種則將攝入的卡路里用於維護身體運轉,不得不犧牲大腦皮層的神經元數量。

之所以先談大腦神經元原理,也是為了引出本文的重點–現代 AI 技術。在正式進入 AI 技術前,我先講講軟件工程師這份工作,因為現在有很多軟件工程師準備轉入 AI 行業。

軟件工程師

我是軟件工程師出身,2004 年剛畢業時我寫的是 JSP 代碼(一種將 Java 語言嵌入在 HTML 代碼中的編寫方式),工作幾年後轉入分佈式軟件技術,再後來進入大數據技術領域,最近的 4 年時間我一直在從事 AI 平台研發工作。

軟件工程師的要求,我總體分為基礎編碼和系統架構兩方面,因此我對於軟件工程師的考察,特別是校招學生時,為了進一步考察他們的綜合能力,我每次都會自己準備面試題,這些題目包括了編程基本概念、算法編程題、操作系統、數據庫編程、開源代碼閱讀、垃圾回收機制、系統架構描述等。

編碼的話題展開來可以講很久,發展歷史很悠久,我 15 歲學編程時用的是 Basic 語言,讀大學時學的是 C 語言,大學畢業參加工作后第一門用的語言是 Java,其中的各種故事和理解可以寫幾篇文章,這裏不展開談。

我覺得談到軟件工程師工作,避不開軟件架構設計。大眾談軟件架構,很多人會認為軟件架構就是一堆框架的組合,其實不對,軟件架構本身是對於軟件實體的組織形式的闡述,使用框架的意義是快速完成軟件架構設計,而不是取代軟件架構設計,兩者本質上不是一類事物,更像是設計圖紙和所使用的原材料。軟件架構就是通過對軟件生命周期的拆分,在符合業務架構的前提下,以達到軟件本身訪問增長目的的方式。這個增長需要軟件開發的增長,也需要軟件運行的增長,由此達到所支撐業務的增長。

市面上也確實有很多例如“分佈式系統架構”、“微服務架構”等等跟隨着潮流的書籍,但是看完后只停留在會採用一些開源框架進行整體框架搭建,我說的是搭建,而不是設計。確實是搭建,你所擁有的能力就好像小孩子搭積木,只會採用固定討論,或者學得差點,連固定套路都沒學會,這樣對你的個人能力發展其實沒有多大好處,這也是為什麼很多程序員在完成了程序員 – 架構師的轉型后,沒過多久就轉為純管理,或者徹底離開了技術界,因為從來沒有大徹大悟理解系統架構。

之所以談了這麼多系統架構相關的工作理解,是因為我認為系統架構師系統化的思維,我們搞 AI 系統也是系統化的思維,從有較強編程能力的系統架構師轉 AI 技術,相對容易一些。

AI 工程師

為什麼要從軟件工程師轉行到 AI 產品研發?因為 AI 產品研發有更大的吸引力,因為它更難,難到我們並不確定什麼時候才能真正做出來,做出來真正能夠可複製的 AI 產品。表面上看它也是一個門檻—一個“可用”且“可複製”的 AI 技術,但因為難度足夠大,所以有挑戰性,必須不斷地改善技術,做全球範圍內還沒有做出來的技術。搞軟件開發時處理的一些問題可能是其他公司已經解決的,並非“人類”都還沒有解決的問題。

AI 的研究最早可以被追溯到亞里士多德的三段論,然後萊布尼茨創立了處理邏輯,布爾在布爾代數上的貢獻,弗雷德在近代邏輯上的貢獻,羅素在邏輯主義方面的貢獻,這些工作都是在數據邏輯上的。一般認為,現代 AI 技術討論,起源於 1956 年在達特茅斯學院召開的夏季研討會,而這門學科的源頭可能是 Alan Turing(阿蘭. 圖靈) 1948 年在英國國家物理實驗室(NPL)寫過的一份內部報告,這份報告中提到了肉體智能和無肉體智能,從某種意義上預示了後來符號派和統計派之爭,或是 Turing 在 1950 年在哲學雜誌《心》(Mind)上發表的文章“計算機與智能”,反正都是 Turing。

可以這麼認為,現代 AI 是一系列通用目的技術的總稱。現代 AI 技術,主要指基於機器學習(Machine Learning,簡稱 ML)/ 深度學習(Deep Learning,簡稱 DL)的一系列方法和應用,這隻是 AI 領域的一個分支,也是目前發展最快、應用最廣的分支。

機器學習 / 深度學習的原理可以這樣理解:建立一個模型,給一個輸入,通過模型的運算,得到一個輸出。可以用於解決一個簡單問題,例如識別圖片是不是狗,也可以用來解決複雜問題,例如下棋、開車、醫療診斷、交通治理等等,也可以理解為,模型就是一個函數 f(x),上述過程,可以表達為:f(一張圖片)= 狗 / 不是狗。

一個 AI 應用開發,大概分為三個階段:

  • 第一階段,識別問題、構建模型、選擇模型。AI 的開發和培養一個小孩子類似,不同的孩子有不同的愛好和特長,同樣地,AI 也有很多模型 / 算法,不同的模型 / 算法適合解決不同的問題。所以,首先要識別你要解決的是個什麼問題,然後選擇一個合適的模型 / 算法;
  • 第二階段,訓練模型。和培養小孩子一樣,即使你發現小孩子有音樂天分,他也不可能天生就是鋼琴家,他需要專業的訓練。AI 開發也一樣,選定模型 / 算法后,即使算法再好,也不能馬上有效工作,你需要用大量的數據訓練這個模型,訓練過程中不斷優化參數,讓模型能夠更為有效地工作。這個階段 AI 模型的工作狀態,叫做“訓練”;
  • 第三階段,模型部署。模型訓練結束后就可以部署了。比如一個人臉識別的模型,你可以把它部署在手機上,用於開機鑒權,也可以把它部署在園區閘機上,用於出入管理,還可以把它部署在銀行的客戶端上,用於業務鑒權,等等。如同一個孩子成長為鋼琴家后,既可以在音樂會上演奏,也可以在家庭聚會上表演。AI 模型部署之後的工作狀態,專業的說法,叫做“推理”。

通過上述 AI 開發過程的簡述,可以發現,算法、數據和算力,是驅動 AI 發展的三大動力,三者缺一不可。

  • 算法相當於是基因。基因不好,再努力也白搭。如何識別問題,並根據問題選擇算法,甚至開發新的算法,是高端 AI 專家的核心競爭力;
  • 數據相當於是學習材料。光基因好,沒有好的教材,也教不出大師。AI 的訓練,需要海量的、高質量的數據作為輸入。AlhpaGo 通過自己和自己下棋,下了幾千萬盤,人類一輩子最多也就下幾千盤。沒有這樣的訓練量,AlhpaGo 根本不可戰勝人類。自動駕駛,Google 已經搞了 10 年,訓練了幾十萬小時,遠遠超過一個專業賽車手的訓練量,但離真正的無人駕駛還差很遠。另外,數據的質量也很重要,如果你給 AI 輸入的數據是錯的,那麼訓練出來的 AI,也會做出錯誤的結果。簡單的說,如果你把貓的圖片當做狗的圖片去訓練 AI,那麼訓練出來的 AI,就一定會把貓當做狗。數據的重要性直接導致了中國湧現了大批以數據標註為生存手段的公司和個人;
  • 一個小孩,光有天分和好的學習材料,自己如果不努力,不投入時間和精力好好學習,絕對不可能成為大師。同樣的道理,一個 AI 模型,算法再好、數據再多,如果沒有足夠的算力,支撐它持續不斷的訓練,這個模型永遠也不能成為一個真正好用的模型。這就是為什麼英偉達崛起的原因,這家公司的 GPU 芯片提供了最為適配於人腦神經網絡的計算算力,現在國內工業界也有了類似的公司產品 – 華為的達芬奇芯片。

訓練 AI 應用模型

動手實踐前

接下來,我們通過對一個 AI 應用模型的訓練和推理過程介紹,開始動手實踐。

訓練模型需要算力,對於算力的獲取,訓練和推理可以根據自己的業務需求,選擇使用公有雲或自己購買帶算力芯片的服務器,本文案我選擇的是某花廠的 AI 開發平台,因為近期他們剛推出一個免費算力的推廣活動,可以省下一筆訓練費用。為了便於調試,我首先在自己的 CPU 個人電腦上編寫代碼、訓練模型,這樣做的缺點是模型收斂的時間長了一些。

疫情期間,對於民眾來說,佩戴口罩是最有效防止被傳染新冠病毒的方式,保護自己的同時也保護他人。所以本文的案例是佩戴口罩的識別模型訓練。識別算法離不開目標檢測。目標檢測(Object Detection)的任務是找出圖像中所有感興趣的目標(物體),確定它們的位置和大小。由於各類物體有不同的形狀、大小和數量,加上物體間還會相互遮擋, 因此目標檢測一直都是機器視覺領域中最具挑戰性的難題之一。

基於深度學習的人臉檢測算法,多數都是基於深度學習目標檢測算法進行的改進,或者說是把通用的目標檢測模型,為適應人臉檢測任務而進行的特定配置。而眾多的目標檢測模型(Faster RCNN、SSD、YOLO)中,人臉檢測算法最常用的是 SSD 算法(Single Shot MultiBox Detector,“Single Shot”指的是單目標檢測,“MultiBox”中的“Box”就像是我們平時拍攝時用到的取景框,只關注框內的畫面,屏蔽框外的內容。創建“Multi”個 “Box”,將每個 “Box” 的單目標檢測結果匯總起來就是多目標檢測。換句話說,SSD 將圖像切分為 N 片,並對每片進行獨立的單目標檢測,最後匯總每片的檢測結果。),其他如 SSH 模型、S3FD 模型、RetinaFace 算法,都是受 SSD 算法的啟發,或者基於 SSD 進行的任務定製化改進, 例如將定位層提到更靠前的位置,Anchor 大小調整、Anchor 標籤分配規則的調整,在 SSD 基礎上加入 FPN 等。本文訓練口罩識別模型採用了 YOLO。

目標檢測過程都可以分解為兩個獨立的操作:

  • 定位(location): 用一個矩形(bounding box)來框定物體,bounding box 一般由 4 個整數組成,分別表示矩形左上角和右下角的 x 和 y 坐標,或矩形的左上角坐標以及矩形的長和高。
  • 分類(classification): 識別 bounding box 中的(最大的)物體。

我選擇採用 keras-yolo3-Mobilenet 方案,開源項目地址:
https://github.com/Adamdad/keras-YOLOv3-mobilenet。
MobileNet 的創新亮點是 Depthwise Separable Convolution(深度可分離卷積),與 VGG16 相比,在很小的精度損失情況下,將運算量減小了 30 倍。YOLOv3 的創新亮點是 DarkNet-53、Prediction Across Scales、多標籤多分類的邏輯回歸層。

基於開源數據集的實驗結果:

動手訓練模型

訓練模型自然需要訓練數據集和測試數據集,大家可以在這裏下載:

https://modelarts-labs-bj4.obs.cn-north-4.myhuaweicloud.com/casezoo/maskdetect/datasets/maskdetectdatasets.zip

Yolo v3-MobileNet 目標檢測工程的目錄結構如下:

|--model_data
 |--voc_classes.txt
 |--yolo_anchors.txt
|--yolo3
 |--model.py
 |--model_Mobilenet.py
 |--utiles.py
|--convert.py
|--kmeans.py
|--train.py
|--train_Mobilenet.py
|--train_bottleneck.py
|--voc_annotation.py
|--yolo.py
|--yolo_Mobilenet.py
|--yolo_video.py

開源項目的好處是已經幫你封裝了流程,例如涉及的 Yolo 代碼不用修改,本次訓練過程需要修改的代碼主要是以下三個:

1.train_Mobilenet.py:模型訓練代碼;
2.yolo/model_Mobilenet.py:基於 mobilenet 的 yolo 的模型代碼,如果相對模型代碼仔細研究的人,可以研究這個代碼;
3.yolo_Mobilenet.py:模型推理代碼。

接下來具體介紹我們需要修改的代碼,按照功能分為數據類、模型類、可視化類、遷移上雲準備類。

※教你寫出一流的銷售文案?

銷售文案是什麼?A文案是廣告用的文字。舉凡任何宣傳、行銷、販賣商品時所用到的文字都是文案。在網路時代,文案成為行銷中最重要的宣傳方式,好的文案可節省大量宣傳資源,達成行銷目的。

•數據類:

仿照 modeldata/vocclasses.txt 寫一個是否有戴口罩的類別的 txt,內容只有 yes_mask、no_mask 兩個字符。

如果你下載我給出的數據集,你會發現,口罩數據集中給出的 xml 標註格式是 VOC 的標準的,仿照 convert.py 和 voc_annotation.py 寫一個數據轉換文件,代碼如下所示:

import xml.etree.ElementTree as ET 
import os 
 
def convert_annotation(classes, label_path): 
    in_file = open(label_path) 
    tree=ET.parse(in_file) 
    root = tree.getroot() 
    output_list = [] 
    for obj in root.iter('object'): 
        difficult = obj.find('difficult').text 
        cls = obj.find('name').text 
        if cls not in classes or int(difficult)==1: 
            continue 
        cls_id = classes.index(cls) 
        xmlbox = obj.find('bndbox') 
        b = (int(xmlbox.find('xmin').text), int(xmlbox.find('ymin').text), int(xmlbox.find('xmax').text), int(xmlbox.find('ymax').text)) 
        output_list.append(" " + ",".join([str(a) for a in b]) + ',' + str(cls_id)) 
    return (' '.join(output_list)) 
 
 
def mask_convert(data_path, classes): 
    img_list = [] 
    for i in list(os.listdir(data_path)): 
        if i.split('.')[1] == 'jpg': 
            img_list.append(i.split('.')[0]) 
 
    output_list = [] 
    for image_id in img_list: 
        img_path = (data_path + '/%s.jpg' % (image_id)) 
        label_path = (data_path + '/%s.xml' % (image_id)) 
        annotation = convert_annotation(classes, label_path) 
        output_list.append(img_path + annotation) 
 
    return output_list

•模型類:

訓練過程中會有一個 tensor 對不上的錯誤,需要修改 model_data/model.py 這個代碼中的 140-141 行,如下所示:

box_xy = (K.sigmoid(feats[..., :2]) + grid) / K.cast(grid_shape[..., ::-1], K.dtype(feats)) 
box_wh = K.exp(feats[..., 2:4]) * anchors_tensor / K.cast(input_shape[..., ::-1], K.dtype(feats))

•可視化類:

為了直觀判斷模型效果,增加了一個在圖片上直接標註的可視化代碼,也就是在圖片上打印輸出結果(yes_mask 或 no_mask),代碼如下所示:

#!/usr/bin/env python 
# coding: utf- 
 
img_path = "D:/Code/mask_detection/data/test" 
save_path = "D:/Code/mask_detection/data/test_result/" 
 
 
import matplotlib 
matplotlib.use('Agg') 
import matplotlib.pyplot as plt 
import matplotlib.patches as patches 
import matplotlib.image as mpimg 
import random 
import json 
 
# 推理輸出路徑 
with open('D:/Code/mask_detection/keras-YOLOv3-mobilenet-master/annotation_YOLOv3.json') as json_file: 
    data = json.load(json_file) 
 
imgs = list(data.keys()) 
 
def parse_json(json): 
    bbox = [] 
    for item in json['annotations']: 
        name = item['label'] 
        xmin = item['x'] 
        ymin = item['y'] 
        xmax = item['x']+item['width'] 
        ymax = item['y']+item['height'] 
        bbox_i = [name, xmin, ymin, xmax, ymax] 
        bbox.append(bbox_i) 
    return bbox 
 
 
def visualize_bbox(image, bbox, name): 
    fig, ax = plt.subplots() 
    plt.imshow(image) 
    colors = dict()#指定標註某個對象的邊框的顏色 
    for bbox_i in bbox: 
        cls_name = bbox_i[0] #得到 object 的 name 
        if cls_name not in colors: 
            colors[cls_name] = (random.random(), random.random(), random.random()) #隨機生成標註 name 為 cls_name 的 object 的邊框顏色 
        xmin = bbox_i[1] 
        ymin = bbox_i[2] 
        xmax = bbox_i[3] 
        ymax = bbox_i[4] 
        #指明對應位置和大小的邊框 
        rect = patches.Rectangle(xy=(xmin, ymin), width=xmax-xmin, height=ymax-ymin, edgecolor=colors[cls_name],facecolor='None',linewidth=3.5) 
        plt.text(xmin, ymin-2, '{:s}'.format(cls_name), bbox=dict(facecolor=colors[cls_name], alpha=0.5)) 
        ax.add_patch(rect) 
    plt.axis('off') 
    plt.savefig(save_path+'{}_gt.png'.format(name)) #將該圖片保存下來 
    plt.close() 
 
 
for item in imgs: 
    img = mpimg.imread(img_path+item) 
    bbox = parse_json(data[item]) 
    visualize_bbox(img, bbox, item.split('.')[0])

•上雲準備類:

開源代碼寫的比較隨意,直接就是在訓練代碼 trian_Mobilenet.py 代碼中一開頭指定所有的參數。華為雲中訓練作業是需要指定 OBS 的輸入路徑和輸出路徑的,最好使用 argparse 的形式將路徑參數傳進去。其他參數可以按照自己需求做增加,修改樣例如下:

import argparse 
 
parser = argparse.ArgumentParser(description="training a maskmodel in modelarts") 
# 訓練輸出路徑 
parser.add_argument("--train_url", default='logs/maskMobilenet/003_Mobilenet_finetune/', type=str) 
# 數據輸入路徑 
parser.add_argument("--data_url", default="D:/code/mask_detection/data/MASK_MERGE/", type=str) 
# GPU 數量 
parser.add_argument("--num_gpus", default=0, type=int) 
args = parser.parse_args()

開源代碼中,數據處理的部分是將 xml 轉換成 yolo 讀的 txt 文檔,這樣導致數據輸入需要有一個寫入到 txt 文件,然後訓練工程讀取這個 txt 文件和圖片的過程。上雲后,這種流程不太方便,需要將數據處理,數據轉換和訓練代碼打通。這裏我使用緩存將數據直接傳到訓練代碼中,這樣改起來比較方便,但是當數據量較大的時候並不科學,有興趣的人可以自己修改。

遷移公有雲

我使用某廠商公有雲的 AI 訓練平台,用的是 OBS 桶上傳已經調試好的代碼(建議大家體驗 Notebook 方式,在線編程、編譯),如下圖所示:

接着啟動 Notebook,不過我沒有用 jupyter 方式寫代碼,而是採用同步 OBS 桶的資源,通過 Notebook 啟動一個 GPU 鏡像:

創建一個 Notebook 環境:

確認計算資源規格:

創建 Notebook 環境成功:

從 OBS 桶同步相關文件:

接下來進入該 Notebook 的終端環境,運行以下代碼,啟動訓練任務:

訓練過程輸出片段如下所示:

2020-04-07 18:58:14.497319: I tensorflow/stream_executor/dso_loader.cc:152] successfully opened CUDA library libcublas.so.10.0 locally
7/7 [==============================] - 17s 2s/step - loss: 4226.4421 - val_loss: 22123.3750
Epoch 2/50
7/7 [==============================] - 6s 855ms/step - loss: 1083.1558 - val_loss: 1734.1427
Epoch 3/50
7/7 [==============================] - 6s 864ms/step - loss: 521.8567 - val_loss: 455.0971
Epoch 4/50
7/7 [==============================] - 6s 851ms/step - loss: 322.8907 - val_loss: 193.3107
Epoch 5/50
7/7 [==============================] - 6s 841ms/step - loss: 227.7257 - val_loss: 150.8902
Epoch 6/50
7/7 [==============================] - 6s 851ms/step - loss: 179.0605 - val_loss: 154.9351
Epoch 7/50
7/7 [==============================] - 6s 868ms/step - loss: 150.4297 - val_loss: 147.3101
Epoch 8/50
7/7 [==============================] - 8s 1s/step - loss: 129.5681 - val_loss: 144.8283

模型生成后,創建一個 python 腳本,代碼如下,實現了模型文件拷貝到 OBS 桶:

from modelarts.session import Session
session = Session()
session.upload_data(bucket_path="/mask-detection-modelarts-test/run/log/", path="/home/ma-user/work/log/trained_weights_final.h5")

運行推理腳本,我把推測結果打印在了測試圖片上,如下圖所示,識別出了口罩:

後記

AI 技術的興起,已經帶動了科技行業的革命,而每一次業界的革命,都會讓一些公司落寞而讓另一些公司崛起,程序員也一樣,每一次技術換代也都會讓一些程序員沒落而讓另一些程序員崛起。抓住目前正在流行的 AI 技術趨勢,使用雲端的免費計算資源,上手學習並實踐 AI 技術,會是相當一部分軟件工程師、數據科學家的選擇。此外,由於在圖像識別、文本識別、語音識別等技術領域,算法的精度已經給有大幅度的提升,在很多場景下已經達到可商用級別,也進一步讓自動機器學習技術(模型的自動設計和訓練)的發展成為可能。因此,在上述幾個技術領域的很多應用場景下,公有雲已經可以做到根據用戶自定義數據進行 AI 模型的自動訓練。

點擊關注,第一時間了解華為雲新鮮技術~

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。