如何在一天內(nèi)構(gòu)建和部署機器學習web應用程序?
本文我將帶領(lǐng)大家構(gòu)建一個Web應用程序以對榴蓮進行分類,在這里(https://durian-classifier.herokuapp.com/) 可以查看相關(guān)信息。
如果你不知道榴蓮是什么,那我向你說明一下。它是一種質(zhì)地乳脂狀、氣味刺鼻(見下圖)和外表刺眼的水果(在新加坡我們稱之為水果之王),這意味著刺鼻的氣味讓人要么討厭它,要么絕對喜歡它(很明顯,我屬于后者)。如果你覺得它聞起來很香,那么它的味道可能會更好。問題陳述是的,這個項目的動力源于我對榴蓮的熱愛。你一定想知道,我們到底在分類什么?你會發(fā)現(xiàn),榴蓮有很多種,它們的味道、質(zhì)地和顏色各不相同。對于此項目,我們將對四種不同類型的榴蓮進行分類,即:貓山王金鳳凰D24紅蝦下表總結(jié)了這些榴蓮的不同之處:
榴蓮的品種還有很多,但我認為這些榴蓮的細微差別可能會讓我們的模型難以學習。數(shù)據(jù)收集每個項目都從數(shù)據(jù)收集開始。由于我們將部署的模型用于個人和教育目的,因此我們將從google獲取圖像,如果你將圖片用于其他用途,請檢查版權(quán)。我們將使用此API(https://github.com/ultralytics/google-images-download) 來獲取圖像。只需按照repo上的說明安裝軟件包。在說明的第3步中,我們將針對特定的用例運行此命令(將路徑替換為chromedriver):python3 bing_scraper.py --url 'https://www.bing.com/images/search?q=mao+shan+wang' --limit 100 --download --chromedriver <path_to_chromedriver>在這里,我們將下載的圖片數(shù)量限制在100張,因為沒有多少具體的“貓山王”圖片。我們重復以上步驟三次,用其他品種的榴蓮進行搜索。請注意,由于我們在API中修改了搜索URL,查詢中的空格將替換為“+”(即mao+shan+wang,red+prawn+durian等)。當然,你可以對任何要分類的圖像執(zhí)行此步驟。數(shù)據(jù)清理在我們的用例中,由于沒有公開的榴蓮圖像,因此下載的許多圖像可能與正確的榴蓮品種不符(例如,在搜索“ mao shan wang”時可能會找到通用的“未標記”榴蓮) )。
因此,我需要手動檢查所有下載的圖像,以確保圖片的質(zhì)量,畢竟擁有高質(zhì)量(即正確標記)的數(shù)據(jù)勝過大數(shù)量的數(shù)據(jù),對吧?此步驟確實需要一些領(lǐng)域知識,并且可能會花費一些時間。(但是,數(shù)據(jù)清理是機器學習管道中的基本步驟,反映了數(shù)據(jù)科學家和AI工程師的實際情況。)清除數(shù)據(jù)后,剩下55張 D24、39張金鳳,59張貓山王和68張紅蝦圖像。訓練榴蓮分類器我選擇使用TensorFlow框架,我相信大多數(shù)實踐者都已經(jīng)熟練使用了(當然,可以隨意使用Pytorch)。
由于我們只有很少的圖像,我們無疑必須使用一個預先訓練好的模型,并在我們的數(shù)據(jù)集上對其進行微調(diào)。首先,確保你有下面的文件夾結(jié)構(gòu),這是之后使用 flow_from_directory 所必需的。train|-- d24|-- golden-phoenix|-- mao-shan-wang|-- red-prawnvalid|-- d24|-- golden-phoenix|-- mao-shan-wang|-- red-prawn讓我們開始構(gòu)建分類器。 Import relevant libraries we will be usingimport numpy as np
from tensorflow.keras.initializers import glorot_uniformfrom tensorflow.keras.regularizers import l2from tensorflow.keras.preprocessing.image import ImageDataGeneratorfrom tensorflow.keras.a(chǎn)pplications import Xceptionfrom tensorflow.keras.layers import ( Flatten, Dense, AveragePooling2D, Dropout)from tensorflow.keras.optimizers import SGDfrom tensorflow.keras.preprocessing import imagefrom tensorflow.keras import Modelfrom tensorflow.keras.preprocessing.image import img_to_arrayfrom tensorflow.keras.callbacks import ( EarlyStopping, ModelCheckpoint, LearningRateScheduler)如上所示,我們將使用的基本模型是Xception,讓我們實例化它并添加一些全連接層。因為我們有很多圖像,所以我們將使用較小的批處理大小8。我們還需要警惕我們的小型數(shù)據(jù)集過度擬合。SHAPE = 224BATCH_SIZE = 8
model = Xception( input_shape=(SHAPE, SHAPE, 3), include_top=False, weights='imagenet')
x = model.outputx = AveragePooling2D(pool_size=(2, 2))(x)x = Dense(32, activation='relu')(x)x = Dropout(0.1)(x)x = Flatten()(x)x = Dense(4, activation='softmax', kernel_regularizer=l2(.0005))(x)
model = Model(inputs=model.inputs, outputs=x)
opt = SGD(lr=0.0001, momentum=.9)model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy'])在此之后,讓我們使用TensorFlow的ImageDataGenerator及其flow_from_directory創(chuàng)建圖像生成器對象。由于我們沒有足夠的訓練圖像,圖像增強比以往任何時候都更重要。train_datagen = ImageDataGenerator( rescale=1./255, rotation_range=15, width_shift_range=0.1, height_shift_range=0.1, horizontal_flip=True)
valid_datagen = ImageDataGenerator( rescale=1./255, rotation_range=0, width_shift_range=0.0, height_shift_range=0.0, horizontal_flip=False)
train_generator = train_datagen.flow_from_directory( 'train/', target_size=(SHAPE, SHAPE), shuffle=True, batch_size=BATCH_SIZE, class_mode='categorical',)
valid_generator = valid_datagen.flow_from_directory( 'valid/', target_size=(SHAPE, SHAPE), shuffle=True, batch_size=BATCH_SIZE, class_mode='categorical',)
>>> Found 178 images belonging to 4 classes.>>> Found 42 images belonging to 4 classes.讓我們在.fit()即我們的模型之前定義一些回調(diào)函數(shù)。earlystop = EarlyStopping(monitor='val_loss', patience=4, verbose=1)
checkpoint = ModelCheckpoint( "model-weights/xception_checkpoint.h5", monitor="val_loss", mode="min", save_best_only=True, verbose=1)我們的模型終于開始訓練了!history = model.fit_generator( train_generator, epochs=30, callbacks=[earlystop, checkpoint], validation_data=valid_generator)
# Save our model for inferencemodel.save("model-weights/xception.h5")
不幸的是,由于我們擁有的圖像數(shù)量有限,我們的模型在驗證集上無法獲得非常好的準確性,但是,模型微調(diào)并不是本文的重點,因此我們不會對此進行過多介紹。選擇我們的Web框架在這個項目中,我選擇使用streamlit(https://www.streamlit.io/) ,因為它可以實現(xiàn)機器學習應用程序的超快速可視化,并且科可以方便地用Python編寫。建立好這些之后,剩下要做的就是部署它。首先,導入所需的庫并指定模型權(quán)重的路徑,同樣由于我們使用了flow_from_directory ,TensorFlow按字母順序分配類編號,因此,D24將為0類,依此類推。import numpy as np
from PIL import Imagefrom tensorflow.keras.models import load_modelfrom tensorflow.keras.preprocessing.image import img_to_arrayfrom tensorflow.keras.preprocessing import imageimport streamlit as st
PATH = "model-weights/"WEIGHTS = "xception.h5"CLASS_DICT = { 0: 'D24', 1: 'JIN FENG', 2: 'MAO SHAN WANG', 3: 'RED PRAWN'}
接下來,我們創(chuàng)建一個函數(shù),將上傳的圖像轉(zhuǎn)換為模型要使用的格式。我們使用PIL中的Image類,因為上傳的圖像是BytesIO格式的。def load_img(input_image, shape): img = Image.open(input_image).convert('RGB') img = img.resize((shape, shape)) img = image.img_to_array(img) return np.reshape(img, [1, shape, shape, 3])/255Streamlit的工作方式是,用戶指定參數(shù)的每一次更改,腳本都會從上到下重新運行(因此它是交互式的UI),因此它以st.cache形式提供了一個緩存裝飾器來緩存加載的對象。緩存通常用于數(shù)據(jù)加載步驟或任何需要長時間計算/處理的步驟。
請記住,我們使用allow_output_variation=True參數(shù),因為默認情況下這是False,如果輸出對象以任何方式發(fā)生了變化,則應用程序?qū)⒈恢匦录虞d。在我們的例子中,模型對象將在每次預測中發(fā)生變化,因此我們將 allow_output_variation的參數(shù)設(shè)置為True。我們之所以要緩存我們的模型是因為我們不希望每次用戶選擇不同的圖像時都加載它(即只加載一次模型)。@st.cache(allow_output_mutation=True)def load_own_model(weights): return load_model(weights)最后,我們只需要向UI添加一些代碼即可:if __name__ == "__main__": result = st.empty() uploaded_img = st.file_uploader(label='upload your image:') if uploaded_img: st.image(uploaded_img, caption="your sexy durian pic", width=350) result.info("please wait for your results") model = load_own_model(PATH + WEIGHTS) pred_img = load_img(uploaded_img, 224) pred = CLASS_DICT[np.a(chǎn)rgmax(model.predict(pred_img))] result.success("The breed of durian is " + pred)我們用Python創(chuàng)建的web應用程序不需要太多的代碼行。你可以確保它(假設(shè)它會被調(diào)用應用程序副本)可以通過在命令行中輸入以下命令在本地運行:streamlit run app.py將我們的模型部署到Heroku就我個人而言,部署不是我最喜歡的部分,但是,如果web應用程序不在web上,那它還有什么意義呢?我們開始吧。你可以通過多種方式為web應用程序提供服務,也可以使用許多云服務提供商來托管它。在這種情況下,我選擇使用Heroku主要是因為我以前沒有嘗試過。
什么是Heroku?
Heroku是一個云平臺即服務(PaaS),支持多種編程語言,允許開發(fā)人員完全在云中構(gòu)建、運行和操作應用程序。下面這篇文章解釋得很清楚。文章鏈接:https://devcenter.heroku.com/articles/how-h(huán)eroku-works在Heroku部署為了部署應用程序,我們總是需要某種版本控制,以確保我們的應用程序運行在一個不同的服務器上,而不是在本地計算機上。為此,許多人使用Docker容器,指定所需的可運行應用程序和包。
使用Heroku進行部署類似于同時使用Docker容器和web托管服務,但是,它使用Git作為部署應用程序的主要手段。我們不需要將所有必需的文件打包到Docker容器中,而是創(chuàng)建一個用于版本控制的git存儲庫,然后我們可以使用熟悉的git push,但是要用到heroku遠程。Heroku隨后使用了相同的容器技術(shù),以dyno的形式進行。每個應用程序都放在一個dyno(或容器)中,每個應用程序都消耗“dyno hours”。每個Heroku帳戶都有一些可用的空閑小時數(shù),消耗的小時數(shù)取決于應用程序的活動/流量。
如果你的應用程序不需要大量流量,那么免費套餐應已足夠了。另外值得注意的是,當Heroku接收到應用程序源時,它會啟動應用程序的構(gòu)建(例如在requirements.txt創(chuàng)建必要的資產(chǎn)等),被組裝成一個slug。術(shù)語解釋:slug是源代碼、獲取的依賴項、語言運行時和編譯生成的系統(tǒng)輸出的捆綁包—為執(zhí)行做準備。要在Heroku上部署,我們需要以下文件:(1)setup.sh創(chuàng)建必要的目錄并將一些信息(例如端口號)寫入.toml文件mkdir -p ~/.streamlit/
echo "[server]headless = trueport = $PORTenableCORS = false\n" > ~/.streamlit/config.toml(2) Procfile類似于Dockerfile,包含我們要執(zhí)行的指令。我們將首先在setup.sh中執(zhí)行一些bash命令,然后執(zhí)行streamlit run app.py命令。web: sh setup.sh && streamlit run app.py(3) requirements.txt包含應用程序所需的所有包依賴項。請注意,這些是我正在使用的版本。你可以通過終端中的conda list或使用pip freeze > requirements.txt獲取環(huán)境當前使用的軟件包的詳盡列表。numpy==1.18.1spacy==2.2.4pandas==1.0.1Pillow==7.1.2streamlit==0.61.0tensorflow-cpu==2.2.0我們的文件夾目錄應如下所示:app.pyProcfileREADME.mdrequirements.txtsetup.shmodel-weights|-- xception.h5如果你以前從未創(chuàng)建過Github存儲庫,請按照以下一些簡單步驟進行操作:創(chuàng)建一個新的存儲庫<repo_name>
復制紅色框中的URL
在終端上,運行以下命令:# Clone the repository into our local machinegit clone <repo URL in step 2>
# Enter the directory we just clonedcd <repo_name>將之前創(chuàng)建的文件復制到此文件夾中,然后在終端中運行以下命令:# Add all the files we just copied over to be committedgit add .
# Commit the files, along with a commit messagegit commit -m "deploy app"
# Push to master branch on our github repogit push origin master我們就快到了!這是最后的步驟。
(1)創(chuàng)建一個Heroku帳戶并進行驗證
(2)在此處(https://devcenter.heroku.com/articles/heroku-cli) 安裝Heroku CLI
(3)通過終端登錄到你的Heroku帳戶。將打開一個瀏覽器窗口,供你進行身份驗證。heroku login
(4)創(chuàng)建一個Heroku應用heroku create <project-name>完成此步驟后,你將能夠在終端中看到指向你的項目的鏈接。
(5)將git repo推送到Heroku遙控器。在我們的github存儲庫的同一目錄中,運行以下命令:git push heroku master我們完成了!構(gòu)建完成后,你應該能夠在上面的鏈接中看到部署的應用程序!
請輸入評論內(nèi)容...
請輸入評論/評論長度6~500個字
最新活動更多
-
10月31日立即下載>> 【限時免費下載】TE暖通空調(diào)系統(tǒng)高效可靠的組件解決方案
-
即日-11.13立即報名>>> 【在線會議】多物理場仿真助跑新能源汽車
-
11月28日立即報名>>> 2024工程師系列—工業(yè)電子技術(shù)在線會議
-
12月19日立即報名>> 【線下會議】OFweek 2024(第九屆)物聯(lián)網(wǎng)產(chǎn)業(yè)大會
-
即日-12.26火熱報名中>> OFweek2024中國智造CIO在線峰會
-
即日-2025.8.1立即下載>> 《2024智能制造產(chǎn)業(yè)高端化、智能化、綠色化發(fā)展藍皮書》
推薦專題
- 高級軟件工程師 廣東省/深圳市
- 自動化高級工程師 廣東省/深圳市
- 光器件研發(fā)工程師 福建省/福州市
- 銷售總監(jiān)(光器件) 北京市/海淀區(qū)
- 激光器高級銷售經(jīng)理 上海市/虹口區(qū)
- 光器件物理工程師 北京市/海淀區(qū)
- 激光研發(fā)工程師 北京市/昌平區(qū)
- 技術(shù)專家 廣東省/江門市
- 封裝工程師 北京市/海淀區(qū)
- 結(jié)構(gòu)工程師 廣東省/深圳市