์๋ ํ์ธ์ ์ฌ๋ฌ๋ถ! ์ ๋ CROC์ CV ๊ฐ๋ฐ์์ ๋๋ค. ์ฐ๋ฆฌ๋ ํ์ฌ 3๋ ๋์ CV ๋ถ์ผ์ ํ๋ก์ ํธ๋ฅผ ์งํํด ์์ต๋๋ค. ์ด ๊ธฐ๊ฐ ๋์ ์ฐ๋ฆฌ๋ ๋ง์ ์ผ์ ํ์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์ด์ ํ๋ ๋์ ์ ์ ๋ง์์ง ์๊ณ , ๋ด๋ฐฐ๋ฅผ ํผ์ฐ์ง ์๊ณ , ์ ํ๋ฅผ ํ์ง ์๊ณ , ๊ธธ์ ๋ฐ๋ผ๋ณด๊ณ , ๊ฟ์ด๋ ๊ตฌ๋ฆ์ ๋ณด์ง ์๋๋ก ์ด์ ์๋ฅผ ๋ชจ๋ํฐ๋งํ์ต๋๋ค. ; ์ฐ๋ฆฌ๋ ์ ์ฉ ์ฐจ์ ์์ ์ด์ ํ๊ณ ์ฌ๋ฌ ์ฃผ์ฐจ ๊ณต๊ฐ์ ์ฐจ์งํ๋ ์ฌ๋๋ค์ ๊ธฐ๋กํ์ต๋๋ค. ๊ทผ๋ก์๊ฐ ํฌ๋ฉง, ์ฅ๊ฐ ๋ฑ์ ์ฐฉ์ฉํ๋์ง ํ์ธํฉ๋๋ค. ์์ค์ ๋ค์ด๊ฐ๊ณ ์ถ์ดํ๋ ์ง์์ ์๋ณํ์ต๋๋ค. ์ฐ๋ฆฌ๋ ์ฐ๋ฆฌ๊ฐ ํ ์ ์๋ ๋ชจ๋ ๊ฒ์ ์ธ์์ต๋๋ค.
๋ด๊ฐ ์ด ๋ชจ๋ ๊ฒ์ ๋ฌด์์ ์ํด ํ๊ณ ์๋ ๊ฑธ๊น์?
ํ๋ก์ ํธ๋ฅผ ์คํํ๋ ๊ณผ์ ์์ ์ฐ๋ฆฌ๋ ๋ถ๋ชํ๊ณ , ๋ง์ ์ถฉ๋์ ๊ฒช๊ฒ ๋ฉ๋๋ค. ์ฌ๋ฌ๋ถ์ด ์ด๋ฏธ ์๊ณ ์๊ฑฐ๋ ์์ผ๋ก ์๊ฒ ๋ ๋ฌธ์ ๋ค๋ ์์ต๋๋ค.
์ํฉ ๋ชจ๋ธ๋ง
ML๊ณผ ๊ด๋ จ๋ ํ๋์ ํ๋ ์ ์ ํ์ฌ N์ ์ทจ์งํ๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค. ์ฐ๋ฆฌ๋ ML(DL, CV) ํ๋ก์ ํธ๋ฅผ ์งํํ๋ค๊ฐ ์ด๋ค ์ด์ ๋ก ๋ค๋ฅธ ์ง์ ์ผ๋ก ์ ํํ๊ณ ์ผ๋ฐ์ ์ผ๋ก ํด์์ ์ทจํ ํ ์ฐ๋ฆฌ ์์ ์ด๋ ๋ค๋ฅธ ์ฌ๋์ ๋ด๋ฐ์ผ๋ก ๋์๊ฐ๋๋ค.
- ์ง์ค์ ์๊ฐ์ด ์ค๋ฉด, ์ด๋์์ ๋ฉ์ท๋์ง, ์ด๋ค ํ์ดํผํ๋ผ๋ฏธํฐ๋ฅผ ์๋ํ๋์ง, ๊ทธ๋ฆฌ๊ณ ๊ฐ์ฅ ์ค์ํ๊ฒ๋ ๊ทธ ๊ฒฐ๊ณผ๊ฐ ๋ฌด์์ธ์ง ๊ธฐ์ตํด์ผ ํฉ๋๋ค.
ํค๋, ๊ตฌ์ฑ, ๋ฉ๋ชจ์ฅ, ํด๋ผ์ฐ๋์ ์์ ํ๊ฒฝ ๋ฑ ๋ชจ๋ ์คํ์ ๋ํ ์ ๋ณด๋ฅผ ์ ์ฅํ ์ฌ๋์ ๋ํ ๋ค์ํ ์ต์ ์ด ์์ ์ ์์ต๋๋ค. ํ์ดํผํ๋ผ๋ฏธํฐ๊ฐ ์ฝ๋์ ์ฃผ์ ์ฒ๋ฆฌ๋ ์ค๋ก ์ ์ฅ๋์ด ์์ ๋ ์ฐ์ฐํ ์ต์ ์ ๋ณด๊ฒ ๋์๋๋ฐ, ์ด๋ ์ผ๋ฐ์ ์ผ๋ก ํ์์ ์ด์์ต๋๋ค. ์ด์ ๋น์ ์ด ์์ ์ ํ๋ก์ ํธ๊ฐ ์๋ ํ์ฌ๋ฅผ ๋ ๋ ์ฌ๋์ ํ๋ก์ ํธ๋ก ๋์๊ฐ์ model_1.pb๋ผ๋ ์ฝ๋์ ๋ชจ๋ธ์ ์์๋ฐ์๋ค๊ณ ์์ํด ๋ณด์ญ์์ค. ๊ทธ๋ฆผ์ ์์ฑํ๊ณ ๋ชจ๋ ๊ณ ํต์ ์ ๋ฌํ๊ธฐ ์ํด ๋น์ ๋ ์ด๋ณด ์ ๋ฌธ๊ฐ๋ผ๊ณ ์์ํด ๋ด ์๋ค. - ๊ณ์ํ์ธ์. ์ฝ๋๋ฅผ ์คํํ๋ ค๋ฉด ์ฐ๋ฆฌ์ ์ฝ๋๋ฅผ ์ฌ์ฉํ๋ ๋ชจ๋ ์ฌ๋์ด ํ๊ฒฝ์ ๋ง๋ค์ด์ผ ํฉ๋๋ค. ์ด๋ค ์ด์ ๋ก ๊ทธ๋ค์ ๊ทธ๋ฅผ ์ฐ๋ฆฌ์ ์์ ์ฌ์ฐ์ผ๋ก ๋จ๊ฒจ ๋์ง ์๋ ๊ฒฝ์ฐ๊ฐ ์ข ์ข ์์ต๋๋ค. ์ด๊ฒ์ ๋ํ ์ฌ์ํ ์์ ์ด ๋ ์ ์์ต๋๋ค. ์ด ๋จ๊ณ์์ ์๊ฐ์ ๋ญ๋นํ๊ณ ์ถ์ง ์์ต๋๊น?
- ๋ชจ๋ธ(์: ์๋์ฐจ ๊ฐ์ง๊ธฐ)์ ํ์ตํฉ๋๋ค. ๊ฒฐ๊ณผ๊ฐ ๋งค์ฐ ์ข์์ง๋ ์ง์ ์ ์ด๋ฅด๋ ์ต๋๋ค. ์ด์ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ ์๊ฐ์ ๋๋ค. car_Detection_v1.pb๋ผ๊ณ ๋ถ๋ฅด๊ฒ ์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ car_Detection_v2.pb๋ผ๋ ๋ ๋ค๋ฅธ ๊ฒ์ ํ๋ จํฉ๋๋ค. ์ผ๋ง ํ, ์ฐ๋ฆฌ ๋๋ฃ๋ ์ฐ๋ฆฌ ์์ ์ ๋ค์ํ ์ํคํ ์ฒ๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ ๋ ๋ง์ ๊ฒ์ ๊ฐ๋ฅด์นฉ๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ๋ง์ ์ ๋ฌผ์ด ํ์ฑ๋๊ณ ์ด์ ๋ํ ์ ๋ณด๋ฅผ ํ๋ค๊ฒ ์์งํด์ผ ํฉ๋๋ค(๊ทธ๋ฌ๋ ์ง๊ธ์ ๋ ์ค์ํ ๋ฌธ์ ๊ฐ ์์ผ๋ฏ๋ก ์ด ์์ ์ ๋์ค์ ์ํํ ๊ฒ์ ๋๋ค).
- ์ข์ ์ด์ ๋ค ๋๋ฌ์ด! ์ฐ๋ฆฌ์๊ฒ ๋ชจ๋ธ์ด ์์ด์! ๋ค์ ๋ชจ๋ธ ํ์ต์ ์์ํ๊ณ ์๋ก์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ์ํคํ ์ฒ๋ฅผ ๊ฐ๋ฐํ ์ ์๋์? ์๋๋ฉด ์ฐจ๋ฅผ ๋ง์๋ฌ ๊ฐ ์ ์๋์? ๊ทธ๋ฆฌ๊ณ ๋๊ฐ ๋ฐฐ์นํ ๊ฒ์ธ๊ฐ?
๋ฌธ์ ์๋ณ
ํ๋ก์ ํธ๋ ์ ํ ์์ ์ ๋ง์ ์ฌ๋๋ค์ ์์ ์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์๊ฐ์ด ์ง๋๋ฉด์ ์ฌ๋๋ค์ด ๋ ๋๊ณ ๋ค์ด์ค๊ณ , ํ๋ก์ ํธ๋ ๋์ด๋๊ณ , ํ๋ก์ ํธ ์์ฒด๋ ๋์ฑ ๋ณต์กํด์ง๋๋ค. ์ด๋ค ์์ผ๋ก๋ ํน์ ์กฐํฉ์์ ์์์ ์ค๋ช ํ ์ฃผ๊ธฐ์ ์ํฉ์ ๋ฐ๋ณต๋ง๋ค ๋ฐ์ํฉ๋๋ค. ์ด ๋ชจ๋ ๊ฒ์ ์๊ฐ ๋ญ๋น, ํผ๋, ๋ถ์, ๊ณ ๊ฐ ๋ถ๋ง์กฑ, ๊ถ๊ทน์ ์ผ๋ก๋ ๋ ์์ค์ ์ด๋ํฉ๋๋ค. ์ฐ๋ฆฌ ๋ชจ๋๋ ์ผ๋ฐ์ ์ผ๋ก ๋๊ฐ์ ๊ฐํด๋ฅผ ๋ฐ๋ฅด์ง๋ง, ๋๊ตฌ๋ ์ด๋ฌํ ์๊ฐ์ ๋ฐ๋ณตํด์ ์ฌํํ๊ณ ์ถ์ดํ์ง ์๋๋ค๊ณ ๋ฏฟ์ต๋๋ค.
๊ทธ๋์ ์ฐ๋ฆฌ๋ ํ๋์ ๊ฐ๋ฐ ์ฃผ๊ธฐ๋ฅผ ๊ฑฐ์ณค๊ณ ํด๊ฒฐํด์ผ ํ ๋ฌธ์ ๊ฐ ์๋ค๋ ๊ฒ์ ์๊ฒ ๋์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ ค๋ฉด ๋ค์์ด ํ์ํฉ๋๋ค.
- ์์ ๊ฒฐ๊ณผ๋ฅผ ํธ๋ฆฌํ๊ฒ ์ ์ฅํฉ๋๋ค.
- ์ ๊ท ์ง์ ์ฐธ์ฌ ๊ณผ์ ์ ๋จ์ํํฉ๋๋ค.
- ๊ฐ๋ฐ ํ๊ฒฝ ๋ฐฐํฌ ํ๋ก์ธ์ค๋ฅผ ๋จ์ํํฉ๋๋ค.
- ๋ชจ๋ธ ๋ฒ์ ๊ด๋ฆฌ ํ๋ก์ธ์ค๋ฅผ ๊ตฌ์ฑํฉ๋๋ค.
- ๋ชจ๋ธ์ ๊ฒ์ฆํ๋ ํธ๋ฆฌํ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
- ๋ชจ๋ธ ์ํ ๊ด๋ฆฌ ๋๊ตฌ๋ฅผ ์ฐพ์ผ์ธ์.
- ๋ชจ๋ธ์ ํ๋ก๋์ ๋จ๊ณ๋ก ์ ๋ฌํ๋ ๋ฐฉ๋ฒ์ ์ฐพ์ผ์ธ์.
์ด ๋ผ์ดํ์ฌ์ดํด์ ์ฝ๊ณ ํธ๋ฆฌํ๊ฒ ๊ด๋ฆฌํ ์ ์๋ ์ํฌํ๋ก์ฐ๊ฐ ํ์ํ ๊ฒ ๊ฐ์๋ฐ์? ์ด ๋ฐฉ์์ MLOps๋ผ๊ณ ํฉ๋๋ค.
MLOps(๊ธฐ๊ณ ํ์ต์ ์ํ DevOps)๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐ ๊ณผํ ํ๊ณผ IT ํ์ด ํ๋ ฅํ์ฌ ๊ธฐ๊ณ ํ์ต ๋ชจ๋ธ์ ๋ํ ๋ชจ๋ํฐ๋ง, ๊ฒ์ฆ ๋ฐ ๊ฑฐ๋ฒ๋์ค๋ฅผ ํตํด ๋ชจ๋ธ ๊ฐ๋ฐ ๋ฐ ๋ฐฐํฌ ์๋๋ฅผ ๋์ผ ์ ์์ต๋๋ค.
๋๋ ํ ์์๋ค.
๋ด ๊ธฐ์ฌ์์๋ ํ๋ก์ธ์ค์ ์ผ๋ถ๋ง ์ค๋ช ํ๊ฒ ์ต๋๋ค. ๊ตฌํ์ ์ํด MLflow ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๊ฒ ์ต๋๋ค. ์๋ํ๋ฉด... ์ด๊ฒ์ ์คํ ์์ค ํ๋ก์ ํธ์ด๋ฏ๋ก ์ฐ๊ฒฐํ๋ ๋ฐ ์๋์ ์ฝ๋๊ฐ ํ์ํ๋ฉฐ ๋๋ฆฌ ์ฌ์ฉ๋๋ ml ํ๋ ์์ํฌ์ ํตํฉ๋์ด ์์ต๋๋ค. ์ธํฐ๋ท์์ Kubeflow, SageMaker, Trains ๋ฑ๊ณผ ๊ฐ์ ๋ค๋ฅธ ๋๊ตฌ๋ฅผ ๊ฒ์ํ์ฌ ํ์์ ๋ ์ ํฉํ ๋๊ตฌ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.
MLFlow ๋๊ตฌ ์ฌ์ฉ ์๋ฅผ ์ฌ์ฉํ์ฌ MLOps "๊ตฌ์ถ"
MLFlow๋ ML ๋ชจ๋ธ์ ์๋ช
์ฃผ๊ธฐ ๊ด๋ฆฌ๋ฅผ ์ํ ์คํ ์์ค ํ๋ซํผ์
๋๋ค(
MLflow์๋ ๋ค ๊ฐ์ง ๊ตฌ์ฑ ์์๊ฐ ํฌํจ๋ฉ๋๋ค.
- MLflow ์ถ์ - ์ด ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ ธ์จ ๋งค๊ฐ๋ณ์ ๋ฐ ๊ฒฐ๊ณผ ๊ธฐ๋ก ๋ฌธ์ ๋ฅผ ๋ค๋ฃน๋๋ค.
- MLflow ํ๋ก์ ํธ - ์ฝ๋๋ฅผ ํจํค์งํ๊ณ ๋ชจ๋ ํ๋ซํผ์์ ์ฌํํ ์ ์์ต๋๋ค.
- MLflow ๋ชจ๋ธ - ํ๋ก๋์ ์ ๋ชจ๋ธ ๋ฐฐํฌ๋ฅผ ๋ด๋นํฉ๋๋ค.
- MLflow Registry - ์ค์ ์ ์ฅ์์์ ๋ชจ๋ธ์ ์ ์ฅํ๊ณ ํด๋น ์ํ๋ฅผ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
MLflow๋ ๋ ์ํฐํฐ์์ ์๋ํฉ๋๋ค.
- ์ถ์๋ ์ฐ๋ฆฌ๊ฐ ๋ฑ๋กํ๋ ค๋ ๊ต์ก, ๋งค๊ฐ๋ณ์ ๋ฐ ์งํ์ ์ ์ฒด ์ฃผ๊ธฐ์ ๋๋ค.
- ์คํ์ ํจ๊ป ์งํ๋๋ '์ฃผ์ '์ ๋๋ค.
์์ ์ ๋ชจ๋ ๋จ๊ณ๋ Ubuntu 18.04 ์ด์ ์ฒด์ ์์ ๊ตฌํ๋ฉ๋๋ค.
1. ์๋ฒ ๋ฐฐํฌ
ํ๋ก์ ํธ๋ฅผ ์ฝ๊ฒ ๊ด๋ฆฌํ๊ณ ํ์ํ ๋ชจ๋ ์ ๋ณด๋ฅผ ๋ฐ์ ์ ์๋๋ก ์๋ฒ๋ฅผ ๋ฐฐํฌํ๊ฒ ์ต๋๋ค. MLflow ์ถ์ ์๋ฒ์๋ ๋ ๊ฐ์ง ์ฃผ์ ๊ตฌ์ฑ ์์๊ฐ ์์ต๋๋ค.
- ๋ฐฑ์๋ ์ ์ฅ์ - ๋ฑ๋ก๋ ๋ชจ๋ธ์ ๋ํ ์ ๋ณด๋ฅผ ์ ์ฅํ๋ ์ญํ ์ ๋ด๋นํฉ๋๋ค(4๊ฐ์ DBMS ์ง์: mysql, mssql, sqlite ๋ฐ postgresql).
- ์ํฐํฉํธ ์ ์ฅ์ - ์ํฐํฉํธ ์ ์ฅ์ ๋ด๋นํฉ๋๋ค(7๊ฐ์ง ์คํ ๋ฆฌ์ง ์ต์ ์ง์: Amazon S3, Azure Blob Storage, Google Cloud Storage, FTP ์๋ฒ, SFTP ์๋ฒ, NFS, HDFS).
๋ก ์ ๋ฌผ ๊ฐ๊ฒ ๋จ์ํ๋ฅผ ์ํด SFTP ์๋ฒ๋ฅผ ์ฌ์ฉํ๊ฒ ์ต๋๋ค.
- ๊ทธ๋ฃน ๋ง๋ค๊ธฐ
$ sudo groupadd sftpg
- ์ฌ์ฉ์๋ฅผ ์ถ๊ฐํ๊ณ ๊ทธ ์ฌ๋์ ๋น๋ฐ๋ฒํธ๋ฅผ ์ค์ ํ์ธ์
$ sudo useradd -g sftpg mlflowsftp $ sudo passwd mlflowsftp
- ๋ช ๊ฐ์ง ์ก์ธ์ค ์ค์ ์กฐ์
$ sudo mkdir -p /data/mlflowsftp/upload $ sudo chown -R root.sftpg /data/mlflowsftp $ sudo chown -R mlflowsftp.sftpg /data/mlflowsftp/upload
- /etc/ssh/sshd_config์ ๋ช ์ค ์ถ๊ฐ
Match Group sftpg ChrootDirectory /data/%u ForceCommand internal-sftp
- ์๋น์ค๋ฅผ ๋ค์ ์์ํ์ธ์
$ sudo systemctl restart sshd
๋ก ๋ฐฑ์๋ ์คํ ์ด postgresql์ ์ฌ์ฉํด๋ณด์.
$ sudo apt update
$ sudo apt-get install -y postgresql postgresql-contrib postgresql-server-dev-all
$ sudo apt install gcc
$ pip install psycopg2
$ sudo -u postgres -i
# Create new user: mlflow_user
[postgres@user_name~]$ createuser --interactive -P
Enter name of role to add: mlflow_user
Enter password for new role: mlflow
Enter it again: mlflow
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) n
Shall the new role be allowed to create more new roles? (y/n) n
# Create database mlflow_bd owned by mlflow_user
$ createdb -O mlflow_user mlflow_db
์๋ฒ๋ฅผ ์์ํ๋ ค๋ฉด ๋ค์ Python ํจํค์ง๋ฅผ ์ค์นํด์ผ ํฉ๋๋ค(๋ณ๋์ ๊ฐ์ ํ๊ฒฝ์ ๋ง๋๋ ๊ฒ์ด ์ข์ต๋๋ค).
pip install mlflow
pip install pysftp
์๋ฒ๋ฅผ ์์ํด๋ณด์
$ mlflow server
--backend-store-uri postgresql://mlflow_user:mlflow@localhost/mlflow_db
--default-artifact-root sftp://mlflowsftp:mlflow@sftp_host/upload
--host server_host
--port server_port
2. ์ถ์ ์ถ๊ฐ
ํ๋ จ ๊ฒฐ๊ณผ๊ฐ ์์ค๋์ง ์๋๋ก, ๋ฏธ๋ ์ธ๋์ ๊ฐ๋ฐ์๋ค์ด ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ์ดํดํ๊ณ , ๋์ด๋ ๋์ง๋ค๊ณผ ์ฌ๋ฌ๋ถ์ด ํ์ต ๊ณผ์ ์ ์นจ์ฐฉํ๊ฒ ๋ถ์ํ ์ ์๋๋ก ์ถ์ ์ ์ถ๊ฐํด์ผ ํฉ๋๋ค. ์ถ์ ์ด๋ ๋งค๊ฐ๋ณ์, ์งํ, ์ํฐํฉํธ ๋ฐ ๊ต์ก ์์์ ๋ํ ์ถ๊ฐ ์ ๋ณด๋ฅผ ์๋ฒ์ ์ ์ฅํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
์๋ฅผ ๋ค์ด, ์ ๋ ์์
๊ฐ์ฅ ํฅ๋ฏธ๋ก์ด ์ผ์ด ์ผ์ด๋๋ ๋ถ๋ถ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
def run(self, epochs, lr, experiment_name):
# getting the id of the experiment, creating an experiment in its absence
remote_experiment_id = self.remote_server.get_experiment_id(name=experiment_name)
# creating a "run" and getting its id
remote_run_id = self.remote_server.get_run_id(remote_experiment_id)
# indicate that we want to save the results on a remote server
mlflow.set_tracking_uri(self.tracking_uri)
mlflow.set_experiment(experiment_name)
with mlflow.start_run(run_id=remote_run_id, nested=False):
mlflow.keras.autolog()
self.train_pipeline.train(lr=lr, epochs=epochs)
try:
self.log_tags_and_params(remote_run_id)
except mlflow.exceptions.RestException as e:
print(e)
์ฌ๊ธฐ์ self.remote_server๋ mlflow.tracking ๋ฉ์๋์ ๋ํ ์์ ๋ํผ์ ๋๋ค. MlflowClient(ํธ์๋ฅผ ์ํด ๋ง๋ค์์ต๋๋ค)๋ฅผ ์ฌ์ฉํ์ฌ ์คํ์ ๋ง๋ค๊ณ ์๋ฒ์์ ์คํํฉ๋๋ค. ๋ค์์ผ๋ก, ์คํ ๊ฒฐ๊ณผ๋ฅผ ๋ณํฉํด์ผ ํ๋ ์์น(mlflow.set_tracking_uri(self.tracking_uri))๋ฅผ ์ง์ ํฉ๋๋ค. ์๋ ๋ก๊น mlflow.keras.autolog()๋ฅผ ํ์ฑํํฉ๋๋ค. ํ์ฌ MLflow Tracking์ TensorFlow, Keras, Gluon XGBoost, LightGBM, Spark์ ๋ํ ์๋ ๋ก๊น ์ ์ง์ํฉ๋๋ค. ํ๋ ์์ํฌ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐพ์ง ๋ชปํ ๊ฒฝ์ฐ ์ธ์ ๋ ์ง ๋ช ์์ ์ผ๋ก ๋ก๊น ํ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ํ๋ จ์ ์์ํฉ๋๋ค. ์๊ฒฉ ์๋ฒ์ ํ๊ทธ์ ์ ๋ ฅ ๋งค๊ฐ๋ณ์๋ฅผ ๋ฑ๋กํฉ๋๋ค.
๋ช ์ค๋ง ์์ผ๋ฉด ๋ค๋ฅธ ๋ชจ๋ ์ฌ๋๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ชจ๋ ์ถ์์ ๋ํ ์ ๋ณด์ ์ก์ธ์คํ ์ ์์ต๋๋ค. ์์ํ?
3. ํ๋ก์ ํธ๋ฅผ ์์ฑํฉ๋๋ค
์ด์ ํ๋ก์ ํธ๋ฅผ ์ฝ๊ฒ ์์ํ๋๋ก ํ๊ฒ ์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ ค๋ฉด MLproject ๋ฐ conda.yaml ํ์ผ์ ํ๋ก์ ํธ ๋ฃจํธ์ ์ถ๊ฐํฉ๋๋ค.
MLํ๋ก์ ํธ
name: flow_segmentation
conda_env: conda.yaml
entry_points:
main:
parameters:
categories: {help: 'list of categories from coco dataset'}
epochs: {type: int, help: 'number of epochs in training'}
lr: {type: float, default: 0.001, help: 'learning rate'}
batch_size: {type: int, default: 8}
model_name: {type: str, default: 'Unet', help: 'Unet, PSPNet, Linknet, FPN'}
backbone_name: {type: str, default: 'resnet18', help: 'exampe resnet18, resnet50, mobilenetv2 ...'}
tracking_uri: {type: str, help: 'the server address'}
experiment_name: {type: str, default: 'My_experiment', help: 'remote and local experiment name'}
command: "python mlflow_training.py
--epochs={epochs}
--categories={categories}
--lr={lr}
--tracking_uri={tracking_uri}
--model_name={model_name}
--backbone_name={backbone_name}
--batch_size={batch_size}
--experiment_name={experiment_name}"
MLflow ํ๋ก์ ํธ์๋ ๋ค์๊ณผ ๊ฐ์ ๋ช ๊ฐ์ง ์์ฑ์ด ์์ต๋๋ค.
- ์ด๋ฆ - ํ๋ก์ ํธ ์ด๋ฆ
- ํ๊ฒฝ - ๋ด ๊ฒฝ์ฐ conda_env๋ Anaconda๋ฅผ ์ฌ์ฉํ์ฌ ์คํํ๊ณ ์ข ์์ฑ ์ค๋ช ์ด conda.yaml ํ์ผ์ ์์์ ๋ํ๋ ๋๋ค.
- ์ง์ ์ - ์คํํ ์ ์๋ ํ์ผ๊ณผ ๋งค๊ฐ๋ณ์๋ฅผ ๋ํ๋ ๋๋ค(ํ๋ จ์ ์์ํ ๋ ๋ชจ๋ ๋งค๊ฐ๋ณ์๊ฐ ์๋์ผ๋ก ๊ธฐ๋ก๋ฉ๋๋ค).
conda.yaml
name: flow_segmentation
channels:
- defaults
- anaconda
dependencies:
- python==3.7
- pip:
- mlflow==1.8.0
- pysftp==0.2.9
- Cython==0.29.19
- numpy==1.18.4
- pycocotools==2.0.0
- requests==2.23.0
- matplotlib==3.2.1
- segmentation-models==1.0.1
- Keras==2.3.1
- imgaug==0.4.0
- tqdm==4.46.0
- tensorflow-gpu==1.14.0
Docker๋ฅผ ๋ฐํ์ ํ๊ฒฝ์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. ์์ธํ ๋ด์ฉ์ ๋ค์์ ์ฐธ์กฐํ์ธ์.
4. ํ๋ จ์ ์์ํ์
ํ๋ก์ ํธ๋ฅผ ๋ณต์ ํ๊ณ ํ๋ก์ ํธ ๋๋ ํฐ๋ฆฌ๋ก ์ด๋ํฉ๋๋ค.
git clone https://github.com/simbakot/mlflow_example.git
cd mlflow_example/
์คํํ๋ ค๋ฉด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํด์ผ ํฉ๋๋ค.
pip install mlflow
pip install pysftp
์๋ํ๋ฉด conda_env๋ฅผ ์ฌ์ฉํ๋ ์์์๋ Anaconda๊ฐ ์ปดํจํฐ์ ์ค์น๋์ด ์์ด์ผ ํฉ๋๋ค(๊ทธ๋ฌ๋ ํ์ํ ๋ชจ๋ ํจํค์ง๋ฅผ ์ง์ ์ค์นํ๊ณ ์์ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๋ค).
๋ชจ๋ ์ค๋น ๋จ๊ณ๊ฐ ์๋ฃ๋์์ผ๋ฉฐ ๊ต์ก์ ์์ํ ์ ์์ต๋๋ค. ํ๋ก์ ํธ ๋ฃจํธ์์:
$ mlflow run -P epochs=10 -P categories=cat,dog -P tracking_uri=http://server_host:server_port .
๋ช
๋ น์ด๋ฅผ ์
๋ ฅํ๋ฉด ์๋์ผ๋ก conda ํ๊ฒฝ์ด ์์ฑ๋๊ณ ํ๋ จ์ด ์์๋ฉ๋๋ค.
์์ ์์์๋ ํ๋ จ์ ์ํ ์๋ ์, ์ฆ ๋ถ๋ฅํ๋ ค๋ ๋ฒ์ฃผ๋ฅผ ์ ๋ฌํ์ต๋๋ค(์ ์ฒด ๋ชฉ๋ก์ ๋ณผ ์ ์์ต๋๋ค).
๊ฐ๋ฅํ ๋งค๊ฐ๋ณ์์ ์ ์ฒด ๋ชฉ๋ก์ MLproject ํ์ผ์์ ์ฐพ์ ์ ์์ต๋๋ค.
5. ํ์ต ๊ฒฐ๊ณผ ํ๊ฐ
๊ต์ก์ ๋ง์น ํ ๋ธ๋ผ์ฐ์ ์์ ์๋ฒ ์ฃผ์๋ก ์ด๋ํ ์ ์์ต๋๋ค.
์ฌ๊ธฐ์๋ ๋ชจ๋ ์คํ ๋ชฉ๋ก(์ผ์ชฝ ์๋จ)๊ณผ ์คํ ์ ๋ณด(๊ฐ์ด๋ฐ)๊ฐ ํ์๋ฉ๋๋ค. ๊ฐ ์ถ์์ ๋ํ ๋ ์์ธํ ์ ๋ณด(๋งค๊ฐ๋ณ์, ์งํ, ์ํฐํฉํธ ๋ฐ ์ผ๋ถ ์ถ๊ฐ ์ ๋ณด)๋ฅผ ๋ณผ ์ ์์ต๋๋ค.
๊ฐ ์งํ์ ๋ํด ๋ณ๊ฒฝ ๋ด์ญ์ ๊ด์ฐฐํ ์ ์์ต๋๋ค.
์ ๊ฒ๋ค. ํ์ฌ๋ "์๋" ๋ชจ๋์์ ๊ฒฐ๊ณผ๋ฅผ ๋ถ์ํ ์ ์์ผ๋ฉฐ MLflow API๋ฅผ ์ฌ์ฉํ์ฌ ์๋ ๊ฒ์ฆ์ ์ค์ ํ ์๋ ์์ต๋๋ค.
6. ๋ชจ๋ธ ๋ฑ๋ก
๋ชจ๋ธ์ ๋ถ์ํ๊ณ ์ ํฌ ์ค๋น๊ฐ ์๋ฃ๋์๋ค๊ณ ํ๋จํ ํ ๋ฑ๋ก์ ์งํํฉ๋๋ค. ์ด๋ฅผ ์ํด ํ์ํ ๋ฐ์ฌ๋ฅผ ์ ํํ๊ณ (์ด์ ๋จ๋ฝ์ ํ์๋จ) ๋ด๋ ค๊ฐ๋๋ค.
๋ชจ๋ธ์ ์ด๋ฆ์ ์ง์ ํ๋ฉด ๋ฒ์ ์ด ์์ต๋๋ค. ๋ค๋ฅธ ๋ชจ๋ธ์ ๊ฐ์ ์ด๋ฆ์ผ๋ก ์ ์ฅํ๋ฉด ๋ฒ์ ์ด ์๋์ผ๋ก ์ ๊ทธ๋ ์ด๋๋ฉ๋๋ค.
๊ฐ ๋ชจ๋ธ์ ๋ํด ์ค๋ช ์ ์ถ๊ฐํ๊ณ ์ธ ๊ฐ์ง ์ํ(์คํ ์ด์ง, ํ๋ก๋์ , ๋ณด๊ด๋จ) ์ค ํ๋๋ฅผ ์ ํํ ์ ์์ผ๋ฉฐ, ์ดํ์ API๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฌํ ์ํ์ ์ก์ธ์คํ ์ ์์ผ๋ฉฐ ๋ฒ์ ๊ด๋ฆฌ์ ํจ๊ป ์ถ๊ฐ์ ์ธ ์ ์ฐ์ฑ์ ์ ๊ณตํฉ๋๋ค.
์ฐ๋ฆฌ๋ ๋ํ ๋ชจ๋ ๋ชจ๋ธ์ ์ฝ๊ฒ ์ ๊ทผํ ์ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๊ทธ๋ค์ ๋ฒ์
์ด์ ๋จ๋ฝ์์์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ชจ๋ ์์ ์ API๋ฅผ ์ฌ์ฉํ์ฌ ์ํํ ์ ์์ต๋๋ค.
7. ๋ชจ๋ธ ๋ฐฐํฌ
์ด ๋จ๊ณ์์๋ ์ด๋ฏธ ํ๋ จ๋(keras) ๋ชจ๋ธ์ด ์์ต๋๋ค. ์ฌ์ฉ ๋ฐฉ๋ฒ์ ์:
class SegmentationModel:
def __init__(self, tracking_uri, model_name):
self.registry = RemoteRegistry(tracking_uri=tracking_uri)
self.model_name = model_name
self.model = self.build_model(model_name)
def get_latest_model(self, model_name):
registered_models = self.registry.get_registered_model(model_name)
last_model = self.registry.get_last_model(registered_models)
local_path = self.registry.download_artifact(last_model.run_id, 'model', './')
return local_path
def build_model(self, model_name):
local_path = self.get_latest_model(model_name)
return mlflow.keras.load_model(local_path)
def predict(self, image):
image = self.preprocess(image)
result = self.model.predict(image)
return self.postprocess(result)
def preprocess(self, image):
image = cv2.resize(image, (256, 256))
image = image / 255.
image = np.expand_dims(image, 0)
return image
def postprocess(self, result):
return result
์ฌ๊ธฐ์ self.registry๋ ํธ์์ mlflow.tracking.MlflowClient์ ๋ํ ์์ ๋ํผ์ ๋๋ค. ์์ ์ ์๊ฒฉ ์๋ฒ์ ์ก์ธ์คํ์ฌ ๊ทธ๊ณณ์์ ์ง์ ๋ ์ด๋ฆ๊ณผ ์ต์ ์์ฐ ๋ฒ์ ์ ๊ฐ์ง ๋ชจ๋ธ์ ์ฐพ๋ ๊ฒ์ ๋๋ค. ๋ค์์ผ๋ก ์ํฐํฉํธ๋ฅผ ./model ํด๋์ ๋ก์ปฌ๋ก ๋ค์ด๋ก๋ํ๊ณ ์ด ๋๋ ํฐ๋ฆฌ mlflow.keras.load_model(local_path)์์ ๋ชจ๋ธ์ ๋น๋ํฉ๋๋ค. ์ด์ ๋ชจ๋ธ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. CV(ML) ๊ฐ๋ฐ์๋ ์ฝ๊ฒ ๋ชจ๋ธ์ ๊ฐ์ ํ๊ณ ์ ๋ฒ์ ์ ๊ฒ์ํ ์ ์์ต๋๋ค.
๊ฒฐ๋ก ์ ์ผ๋ก
๋๋ ๋ค์์ ํ์ฉํ๋ ์์คํ ์ ์ ์ํ์ต๋๋ค.
- ML ๋ชจ๋ธ, ํ์ต ์งํ ์ํฉ ๋ฐ ๊ฒฐ๊ณผ์ ๋ํ ์ ๋ณด๋ฅผ ์ค์์ ์ ์ฅํฉ๋๋ค.
- ๊ฐ๋ฐ ํ๊ฒฝ์ ์ ์ํ๊ฒ ๋ฐฐํฌํฉ๋๋ค.
- ๋ชจ๋ธ ์์ ์งํ ์ํฉ์ ๋ชจ๋ํฐ๋งํ๊ณ ๋ถ์ํฉ๋๋ค.
- ๋ชจ๋ธ์ ์ํ๋ฅผ ๋ฒ์ ํํ๊ณ ๊ด๋ฆฌํ๋ ๊ฒ์ด ํธ๋ฆฌํฉ๋๋ค.
- ๊ฒฐ๊ณผ ๋ชจ๋ธ์ ๋ฐฐํฌํ๋ ๊ฒ์ ์ฝ์ต๋๋ค.
์ด ์๋ ์ฅ๋๊ฐ์ด๋ฉฐ ๊ฒฐ๊ณผ ํ๊ฐ ๋ฐ ๋ชจ๋ธ ๋ฑ๋ก ์๋ํ(๊ฐ๊ฐ 5๋ฒ ๋ฐ 6๋ฒ)๋ฅผ ํฌํจํ ์ ์๋ ์์ฒด ์์คํ ์ ๊ตฌ์ถํ๊ธฐ ์ํ ์ถ๋ฐ์ ์ญํ ์ ํ๊ฑฐ๋ ๋ฐ์ดํฐ ์ธํธ์ ๋ฒ์ ๊ด๋ฆฌ๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ ๋ค๋ฅธ ๊ฒ์ ์ถ๊ฐํ ์๋ ์์ต๋๋ค. ์ ๊ฐ ๋งํ๋ ค๊ณ ํ๋ ์์ ์ ์ ์ฒด์ ์ผ๋ก MLOps๊ฐ ํ์ํ๋ค๋ ๊ฒ์ ๋๋ค. MLflow๋ ๋ชฉ์ ์ ์ํ ์๋จ์ผ ๋ฟ์ ๋๋ค.
๋ด๊ฐ ํ์ํ์ง ์์ ์ด๋ค ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋์ง ์ ์ด์ฃผ์ธ์.
๊ทํ์ ์๊ตฌ ์ฌํญ์ ์ถฉ์กฑ์ํค๊ธฐ ์ํด ์์คํ
์ ๋ฌด์์ ์ถ๊ฐํ์๊ฒ ์ต๋๊น?
๋ฌธ์ ์ ์ ๋ถ ๋๋ ์ผ๋ถ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ด๋ค ๋๊ตฌ์ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํฉ๋๊น?
์ถ์ : ๋ช ๊ฐ์ง ๋งํฌ๋ฅผ ๋จ๊ฒจ ๋๊ฒ ์ต๋๋ค.
github ํ๋ก์ ํธ -
MLํ๋ก์ฐ -
์ง๋ฌธ์ ๋ํ ๋ด ์
๋ฌด ์ด๋ฉ์ผ - [์ด๋ฉ์ผ ๋ณดํธ]
์ฐ๋ฆฌ ํ์ฌ๋ ์ ๊ธฐ์ ์ผ๋ก IT ์ ๋ฌธ๊ฐ๋ฅผ ์ํ ๋ค์ํ ์ด๋ฒคํธ๋ฅผ ๊ฐ์ตํฉ๋๋ค. ์๋ฅผ ๋ค์ด ๋ชจ์คํฌ๋ฐ ์๊ฐ์ผ๋ก 8์ 19์ผ 00:XNUMX์ ์จ๋ผ์ธ ํ์์ผ๋ก CV ๋ชจ์์ด ์์ ์์ ์
๋๋ค. ๊ด์ฌ์ด ์๋ ๊ฒฝ์ฐ ์ฐธ๊ฐํ๊ณ ๋ฑ๋กํ ์ ์์ต๋๋ค.
์ถ์ฒ : habr.com