↓↓↓點(diǎn)擊關(guān)注,回復(fù)資料,10個(gè)G的驚喜
很多人可能參加過許多比賽,做過許多項(xiàng)目,但比賽或項(xiàng)目結(jié)束之后,曾經(jīng)寫過的代碼、用過的模型就被丟到了一邊,甚至不久就被刪掉。這種情況并不只存在于比賽中,在學(xué)術(shù)領(lǐng)域同樣存在。當(dāng)學(xué)生訓(xùn)練完模型、寫完論文并被學(xué)術(shù)會(huì)議接收后,該模型的 pipeline 就會(huì)被拋棄,訓(xùn)練數(shù)據(jù)也隨之被刪除。這是不是有點(diǎn)太可惜了?長(zhǎng)期參加 Kaggle 比賽的 Vladimir Iglovikov 在自己的博客中指出了這個(gè)問題,并提出了一些重新利用這些資源的建議。Vladimir Iglovikov 是一位 Kaggle Grandmaster,曾在 Kaggle 全球榜單中排名第 19,拿到過 Carvana 圖像遮蔽挑戰(zhàn)的冠軍(他的個(gè)人經(jīng)歷參見:《Kaggle Grandmaster 是怎樣煉成的》)。在他看來,競(jìng)賽中曾經(jīng)用到的代碼、權(quán)重等資源是一筆寶貴的財(cái)富,可以幫助你鞏固技術(shù)知識(shí)、樹立個(gè)人品牌、提高就業(yè)機(jī)會(huì)。為了解釋這些資源資源的價(jià)值,他還專門創(chuàng)建了一個(gè) GitHub 項(xiàng)目(retinaface)來講述文本的建議。項(xiàng)目鏈接:https://github.com/ternaus/retinaface
花 5 分鐘將代碼發(fā)布到公開的 GitHub 存儲(chǔ)庫(kù)很多時(shí)候,你的代碼可能已經(jīng)存到 GitHub 上了,但是是存在私人庫(kù)里。那公開又有什么損失呢?某些情況下,有些代碼確實(shí)不宜公開,但你在 Kaggle 里做的那些練手項(xiàng)目、解決方案和論文或許沒這個(gè)必要。為什么有些人不愿公開呢?因?yàn)楹芏嗳苏J(rèn)為,「所有公開發(fā)布的代碼都應(yīng)該是完美的,否則就會(huì)遭到批判?!?/span>但實(shí)際情況是,其他人根本不 care,你只管發(fā)布就行。公開代碼是心理防線的一次重大突破,公開不完美的代碼更是一個(gè)自信、大膽的舉動(dòng)。所有后續(xù)步驟也都在這一步的基礎(chǔ)上展開。你可以通過添加語(yǔ)法格式化工具和檢查工具來提升 python 代碼的可讀性。這并不困難,也并不費(fèi)時(shí)。檢查工具和格式化程序不會(huì)將爛代碼變成好代碼,但其可讀性會(huì)有所提升。以下是具體步驟:將這些文件添加到存儲(chǔ)庫(kù)的根目錄。pip?install?black?flake8?mypy
格式化代碼的方法有 100500 多種。諸如 black 或 yapf 之類的格式化工具會(huì)按照一組預(yù)定義的規(guī)則來修改代碼。閱讀具有一定標(biāo)準(zhǔn)的代碼庫(kù)會(huì)更加容易。當(dāng)你花費(fèi)幾個(gè)小時(shí)編寫代碼并需要在不同的編碼風(fēng)格之間切換語(yǔ)境時(shí),你的意志力會(huì)被消耗殆盡。因此,沒有充分的理由就不要這么做。運(yùn)行以下命令將重新格式化所有的 python 文件以遵循 black 的規(guī)則。black?.
運(yùn)行以下命令不會(huì)修改代碼,但會(huì)檢查代碼中的語(yǔ)法問題并將其輸出到屏幕上。然后修改這些問題。flake8
Python 沒有強(qiáng)制性的靜態(tài)類型化,但還是建議將類型添加至函數(shù)參數(shù)并返回類型。例如:class?MyModel(nn.Module):
????....
def?forward(x:?torch.Tensor)?->?torch.Tensor:
????....
????return?self.final(x)
你應(yīng)該在代碼中添加鍵入內(nèi)容。這會(huì)讓代碼讀起來更容易。你可以使用 mypy 包檢查參數(shù)和函數(shù)類型的一致性。更新代碼后,在整個(gè)存儲(chǔ)庫(kù)上運(yùn)行 mypy:mypy?.
如果 mypy 出現(xiàn)問題,修復(fù)它們。一直手動(dòng)運(yùn)行 flake8、black 和 mypy 會(huì)覺得厭倦。一個(gè)名為 pre-commit 的鉤子能夠解決這個(gè)問題。要啟用它,可以將以下文件復(fù)制到你的存儲(chǔ)庫(kù)中:https://github.com/ternaus/retinaface/blob/master/.pre-commit-config.yaml你需要使用以下命令安裝 pre-commit 包。pip?install?pre-commit
pre-commit?install
安裝完成后,每次提交都會(huì)經(jīng)歷一組檢查。當(dāng)提交中有錯(cuò)誤時(shí),檢查不會(huì)允許提交通過。這和手動(dòng)運(yùn)行 black、flake8 以及 mypy 的不同之處在于,它不會(huì)乞求你修復(fù)問題,而是強(qiáng)制要求你做這件事。因此,這種方法不會(huì)浪費(fèi)你的意志力、你已經(jīng)向 pre-commit 鉤子中添加了檢查步驟,并在本地運(yùn)行了這些步驟。但是你還需要第二道防線——讓 GitHub 在每個(gè)拉取請(qǐng)求上運(yùn)行這些檢查步驟。你要做的就是將以下文件添加到存儲(chǔ)庫(kù)中:https://github.com/ternaus/retinaface/blob/master/.github/workflows/ci.yml執(zhí)行以下代碼來告訴 GitHub 要檢查什么:-?name:?Install?dependencies
??????run:?|
????????python?-m?pip?install?--upgrade?pip
????????pip?install?-r?requirements.txt
????????pip?install?black?flake8?mypy
????-?name:?Run?black
??????run:
????????black?--check?.
????-?name:?Run?flake8
??????run:?flake8
????-?name:?Run?Mypy
??????run:?mypy?retinaface
我還建議放棄將代碼直接推送到 master 分支的做法。你可以創(chuàng)建一個(gè)新的分支、修改代碼、提交、放到 Github 上、創(chuàng)建 PR 請(qǐng)求,然后合并到 master。這是一項(xiàng)行業(yè)標(biāo)準(zhǔn),但是在學(xué)術(shù)研究和 Kaggle 參賽者中卻不常見。如果你對(duì)這些工具不熟悉,可能需要花 20 分鐘添加它們并修復(fù)錯(cuò)誤和警告。記住這次的操作。在下個(gè)項(xiàng)目中,你可以在沒寫代碼之前就在第一次提交中添加這些檢查。從這個(gè)時(shí)候開始,每次小的提交都會(huì)被檢查,你每次最多只需要修復(fù)幾行代碼。這么做開銷很小,也是一個(gè)良好的習(xí)慣。花 20 分鐘寫一個(gè)優(yōu)秀的 readme對(duì)你自己而言:可能你認(rèn)為你永遠(yuǎn)都不會(huì)再用到這些代碼了,但實(shí)際上并不一定。下次用的時(shí)候你可能也記不得它的具體內(nèi)容了,但 readme 可以幫到你。
對(duì)其他人而言:readme 是一個(gè)賣點(diǎn)。如果人們看不出該存儲(chǔ)庫(kù)的用途以及它所解決的問題,大家就不會(huì)使用它,你所做的所有工作都不會(huì)對(duì)他人產(chǎn)生積極影響。
一個(gè)機(jī)器學(xué)習(xí)庫(kù)的最低要求是說明以下問題:如果你需要寫 100500 個(gè)詞來描述怎樣運(yùn)行訓(xùn)練或者推理,那就說明你的項(xiàng)目存在問題了。你需要重構(gòu)代碼,使它對(duì)用戶更加友好。
人們經(jīng)常會(huì)問:如何提高寫代碼的能力?這便是一個(gè)鍛煉你的機(jī)會(huì)。你可能需要重寫代碼,嘗試站在別人的角度看待你的 Readme。這是一個(gè)很好的鍛煉機(jī)會(huì),它能夠讓你學(xué)會(huì)從用戶的角度看待問題。我猜你會(huì)編寫如下代碼來加載預(yù)訓(xùn)練模型權(quán)重。model?=?MyFancyModel()
state_dict?=?torch.load()
model.load_state_dict(state_dict)
這樣的方法雖然有用且步驟清晰,但是它需要磁盤上的權(quán)重,并且要知道它們的位置。一個(gè)更好的解決方案是在 TensorFlow 或 Keras 上使用 torchvision 中的 torch.utils.model_zoo.load_url 函數(shù):from?retinaface.pre_trained_models?import?get_model
model?=?get_model("resnet50_2020-07-20",?max_size=2048)
用上面的代碼從 retinaface.pre_trained_models 中引入 get_modelmodel = get_model("resnet50_2020-07-20", max_size=2048)。如果權(quán)重不在磁盤上,那就會(huì)從網(wǎng)絡(luò)上先下載下來再緩存到磁盤上。初始化模型,并加載權(quán)重,這對(duì)用戶來說是很友好的,也是你在 torchvision 和 timm 庫(kù)中所看到的。步驟 1:托管預(yù)訓(xùn)練模型的權(quán)重這對(duì)我來說是最大的障礙。如果不想使用 AWS、GCP,我要把模型的權(quán)重放在哪里?GitHub 上的 releases 是一個(gè)不錯(cuò)的選擇。
每個(gè)文件的大小限制是 2Gb,對(duì)大多數(shù)深度學(xué)習(xí)模型來說夠用了。步驟 2:編寫一個(gè)初始化模型和加載權(quán)重的函數(shù)。#?https://github.com/ternaus/retinaface/blob/master/retinaface/pre_trained_models.py?
?from?collections?import?namedtuple?
?from?torch.utils?import?model_zoo?
?from?retinaface.predict_single?import?Model?
?model?=?namedtuple("model",?["url",?"model"])?
?models?=?{?
?"resnet50_2020-07-20":?model(?
?url="https://github.com/ternaus/retinaface/releases/download/0.01/retinaface_resnet50_2020-07-20-f168fae3c.zip",?#?noqa:?E501?
?model=Model,?
????)?
?}?
?def?get_model(model_name:?str,?max_size:?int,?device:?str?=?"cpu")?->?Model:?
?????model?=?models[model_name].model(max_size=max_size,?device=device)?
?????state_dict?=?model_zoo.load_url(models[model_name].url,?progress=True,?map_location="cpu")?
?????model.load_state_dict(state_dict)?
?????return?model?
在構(gòu)建 Colab Notebook 和 WebApp 時(shí)會(huì)用到這個(gè)函數(shù)。花 20 分鐘創(chuàng)建一個(gè)庫(kù)步驟 1:向 requirements.txt 中添加必要的依賴,你可以手動(dòng)更新或使用如下代碼:pip?freeze?>?requiements.txt
步驟 2:改變存儲(chǔ)庫(kù)的文件結(jié)構(gòu)創(chuàng)建一個(gè)「主文件夾」,在我給出的示例中,這個(gè)文件夾叫「retinaface」。將所有重要代碼都放進(jìn)這個(gè)文件夾,但不要把 helper 圖像、Readme、notebook 或 test 放進(jìn)去。手動(dòng)操作這一步驟并更新所有的 import 會(huì)很累。PyCharm 或者類似的 IDE 會(huì)為你執(zhí)行這一步驟。這是存儲(chǔ)庫(kù)中構(gòu)建代碼結(jié)構(gòu)的常用方法。如果你想讓其更加結(jié)構(gòu)化,請(qǐng)查看 Cookie Cutter 包。向根目錄中添加 setup.py,內(nèi)容類似于示例文件「setup.py」中的內(nèi)容。添加包的版本,在我的示例中,我將它添加到了主文件夾的 init 文件中。步驟 4:在 PyPI 上創(chuàng)建一個(gè)賬戶。步驟 5:搭建一個(gè)庫(kù)并上傳到 PyPI 上。python?setup.py?sdist
python?setup.py?sdist?upload
你的存儲(chǔ)庫(kù)是一個(gè)庫(kù),每個(gè)人都可以使用如下命令安裝它:
pip?install?
如果你在 PyPI 上查看包的頁(yè)面,你就會(huì)看到它使用你存儲(chǔ)庫(kù)中的 Readme 文件來陳述項(xiàng)目。我們將會(huì)在 Google Colab 和 Web App 上使用這一步的功能。花 20 分鐘創(chuàng)建 Google Colab notebook將 Jupiter notebook 添加到存儲(chǔ)庫(kù)是一個(gè)好習(xí)慣,以展示如何初始化模型和執(zhí)行推理功能。在前兩個(gè)步驟中,我們使用了模型初始化和 pip install。接下來創(chuàng)建 Google Golab notebook。現(xiàn)在,只需要一個(gè)瀏覽器,就會(huì)有更多的人嘗試你的模型了。別忘了在 readme 中添加 notebook 的鏈接,并在 PyPi 上更新版本。許多數(shù)據(jù)科學(xué)家認(rèn)為構(gòu)建 web 應(yīng)用程序是一個(gè)復(fù)雜的過程,需要專業(yè)知識(shí)。這種想法是正確的。一個(gè)復(fù)雜項(xiàng)目的 web 應(yīng)用程序確實(shí)需要很多數(shù)據(jù)科學(xué)家并不具備的專業(yè)知識(shí),但構(gòu)建一個(gè)簡(jiǎn)單的 web 應(yīng)用程序來展示模型還是很容易的。我為一個(gè) web 應(yīng)用程序創(chuàng)建了一個(gè)單獨(dú)的 GitHub 存儲(chǔ)庫(kù)。不過,你仍然可以在你的存儲(chǔ)庫(kù)中用你的模型來操作。這里有一篇描述具體細(xì)節(jié)的技術(shù)博客:https://towardsdatascience.com/deploy-streamlit-on-heroku-9c87798d2088。"""Streamlit?web?app"""
import?numpy?as?np
import?streamlit?as?st
from?PIL?import?Image
from?retinaface.pre_trained_models?import?get_model
from?retinaface.utils?import?vis_annotations
import?torch
st.set_option("deprecation.showfileUploaderEncoding",?False)
@st.cache
def?cached_model():
????m?=?get_model("resnet50_2020-07-20",?max_size=1048,?device="cpu")
????m.eval()
????return?m
model?=?cached_model()
st.title("Detect?faces?and?key?points")
uploaded_file?=?st.file_uploader("Choose?an?image...",?type="jpg")
if?uploaded_file?is?not?None:
????image?=?np.array(Image.open(uploaded_file))
????st.image(image,?caption="Before",?use_column_width=True)
????st.write("")
????st.write("Detecting?faces...")
????with?torch.no_grad():
????????annotations?=?model.predict_jsons(image)
????if?not?annotations[0]["bbox"]:
????????st.write("No?faces?detected")
????else:
????????visualized_image?=?vis_annotations(image,?annotations)
????????st.image(visualized_image,?caption="After",?use_column_width=True)
步驟 3:添加 requirements.txt 文件heroku?login
heroku?create
git?push?heroku?master
很多人低估了他們研究的價(jià)值。實(shí)際上你的文章很可能能夠幫助別人,并且能夠?yàn)樽约旱穆殬I(yè)生涯提供更多的機(jī)會(huì)。如果要寫機(jī)器學(xué)習(xí)方面的文章,我建議你包含以下內(nèi)容:花時(shí)間寫篇論文,描述你在這場(chǎng)機(jī)器學(xué)習(xí)競(jìng)賽中的解決方案即使你的論文中沒有重大突破,它也會(huì)被發(fā)表并幫到別人。撰寫學(xué)術(shù)論文也是一項(xiàng)技能。你現(xiàn)在可能還不具備這種技能,但你可以與擅長(zhǎng)學(xué)術(shù)寫作的人合作。下面是我的 Google Scholar 引用情況,這幾年引用量的猛增都得益于我寫的那些總結(jié)機(jī)器學(xué)習(xí)競(jìng)賽的論文。
當(dāng)然,你的論文也包含在一個(gè)大包里,這個(gè)包里還有:GitHub 存儲(chǔ)庫(kù),里面有整潔的代碼和良好的 readme 文件。
非機(jī)器學(xué)習(xí)人員能夠使用的庫(kù)。
允許在瀏覽器中用你的模型進(jìn)行快速實(shí)驗(yàn)的 Colab notebook。
吸引非技術(shù)受眾的 WebApp。
用人類語(yǔ)言講故事的博客文章。
有了這些之后,它就不再只是一篇論文,而是一種綜合性的策略,可以顯示你對(duì)該項(xiàng)目的所有權(quán),還能幫助你與他人進(jìn)行溝通。這兩者對(duì)于你的職業(yè)生涯都是至關(guān)重要的。原文鏈接:https://medium.com/kaggle-blog/i-trained-a-model-what-is-next-d1ba1c560e26