Diversity is All You Need : Learning Skills without a Reward Function
(https://arxiv.org/abs/1802.06070)
์ ๋
ผ๋ฌธ์์ ๋ฐ๋ผ๋ณด๊ณ ์ ํ๋ ์ ์ ๋๋ํ ์ฌ๋๋ค์ ์ง์์์ ์ง์๊ฐ ์์ด๋ ์ค์ค๋ก ๋ค์ํ ์๋๋ค์ ํตํ์ฌ ์ค์ค๋ก ์ ์ฉํ ๊ธฐ์ ๋ค์ ํ์ตํ๋ค๋ ์ผ์์ ์ผ๋ค์ ๊ฐํํ์ต์ ์ ์ฉํด ๋ณด์๋ ์๋๋ฅผ ๊ฐ์ง๊ณ ์์ฑ๋์๋ค.
์ด๋ฅผ ๊ฐํํ์ต์ผ๋ก ํ์ด๋ณด์๋ฉด ์ด๋ป๊ฒ ํ๋ฉด ๋ณด์์ด ์์ด๋ ์ ์ฉํ ๊ธฐ์ ๋ค์ ์ค์ค๋ก ๋ฐฐ์์ ํ์ตํ ์ ์์๊น ์ด๋ฅผ ๊ตฌํํ๊ธฐ ์ํด์ ํ์ํ ๊ฑด ๋ฌด์์ผ๊น? ์ด๋ค.
reward function์ด ์์ด useful skills๋ฅผ ํ์ตํ๋ค. ์ด๋ฅผ ๊ธฐ์ ์ ์ผ๋ก ํ์ด๋ณด์๋ฉด maximum entropy policy๋ฅผ ์ด์ฉํ์ฌ information theoretic objective๋ฅผ ์ต๋ํํ๋ ๋ฐฉ๋ฒ์ ํตํด skills๋ฅผ ํ์ตํ๋ ๋ฐฉ๋ฒ๋ก ์ด๋ผ๊ณ ๋ณด๋ฉด ๋๋ค.
์ฌ๊ธฐ์ ์ค์ํ ํค์๋๋ maximum entropy policy์ด๋ค.
๋ฅ๋ฌ๋์์ ๊ฐ์ฅ ์ค์ํ ๊ฒ์ Data์ Optimization์ธ๋ฐ ์ต์ ํ์ maximum entropy policy๋ฅผ ์ ์ฉํ๋ค๋ ๊ฑด noise๋ฅผ ํตํ smooth ํจ๊ณผ์ ์ ์ฉ์ ํตํ์ฌ ๋จ๊ธฐ์ ๋ณด์๋ณด๋ค๋ ์ฅ๊ธฐ์ ์ธ ๋ณด์์ ๋ํ ๊ธฐ๋๊ฐ์ ๋์ด๊ธฐ ์ํจ์ด๋ค.
Entropy๋ฅผ ์ ๋ณด ์ด๋ก ์์๋ ์ด๋ฒคํธ์ ํฌํจ๋ ์์ ์ ๋ณด ๋นํธ ์๋ก ์ ์ํ ์ ์๊ณ ์ ๋
ผ๋ฌธ์์์ Maximum Entropy๋ผ๋ ๊ฒ์ ์์ด์ ํธ๊ฐ ๊ฐ์ฅ ๋์ ๋ณด์ ํฉ๊ณ์ ์ฅ๊ธฐ Entropy ํฉ๊ณ๋ฅผ ๋ฐ์ ์ ์๋ ๊ฐ์ฅ ์ฌ๋ฐ๋ฅธ ์์
์ ์ ํํ๊ธฐ ์ํด Policy ์ต์ ํ๋ฅผ ์ํํ๋ค๋๋ฐ ์๋ค๊ณ ๋ณด๋ฉด ๋๋ค.
์ด ์ต์ ํ ํจ์๋ฅผ ํตํด Agent๋ ๋ ๋ง์ ๊ฒ์ ํ์ํ๊ณ Local Optimization์ ํผํ ์ ์๋ค.
Maximum Entropy ์๋ฆฌ์ ๋ชฉํ๋ Maximum Entropy์ ๋ถํฌ๋ฅผ ์ฐพ๋ ๊ฒ์ด๋ค.
๋ง์ ๊ฐํํ์ต ์๊ณ ๋ฆฌ์ฆ์์ Agent๋ Local Optimization์ ์๋ ดํ ์ ๋ฐ์ ์๋ ๊ตฌ์กฐ์ ํ๊ณ๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
์ด๋ฅผ ๊ทน๋ณตํ๊ธฐ ์ํด ๋ชฉ์ ํจ์์ Maximum Entropy๋ฅผ ์ถ๊ฐํ์ฌ Agent๊ฐ Maximum Entropy๋ฅผ ๊ฐ๋ ๋ถํฌ๋ฅผ ๊ฒ์ํ ์ ์๋ค. ์ ์๋ ๋งํ๋ฐ์ ๊ฐ์ด Maximum Entropy์ ๋ชฉํ๋ ๊ฐ์ฅ ๋์ ๋์ ๋ณด์๊ณผ Maximum Entropy๋ฅผ ๋ฌ์ฑํ ์ ์๋ ์ต์ ์ ์ ์ฑ
์ ํ์ตํ๋ ๊ฒ์ด๋ค. ์ด ์ต์ ์ ์ ์ฑ
์ ๋ฐ๋ก ์ฅ๊ธฐ ๋ณด์ ๋ฐ ์ฅ๊ธฐ ์ํธ๋กํผ์ ๋ํ ๊ฐ์ฅ ๋์ ๊ธฐ๋์น์ด๋ค.
๋ณธ ๋ ผ๋ฌธ์์๋ pretrained skills๊ฐ ์ด๋ป๊ฒ downstream tasks์ ๋ํด ์ข์ parameter initialization์ ์ ๊ณตํ ์ ์๋์ง์, complexํ๊ณ sparse reward tasks๋ฅผ ํ๊ธฐ ์ํด ๊ณ์ธต์ ๊ตฌ์ฑ์ ํตํด ๋ฌธ์ ๋ฅผ ํ์ด๊ฐ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ฃผ๊ณ ์๋ค.
Downstream task๋ pretrained model ํน์ feature๋ฅผ supervised-learning task์ ์ ์ฉ์ํค๋ ๊ฒ์ด๋ค.
Transfer learning์์ ๋๊ท๋ชจ ๋ฐ์ดํฐ ์
์ผ๋ก ๋ชจ๋ธ์ ํ์ตํ ํ, ํด๋น ๋ชจ๋ธ์ ๋ํ neural network architecture๋ฅผ ์ผ๋ถ ๋ณํํ์ฌ ๋ท๋จ์ ๋ถ๋ถ๋ง ์ผ๋ถ ํ์ต์ ํตํ์ฌ ๋ค์ํ ์๋น์ค๋ฅผ ์ํํ ์ ์๋๋ก ํ๋ ๊ฒ์ downstream task๋ผ๊ณ ํ๋ค. ์ด๋ ๋ณต์กํ ๊ฒ์ ๊ฐ์ ๊ฒฝ์ฐ ์ ๋ต์ ํ์ต์ํค๊ธฐ ์ํด ์ฌ๋์ด ์ง์ reward๋ฅผ ์ค๊ณํ๋ ๊ฒ์ด ์ด๋ ต๋ค.
reward engineering๋จ๊ณ์์ ์ฐ๊ตฌ์์ ์๋๊ฐ ๋ค์ด๊ฐ๋๋ผ๋ ๊ทธ ์๋๋ฅผ ํ์ต์ ์ ๋๋ก ๋ฐ์ํ๋ ๊ฒ์ด ๊น๋ค๋กญ๊ณ , ์ฌ๋์ ๊ฐ์
์์ด agent๋ผ๋ฆฌ ํ์ต์ ํ๋ ๊ณผ์ ์์ agent๊ฐ ์ฐฝ์์ ์ธ ์ ๋ต์ ์ฐพ์๋ด๋ ๊ฒฝ์ฐ๋ ์๊ธฐ ๋๋ฌธ์ ๋์ ํ ๊ฒ์์ ์ฃผ๋ก ๊ฒ์์ด ๋๋ ๋ค ์นํจ์ ๋ฐ๋ผ reward๋ฅผ ์ ๊ณตํ๋ค.
Agent์ ํ์ต episode์์ ๋จ ํ๋ฒ์ reward๋ง์ด ์ฃผ์ด์ง๊ธฐ ๋๋ฌธ์ ์์ ๊ฐ์ ๊ฒฝ์ฐ์์๋ sparse reward problem์ด ์กด์ฌํ๋ค. ์ด ๋
ผ๋ฌธ์์๋ ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ๋ฐฉ๋ฒ๋ก ์ผ๋ก ๊ณ์ธต์ ๊ตฌ์ฑ์ ํตํด ๋ฌธ์ ๋ฅผ ํ์ด๊ฐ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ฃผ๋ ค ํ๋ค.
Introduction
๊ฐํํ์ต์ playing games, controlling robots, navigating complex environment๋ฅผ ํฌํจ, ๋ค์ํ reward driven skills๋ฅผ ํจ์จ์ ์ผ๋ก ํ์ตํ๋ ๋ฐฉ๋ฒ๋ก ์ด๋ค. ํ์ง๋ง intelligent creatures๋ supervision์์ด๋ useful skills๋ฅผ ์ ํ์ตํ๊ณ ํ๊ฒฝ์ exploreํ ์ ์๋ค.
๋ฐ๋ผ์ intelligent creature๋ ์ดํ์ ๋ค๋ฅธ goal์ด ์๊ฒผ์ ๋, skills๋ฅผ ํ์ฉํ์ฌ ๋น ๋ฅด๊ณ ํจ์จ์ ์ผ๋ก ํ์ตํ ์ ์๋ค.
reward์์ด skills๋ฅผ ํ์ตํ๋ practical applications๊ฐ ์๋ค.
์ด๋ sparse rewards๊ฐ ์กด์ฌํ๋ ํ๊ฒฝ์์ agent๊ฐ goal state์ ๋ฌด์์๋ก ๋๋ฌํ ๋๊น์ง์ ๋ณด์์ด ์๋ค.
supervision์์ด useful skills๋ฅผ ํ์ตํ๋ ๊ฒฝ์ฐ exploration์ ์ด๋ ค์์ ํด๊ฒฐํ๋๋ฐ์ ๋์์ ์ฃผ๋๋ฐ ์ด๋ฐ ๋ด์ญ์ ๋ํ์ฌ ๋ณด์์ ์ค๊ณํ๋ ๊ฒ์ ๋งค์ฐ ์ด๋ ต๊ณ ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก agent๋ก ๋ถํฐ ์ํ๋ ํ๋์ ์ ๋ํ๋ reward function์ ์ค๊ณํ๋ ๊ฒ์ ๋์ฑ ์ด๋ ต๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ต์ํ์ง ์์ ํ๊ฒฝ์ด ์ฃผ์ด์ก์ ๋, agent๊ฐ ์ด๋ค tasks๋ฅผ ํ์ตํ ์ ์๋์ง ๊ฒฐ์ ํ๋ ๊ฒ์ด challenging์ด๋ค. ๊ทธ๋ฆฌ๊ณ ๋ณด์์์ด useful skills๋ฅผ ํ์ตํ๋ ๊ฒ ๋ํ ๋งค์ฐ ์ด๋ ค์ด ๋ฌธ์ ์ด๋ค.
๊ฒฐ๋ก ์ ์ผ๋ก ๋งํ์๋ฉด ๋ณด์์ ๋์์ธํ๋ ๊ฒ์ ๋งค์ฐ ์ด๋ ต์ง๋ง ๋ณด์์์ด ํ์ตํ๋ ๊ฒ ๋ํ ๋งค์ฐ ์ด๋ ค์ด ๋ฌธ์ ์ด๋ค.
์์์ ๊ณ์ ์ธ๊ธํ๋ Skill์ด๋ ํ๊ฒฝ์ state๋ฅผ consistent way(์ผ๊ด๋ ๋ฐฉ์)๋ก ๋ณํ์ํค๋ latent conditioned policy์ด๋ค. reward function์ ๋ชจ๋ฅผ ๋๋ ‘set’์ utility๋ฅผ ์ต๋ํํ์ฌ skills์ set์ ํ์ตํ๊ณ ์ถ๋ค.
์ํธ ์ ๋ณด(mutual information)์ ๊ธฐ๋ฐํ ๊ฐ๋จํ ๋ชฉํ๋ฅผ ํตํด ๊ฐํํ์ต agent๊ฐ ์ด๋ฐ skills๋ฅผ ์์จ์ ์ผ๋ก ๋ฐ๊ฒฌํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ณผ ์ ์๋ค๊ณ ํ๋ค. ์ด๋ฐ skills๋ hierarchical reinforcement learning์ด๋ imitation learning๋ฑ์ ํ์ฉ๋๊ณ ์๋ค.
๋ณธ ๋
ผ๋ฌธ์์๋ useful skills๋ฅผ ์ป๊ธฐ ์ํด, ๊ฐ๋ฅํ ํ๋์ set๋ค์ ์ต๋ํ ์ปค๋ฒํ ์ ์๋๋ก skills๋ฅผ ํ๋ จํด์ผ ํ๋ค๊ณ ๊ฐ์ ํ๋ค. ํ๋ จ๋ฐฉ๋ฒ์ผ๋ก๋ objective๋ก์์ skills ์ฌ์ด์ ์ฐจ๋ณ์ฑ(discriminability)์ ์ด์ฉํ๋ ๊ฒ์ด๋ค.
๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์๋ discriminabilityํ๋ฉด์ ๋ค์ํ skills๋ฅผ ํ์ตํด์ผ ํ๋ค.
๋ณธ ๋ ผ๋ฌธ์์๋ ์ด 5๊ฐ์ง์ contribution์ด ์๋ค.
1> Maximum entropy policy๋ก ์ ๋ณด์ด๋ก ์ ๋ชฉํ๋ฅผ ๊ทน๋ํํ๋ ๊ฒ์ผ๋ก ์ฐจ๋ณ๋ goal์ ๊ณต์ํํ๋ค. ์ฆ ์ฌ๋ฌ ๊ฐํํ์ต ์ฐ๊ตฌ์์ bench mark๋ก ์ฌ์ฉํ๋ ํ๊ฒฝ๋ค์์๋ true reward๋ฅผ ๋ฐ์ง ์๊ณ ์ ํ์ตํ๋ ๊ฒ์ ๋ณด์ฌ์ค๋ค.
2> ์ด๋ ํ ๋ณด์์์ด useful skills๋ฅผ ํ์ตํ๋ ๋ฐฉ๋ฒ
๋ฌ๋ฆฌ๊ธฐ, ์ ํ๊ณผ ๊ฐ์ ๋ค์ํ skills์ unsupervised emergence(๋น์ง๋ ์ถํ)์์ ๊ฐ๋จํ ํํ ๋ชฉํ์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค๋ค.
3> Hierarchical RL์ ๋ํด ํ์ต๋ skills๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ ์ ์ํ๊ณ ์ด๋ฐ ๋ฐฉ๋ฒ๋ค์ด challenging tasks๋ฅผ ํด๊ฒฐํจ์ ๋ณด์ด๊ณ ์๋ค.
๊ฐ state๋ง๋ค ์ ์ ํ action์ ์ทจํ ๊ฒ์ด๋ค. ์ฆ ์ฌ๋์ ์ก์
์ ์ ํจ์ ์์ด์ hierarchy๊ฐ ์์ด์ ๋จผ์ ์์ ์ก์
์ ๊ฒฐ์ ํ๊ณ ์์ ์ก์
์ ์ทจํ๊ธฐ ์ํด ํ์ ์ก์
๋ค์ ๊ฒฐ์ ํ๊ฒ ๋๋ค. ์ด๊ฒ์ด ๋ฐ๋ก Hierarchical RL(HRL)์ด๋ค.
4> Skills๊ฐ ์ผ๋ง๋ ๋นจ๋ฆฌ ์๋ก์ด task์ ์ ์ ์ํ๋์ง๋ฅผ ๋ณด์ฌ์ค๋ค.
5> ๋ฐ๊ฒฌ๋ skills๊ฐ imitation learning์ ์ด๋ป๊ฒ ์ฌ์ฉ๋ ์ ์๋์ง๋ฅผ ๋ณด์ฌ์ค๋ค.
imitation learning์ ์ฌ์ฉํ๋ ์ด์ ๋ ์ผ๋ฐ์ ์ธ MDP์์๋, ์ข์ policy๋ฅผ ์ฐพ๊ธฐ ์ํด์๋ ๊ต์ฅํ ๋ง์ ์์ sample๋ค์ด ํ์ํ๋ค. ์๋ฅผ ๋ค์๋ฉด, DQN๊ฐ์ ๊ฒฝ์ฐ ์ต๋ํ ๋ง์ ์์ sample์ ๊ฐ์ง๊ณ ์ค๋ training์ ํด์ผ๋ง ์ข์ ์ฑ๋ฅ์ ๋ผ ์ ์์๋ค. ํ์ง๋ง, ํ์ค ์์์๋ ์ค์ ๊ฐํ ํ์ต์ ์ํํ ๋งํ ๋ง์ ์์ sample๋ค์ ์ป๊ธฐ๋ ์ฝ์ง ์๋ค.
๋ง์ฝ ์ฐ๋ฆฌ๊ฐ ์ฐ์ฃผ์ ์ ๋ฐ์ฌํ๋ ๊ฐํํ์ต agent๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค๊ณ ๊ฐ์ ํด ๋ณด์. ์์์ด ๋ง์ ์ฐ์ฃผ์ ๋ฐ์ฌ๋ฅผ ์คํจํด์ผ๋ง ์ง์ง ์ ๋๋ก ๋ ์ฐ์ฃผ์ ๋ฐ์ฌ๋ฅผ ๋ณผ ์ ์์ ๊ฒ์ด๋ค. ์ด๋ ๊ฒ ๋๋ฉด ์ฒ๋ฌธํ์ ์ธ ๋น์ฉ์ด ์์๋ ๊ฒ์ด๊ณ , ์ฌ์ค์ ์ด๋ฐ ๋ฐฉ์์ RL๋ก๋ ์ฐ์ฃผ์ ๋ฐ์ฌ๋ ๋ถ๊ฐ๋ฅ ํ๋ค๋ ๊ฒ์ ์ ์ ์๋ค. ์์จ์ฃผํ ์๋์ฐจ์ ๊ฒฝ์ฐ๋ ๋ง์ฐฌ๊ฐ์ง๋ค. ์ค์ค๋ก ์ด์ ํ๋ ์๋์ฐจ๋ฅผ ๋ง๋ค์ด์ผ ํ๋๋ฐ, ์์์ด ๋ง์ ์ฌ๊ณ ์ดํ์์ผ ์ด์ ์ ์ ๋๋ก ํ ์ ์๋ค๋ฉด, ์๋ฌด๋ ๊ทธ ๋น์ฉ์ ๊ฐ์ํ๋ ค ํ์ง ์์ ๊ฒ์ด๋ค.
๊ทธ๋ ๋ค๋ฉด sample์ ๊ฐฏ์๋ฅผ ์ค ์ผ ์ ์์ง ์์๊น? ๊ทธ๋ฅ ์๋ฌด๊ฒ๋ ์๋ ค์ฃผ์ง ์์ ์ํ๋ก Optimal Policy๋ฅผ ์ป๊ธฐ๋ฅผ ๊ธฐ๋ํ๊ธฐ ๋ณด๋ค๋, ์ด ๊ฐํ ํ์ต ๊ณผ์ ์ ๋์์ค ์ถ๊ฐ์ ์ธ ์ ๋ณด๋ ๊ตฌ์กฐ๋ค์ ์๋ ค์ค ๋ค์ ํ๋ จ์ ํ๋ฉด ๋์ง ์์๊น ๋ฐ๋ก ์ด๋ฐ ๊ฐ์ ์์ ์ถ๋ฐํ ๊ฒ์ด imitation learning์ด๋ค.
์ง๊ธ๊น์ง์ ๊ฐํํ์ต์ Reward๋ฅผ ํตํด Agent๋ฅผ ํ์ตํ์๋ค. DQN, Q-learning, Monte Carlo ๋ฑ๋ฑ ๋ชจ๋ ๋ค reward function์ ์ฌ์ฉํ์ฌ ์ต๋์ reward๋ฅผ ์ป์ ์ ์๋๋ก ํ๋ ๊ฒ์ด ์ฃผ์ ํฌ์ธํธ์๋ค. ์ด ๋ฐฉ์์ ๋งค์ฐ ๊ฐ๋จํ ๋ฐฉ์์ผ๋ก ํ๋ จ์ด ๊ฐ๋ฅํ๋ค๋ ์ ์์ ์ข์ง๋ง, ๋๋ฌด ๋ง์ sample์ ์๊ตฌํ๋ค๋ ๋จ์ ์ด ์๋ค.
์์จ ์ฃผํ ์๋์ฐจ์ reward๋ฅผ ์ฐ์ ํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผํ ๊น? ๋ง์ฝ ์ด reward๊ฐ์ ์ฌ๊ณ ๊ฐ ๋๋ฉด -10, ์ฌ๊ณ ๊ฐ ๋ฐ์ํ์ง ์์ผ๋ฉด +0.1 ์ด๋ฐ์์ผ๋ก ์ค๊ณํ๋ค๋ฉด ์ด๋จ๊น? ๊ทธ๋ ๊ฒ ๋๋ฉด ์ค๊ณ๊ฐ ๋ agent๊ฐ ์ด๋ป๊ฒ ํด์ผ ์ฌ๊ณ ๊ฐ ๋๊ณ ์ด๋ป๊ฒ ํด์ผ ์ฌ๊ณ ๊ฐ ๋์ง ์์์ง ์์๋ด๋ ๊ฒ์ ๋ง์ ๋น์ฉ์ด ๋ค์ด๊ฐ ๊ฒ์ด๋ค. ๊ทธ๋ ๋ค๋ฉด ๋ชจ๋ ์ํฉ์ ๋ํ์ฌ ์ ์ ํ reward๋ฅผ ๋์
ํด์ฃผ๋ฉด ์ด๋จ๊น? ์ฐ์ ์ด ๋ฐฉ์์ ๋๋ฌด ์ค๋ ์๊ฐ์ด ๊ฑธ๋ฆฌ๊ณ , ์ด๋ ๊ฒ reward๋ฅผ ์ ํด์ค๋ค๊ณ ํด๋ reward์ ์ํ๊ฐ ๋งค์ฐ ๋ถ์์ ํด์ง ์ ์๋ค. ์ด๋ฅผ ๋ณด์ํ๊ธฐ ์ํ ๋์์ฑ
์ผ๋ก, ๋ฐ๋ก reward๋ฅผ demonstration, ์ฆ ์ค์ ๋ก ์ด๋ป๊ฒ ํ๋์ง ๋ณด์ฌ์ฃผ๋ฉด์ reward๋ฅผ implicitํ๊ฒ ์ฃผ๋ ๊ฒ์ด๋ค. ์ด๋ ๊ฒ demonstration์ผ๋ก reward๋ฅผ ์ฐ์ ํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผํ ๊น? ๋ฐ๋ก ํ์ต์ํฌ ๋ถ์ผ์ ์ ๋ฌธ๊ฐ์ ํจ๊ป demonstration trajectory๋ฅผ ๋ง๋ค์ด ํ์ต์ํค๋ ๊ฒ์ด๋ค.
์์จ ์ฃผํ ์๋์ฐจ๋ฅผ ๋ง๋ ๋ค๊ณ ํ๋ฉด, ์ด์ ์ ๋งค์ฐ ์ํ๋ ์ฌ๋์ ๋ฐ๋ ค์์ ์ค์ ๋ก ํ๋ฒ ์ด์ ํ๋ ๋ชจ์ต์ ๋ณด๋ ๊ฒ์ด๋ค.
๊ทธ๋ ๊ฒ ์ป์ State/Action Sequence๋ค์ ๋ฐํ์ผ๋ก ๊ฐํ ํ์ต agent๋ฅผ ํ์ต์ํค๋ฉด ๋๋ค.
imitation learning๋ฐฉ์์ reward๋ฅผ ์ผ์ผํ ๋ถ์ฌํ๊ฑฐ๋ ํน์ policy๋ฅผ ๋ฐ๋ฅด๋๋ก ํ๊ฒ ํ๋ ค๋ ๊ฒ์ด ์๋ ๊ฒฝ์ฐ์ ํจ์จ์ ์ด๋ค.
์ด๋ฐ imitation learning์ ๊ธฐ๋ณธ์ ์ธ setting์ ์ฐ์ ์
๋ ฅ๊ฐ์ ์ง๊ธ๊น์ง์ ๋น์ทํ๊ฒ State์ Action space๋ก ์ด๋ค์ ธ ์๊ณ , Transition model P๊ฐ ์ฃผ์ด์ง๋ค. ๋ค๋ฅธ ์ ์, reward function R์ ์ฃผ์ด์ง์ง ์๋ ๋์ (s0, a0, s1, a1, …..)๊ณผ ๊ฐ์ demonstration์ด ์ฃผ์ด์ง๋ค.
Diversity is all you need
๋ณธ ๋
ผ๋ฌธ์ unsupervised RL ํจ๋ฌ๋ค์์ agent๊ฐ unsupervised “exploration” stage์ ์ด์ด์ supervised stage๋ ํ์ฉ๋ work์์ ๊ณ ๋ คํ๋ค. Unsupervised stage์ ๋ชฉ์ ์ ๊ถ๊ทน์ ์ผ๋ก supervised stage์ task reward๋ฅผ ์ฝ๊ฒ ์ต๋ํํ๋ skills๋ฅผ ํ์ตํ๋ ๊ฒ์ด๋ค.
ํธ๋ฆฌํ๊ฒ๋ ์ด๋ฌํ skills๋ tasks์ ๋ํ ์ฌ์ ์ง์์์ด skills๋ฅผ ํ์ตํ๊ธฐ ๋๋ฌธ์ ๋ง์ ๋ค๋ฅธ tasks์์ ์ฌ์ฉ๋ ์ ์๋ค.
How it works

unsupervised skill์ ๋ฐ๊ฒฌ์ ์ํ ๋ฐฉ๋ฒ์ ์ธ ๊ฐ์ง ์์ด๋์ด๋ก ๊ตฌ์ฑ๋๋ค.
1> Agent๊ฐ visitํ๋ state์ ์ํญ์ ์ฃผ๋ skill์ด ์์ด์ผ ํ๋ค. ( for skills to be useful )
๋ค๋ฅธ skills๋ ์๋ก ๋ค๋ฅธ states์ ๋ฐฉ๋ฌธํด์ผ๋ง ํ๋ฉฐ, ๊ทธ๋์ ๊ตฌ๋ถ๋ ์ ์๋ค.
2> Skills๋ฅผ ๊ตฌ๋ถํ๊ธฐ ์ํด action์ด ์๋ state๋ฅผ ์ด์ฉํ๋ค.
ํ๊ฒฝ์ ์ํฅ์ ์ฃผ์ง ์๋ actions์ outside observer์๊ฒ ๋ณด์ด์ง ์๊ธฐ ๋๋ฌธ์ด๋ค.
์๋ฅผ ๋ค์ด, outside observer๋ ์ปต์ด ์์ง์ด์ง ์์ผ๋ฉด ์ปต์ ์ก์ ๋ ๋ก๋ด ํ์ด ์ผ๋ง๋ ๋ง์ ํ์ ๊ฐํ๋์ง ์ ์ ์๋ค.
๋ง์ง๋ง์ผ๋ก, ๊ฐ๋ฅํ ํ ๋๋คํ๊ฒ ํ๋ํ๋ skills์ ํ์ตํ๋ ๊ฒ์ ํตํด skills์ด ๊ฐ๋ฅํ ๋ค์ํด์ง๋๋ก ํ๋ค.
3> ๊ตฌ๋ถ ๊ฐ๋ฅํ ๋์ entropy๋ฅผ ๊ฐ์ง skills๋ ๋ค๋ฅธ skills๋ก๋ถํฐ ๋ฉ๋ฆฌ ๋จ์ด์ง state space์ ์ผ๋ถ๋ฅผ ๊ผญ explorationํด์ action์ ๋๋ค์ฑ์ด ๊ตฌ๋ณํ ์ ์๋ state๋ก ์ด๋์ง ์๋๋ก ํ๋ค.
Objective๋ฅผ ์ํ notation์ ์ ๋ณด์ด๋ก ์ผ๋ก๋ถํฐ ๊ฐ์ ธ์ ์ฌ์ฉํ๋ค.
– ๊ณ ์ ๋ Z๋ฅผ ์กฐ๊ฑด์ผ๋ก ํ๋ policy๋ฅผ skill์ด๋ผ๊ณ ํ๋ค.
– I์ H๋ ์ํธ ์ ๋ณด(mutual information)์ Shannon entropy์ ๊ฐ๋
์์ ์ฐฉ์ํ์์ผ๋ฉฐ, ๋ ๋ค base e๋ก ๊ณ์ฐ๋๋ค.
– S์ A๋ ๊ฐ๊ฐ States, Actions์ ๋ํ ์์์ ๋ณ์์ด๋ค.
– Z ~ p(z)๋ latent ๋ณ์์ด๋ค.
– ๋ณธ ๋
ผ๋ฌธ์ objective๋, skill์ด agent๊ฐ visitํ๋ state๋ฅผ ์ ์ดํด์ผ๋ง ํ๋ ์์ด๋์ด๋ฅผ ์ธ์ฝ๋ฉํ๊ธฐ ์ํด skills์ states๊ฐ์ ์ํธ ์ ๋ณด( I(A;Z) )๋ฅผ ์ต๋ํํ๋ค.
– ํธ๋ฆฌํ๊ฒ๋, ์ด ์ํธ ์ ๋ณด๋ agent๊ฐ visitํ state์์ skill์ ์ถ๋ก ํ ์ ์์์ ๋ํ๋ธ๋ค.
– actions์ด ์๋ states๊ฐ skills๋ฅผ ๊ตฌ๋ถํ๋๋ฐ ์ฌ์ฉ๋๋๋ก ํ๊ธฐ ์ํด, ์ฃผ์ด์ง state์ skill๊ณผ action๊ฐ์ ์ํธ ์ ๋ณด( I(A;Z | S) )๋ฅผ ์ต์ํํ๋ค.
Policies์ mixture๋ก p(z)์ ํจ๊ป ๋ชจ๋ skills๋ฅผ ๋ณผ ๋ ์ด mixture policy์ ์ํธ๋กํผ H[A | S]๋ฅผ ์ต๋ํํ๋ค.
์์ฝํ์๋ฉด, ์๋์ g(theta)๋ฅผ ์ต๋ํํ๋ ๊ฒ์ด๋ค.

Implementation
๋ณธ ๋
ผ๋ฌธ์์๋ SAC(Soft Actor Critic)์ ์ด์ฉํ์๊ณ , latent ๋ณ์ z๋ฅผ ์กฐ๊ฑด์ผ๋ก ํ๋ ์ ์ฑ
์ ํ์ตํ๋ค.
SAC๋ actions์ ๋ํ policyโs entropy๋ฅผ ์ต๋ํํ์ฌ object g์์ ์ํธ๋กํผ ํ
์ ์ฒ๋ฆฌํ๋ค.
task reward๋ฅผ ๋์ฒดํ๋ ๋ฐฉ๋ฒ์ผ๋ก skill reward๋ก๋ g์ expectation์ ์ด์ฉํ๋ค.
– ์ ๊ทธ๋ฆผ์์ logq – logp์ ํด๋นํ๋ ๋ถ๋ถ
– p(z) ์ํด categorical distribution ์ด์ฉํ์๋ค.
Unsupervised learning๋์ ๊ฐ ์ํผ์๋์ ์์๋ถ๋ถ์์ skill z ~ p(z)๋ฅผ ์ํ๋งํ๊ณ ์ํผ์๋๋ด๋ด ํด๋น skill์ ๋ฐ๋ผ ํ๋ํ๋ค.
Agent๋ ๊ตฌ๋ถํ๊ธฐ ์ฌ์ด states๋ฅผ ๋ฐฉ๋ฌธํ๋ฉด ๋ณด์์ ๋ฐ๋ ๋ฐ๋ฉด์, discriminator๋ ๋ฐฉ๋ฌธํ states๋ก๋ถํฐ skill z๋ฅผ ๋ ์ ์ถ๋ก ํ๊ธฐ ์ํ์ฌ ์
๋ฐ์ดํธ ๋๋ค.
๊ทธ๋ฆฌ๊ณ SAC ์
๋ฐ์ดํธ์ ์ผ๋ถ๋ก์ ์ํธ๋กํผ ์ ๊ทํ๊ฐ ์งํ๋๋ค.
[์ถ๊ฐ] ๋ง์ฝ ๋ชจ๋ tasks์ ์ฐ๊ด๋์ด ์๋ ์ฃผ์ด์ง latent variable z~p(z)๊ฐ ์๋ค๊ณ ๊ฐ์ ํ์ ๋, ํด๋น ๊ฐ์ ์ด์ฉํ์ฌ reward function์ ์ ์ํ ์ ์๋ค.
reward function = logD(z|s), ์ฌ๊ธฐ์ D๋ discriminator ํจ์์ธ๋ฐ state๋ก๋ถํฐ latent variable์ ๋ฝ๋๋ฐ ์ฌ์ฉํ๋ค.
D(z|s) = q(z|s)
[์ถ๊ฐ] ํ๋ฒ discriminator function์ด ํ์ต๋๋ฉด, training์ ์ํ ์๋ก์ด MDP๋ฅผ samplingํ๋ ๊ฒ์ ๋งค์ฐ ์ง๊ด์ ์ด ๋๋ค. ์ฐ์ latent variable z~p(z)๋ฅผ ์ํ๋งํ๊ณ ์ด๋ฅผ ์ด์ฉํด์ reward function r(s) =logD(z|s)๋ฅผ ๋ง๋ค์ด๋ธ๋ค.
(์ ์ถ๊ฐ๋ด์ฉ ์ถ์ฒ : talkingaboutme.tistory.com/entry/RL-Meta-Reinforcement-Learning)
Conclusion
๋ณธ ๋
ผ๋ฌธ์์๋ reward function์์ด skills๋ฅผ ํ์ตํ๋ ๋ฐฉ๋ฒ์ผ๋ก DIAYN์ ์ ์ํ๊ณ ์๋ค.
DIAYN์ ๋ณต์กํ tasks์ ๋ํด ๋ค์ํ skills๋ฅผ ํ์ตํ๊ณ , ์ค์ ๋ก task reward๋ฅผ ๋ฐ๋ ๊ณผ์ ์์ด bench mark tasks๋ฅผ ํด๊ฒฐํ์๋ค.
1) ๋น ๋ฅด๊ฒ ์๋ก์ด task์ ์ ์ฉํ๋ ๋ฐฉ๋ฒ
2) HRL์ ์ด์ฉํ์ฌ ๋ณต์กํ tasks๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ
3) ์ ๋ฌธ๊ฐ๋ฅผ ๋ชจ๋ฐฉํ์ฌ ํ์ตํ๋ ๋ฐฉ๋ฒ
์ 3๊ฐ์ง ๋ฐฉ๋ฒ๋ค์ ์ ์ํ๊ณ ์๋ค.
์ผ๋ฐ์ ์ผ๋ก DIAYN์ task์ ๋ณต์กํ action space๋ฅผ useful skills์ set์ผ๋ก ๋์ฒดํ์ฌ task๋ฅผ ๋ ์ฝ๊ฒ ํ์ตํ ์ ์๋๋ก ํ๋ค. DIAYN์ observation space์ reward function์ ์ฆ๊ฐ์ํค๊ธฐ ์ํ ๋ฐฉ๋ฒ๋ค๊ณผ ๊ฒฐํฉ๋ ์ ์๋ค.
๊ฒฐ๋ก ์ ์ผ๋ก task reward function์ skill reward function์ผ๋ก ๋์ฒดํ์ฌ ์ฌ์ฉํ๋ค๋ ๊ฒ์ด๋ค.
CODE
์ฝ๋ ๊ตฌํ ๋ด์ญ์ ๋ํ์ฌ ์ค๋ช
ํด ๋ณด๋๋ก ํ๊ฒ ๋ค
๊ธฐ๋ณธ์ ์ธ ๊ณจ๊ฒฉ์ SAC๋ฅผ ์ฐธ๊ณ ํ๋ฉด ๋๋ ๋ถ๋ถ์ธ์ง๋ผ SAC ์ฝ๋๋ฅผ ๋จผ์ ์ดํด๋ณธ ํ DIAYN์์ ๊ฐ์ ๋ ์ฝ๋ ๋ด์ญ์ ์ดํด๋ณด๋ ๊ฒ์ผ๋ก ์งํํ๋๋ก ํ๊ฒ ๋ค.
SAC CODE
import gym
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.optim import Adam
from torch.distributions import Normal
import numpy as np
import random
import matplotlib.pyplot as plt
#===============================================================================
# global variables
#===============================================================================
seed = 1
gamma = 0.99
tau = 0.005
alpha = 0.2
lr = 0.0003
hidden_size = 256
epsilon = 1e-6
replay_size = 1000000
start_steps = 10000
updates_per_step = 1
batch_size = 256
num_steps = 1000000
def weights_init_(m):
if isinstance(m, nn.Linear):
torch.nn.init.xavier_uniform_(m.weight, gain=1)
torch.nn.init.constant_(m.bias, 0)
def hard_update(target, source):
for target_param, param in zip(target.parameters(), source.parameters()):
target_param.data.copy_(param.data)
def soft_update(target, source, tau):
for target_param, param in zip(target.parameters(), source.parameters()):
target_param.data.copy_(target_param.data * (1.0 - tau) + param.data * tau)
class ReplayMemory:
def __init__(self, capacity, seed):
random.seed(seed)
self.capacity = capacity
self.buffer = []
self.position = 0
def push(self, state, action, reward, next_state, done):
if len(self.buffer) < self.capacity:
self.buffer.append(None)
self.buffer[self.position] = (state, action, reward, next_state, done)
self.position = (self.position + 1) % self.capacity
def sample(self, batch_size):
batch = random.sample(self.buffer, batch_size)
state, action, reward, next_state, done = map(np.stack, zip(*batch))
return state, action, reward, next_state, done
def __len__(self):
return len(self.buffer)
class QNetwork(nn.Module):
def __init__(self, num_inputs, num_actions, hidden_dim):
super(QNetwork, self).__init__()
# Q1 architecture
self.linear1 = nn.Linear(num_inputs + num_actions, hidden_dim)
self.linear2 = nn.Linear(hidden_dim, hidden_dim)
self.linear3 = nn.Linear(hidden_dim, 1)
# Q2 architecture
self.linear4 = nn.Linear(num_inputs + num_actions, hidden_dim)
self.linear5 = nn.Linear(hidden_dim, hidden_dim)
self.linear6 = nn.Linear(hidden_dim, 1)
self.apply(weights_init_)
def forward(self, state, action):
xu = torch.cat([state, action], 1)
x1 = F.relu(self.linear1(xu))
x1 = F.relu(self.linear2(x1))
x1 = self.linear3(x1)
x2 = F.relu(self.linear4(xu))
x2 = F.relu(self.linear5(x2))
x2 = self.linear6(x2)
return x1, x2
class ValueNetwork(nn.Module):
def __init__(self, num_inputs, hidden_dim):
super(ValueNetwork, self).__init__()
self.linear1 = nn.Linear(num_inputs, hidden_dim)
self.linear2 = nn.Linear(hidden_dim, hidden_dim)
self.linear3 = nn.Linear(hidden_dim, 1)
self.apply(weights_init_)
def forward(self, state):
x = F.relu(self.linear1(state))
x = F.relu(self.linear2(x))
x = self.linear3(x)
return x
class GaussianPolicy(nn.Module):
def __init__(self, num_inputs, num_actions, hidden_dim):
super(GaussianPolicy, self).__init__()
self.linear1 = nn.Linear(num_inputs, hidden_dim)
self.linear2 = nn.Linear(hidden_dim, hidden_dim)
self.mean_linear = nn.Linear(hidden_dim, num_actions)
self.log_std_linear = nn.Linear(hidden_dim, num_actions)
self.apply(weights_init_)
def forward(self, state):
x = F.relu(self.linear1(state))
x = F.relu(self.linear2(x))
mean = self.mean_linear(x)
log_std = self.log_std_linear(x)
log_std = torch.clamp(log_std, min=-20, max=2)
return mean, log_std
def sample(self, state):
mean, log_std = self.forward(state)
std = log_std.exp()
normal = Normal(mean, std)
x_t = normal.rsample() # for reparameterization trick (mean + std * N(0,1))
action = torch.tanh(x_t)
log_prob = normal.log_prob(x_t)
# Enforcing Action Bound
log_prob -= torch.log(1 - action.pow(2) + epsilon)
log_prob = log_prob.sum(1, keepdim=True)
return action, log_prob, mean, log_std
class SAC(object):
def __init__(self, num_inputs, action_space):
self.gamma = gamma
self.tau = tau
self.alpha = alpha
self.action_range = [action_space.low, action_space.high]
self.device = 'cuda' if torch.cuda.is_available() else 'cpu'
self.critic = QNetwork(num_inputs, action_space.shape[0], hidden_size).to(device=self.device)
self.critic_optim = Adam(self.critic.parameters(), lr=lr)
self.value = ValueNetwork(num_inputs, hidden_size).to(device=self.device)
self.value_target = ValueNetwork(num_inputs, hidden_size).to(self.device)
self.value_optim = Adam(self.value.parameters(), lr=lr)
hard_update(self.value_target, self.value)
self.policy = GaussianPolicy(num_inputs, action_space.shape[0], hidden_size).to(self.device)
self.policy_optim = Adam(self.policy.parameters(), lr=lr)
def select_action(self, state):
state = torch.FloatTensor(state).to(self.device).unsqueeze(0)
action, _, _, _ = self.policy.sample(state)
action = action.detach().cpu().numpy()[0]
return self.rescale_action(action)
def rescale_action(self, action):
return action * (self.action_range[1] - self.action_range[0]) / 2.0 +\
(self.action_range[1] + self.action_range[0]) / 2.0
def update_parameters(self, memory, batch_size, updates):
# Sample a batch from memory
state_batch, action_batch, reward_batch, next_state_batch, mask_batch = memory.sample(batch_size=batch_size)
state_batch = torch.FloatTensor(state_batch).to(self.device)
next_state_batch = torch.FloatTensor(next_state_batch).to(self.device)
action_batch = torch.FloatTensor(action_batch).to(self.device)
reward_batch = torch.FloatTensor(reward_batch).to(self.device).unsqueeze(1)
mask_batch = torch.FloatTensor(mask_batch).to(self.device).unsqueeze(1)
with torch.no_grad():
vf_next_target = self.value_target(next_state_batch)
next_q_value = reward_batch + mask_batch * self.gamma * (vf_next_target)
qf1, qf2 = self.critic(state_batch, action_batch)
qf1_loss = F.mse_loss(qf1, next_q_value)
qf2_loss = F.mse_loss(qf2, next_q_value)
qf_loss = qf1_loss + qf2_loss
self.critic_optim.zero_grad()
qf_loss.backward()
self.critic_optim.step()
pi, log_pi, mean, log_std = self.policy.sample(state_batch)
qf1_pi, qf2_pi = self.critic(state_batch, pi)
min_qf_pi = torch.min(qf1_pi, qf2_pi)
policy_loss = ((self.alpha * log_pi) - min_qf_pi).mean()
# Regularization Loss (optional)
reg_loss = 0.001 * (mean.pow(2).mean() + log_std.pow(2).mean())
policy_loss += reg_loss
self.policy_optim.zero_grad()
policy_loss.backward()
self.policy_optim.step()
vf = self.value(state_batch)
with torch.no_grad():
vf_target = min_qf_pi - (self.alpha * log_pi)
vf_loss = F.mse_loss(vf, vf_target)
self.value_optim.zero_grad()
vf_loss.backward()
self.value_optim.step()
soft_update(self.value_target, self.value, self.tau)
return vf_loss.item(), qf1_loss.item(), qf2_loss.item(), policy_loss.item()
def main():
env = gym.make('Pendulum-v1')
env.seed(seed)
env.action_space.seed(seed)
torch.manual_seed(seed)
np.random.seed(seed)
agent = SAC(env.observation_space.shape[0], env.action_space)
memory = ReplayMemory(replay_size, seed)
# Training Loop
total_numsteps = 0
updates = 0
ep_r_store = []
for i_episode in range(1000):
episode_reward = 0
episode_steps = 0
done = False
state = env.reset()
while not done:
if start_steps > total_numsteps:
action = env.action_space.sample()
else:
action = agent.select_action(state) # Sample action from policy
if len(memory) > batch_size:
for i in range(updates_per_step): # Number of updates per step in environment
# Update parameters of all the networks
value_loss, critic_1_loss, critic_2_loss, policy_loss = agent.update_parameters(memory, batch_size, updates)
updates += 1
next_state, reward, done, _ = env.step(action) # Step
episode_steps += 1
total_numsteps += 1
episode_reward += reward
# Ignore the "done" signal if it comes from hitting the time horizon.
# (https://github.com/openai/spinningup/blob/master/spinup/algos/sac/sac.py)
mask = 1 if episode_steps == env._max_episode_steps else float(not done)
memory.push(state, action, reward, next_state, mask) # Append transition to memory
state = next_state
if done:
ep_r_store.append(episode_reward)
if total_numsteps > num_steps:
break
print("Episode: {}, total numsteps: {}, episode steps: {}, reward: {}".format(
i_episode, total_numsteps, episode_steps, round(episode_reward, 2)))
env.close()
plt.plot(ep_r_store)
plt.title('SAC')
plt.xlabel('episode number')
plt.ylabel('return')
plt.grid(True)
plt.savefig("sac.png")
if __name__ == '__main__':
main()
hard_update์ soft_update์ ์ฐจ์ด๋ฅผ ์ ์์์ผ ํ๋ค. ์ด๋ฅผ ์ดํดํ๊ธฐ ์ํด์๋ full batch์ mini batch์ฐจ์ด๋ฅผ ์๋ ๊ฒ์ด ๋์์ด ๋๋ค. hard_update๋ฅผ full batch๋ก soft_update๋ฅผ mini batch๋ก ์ดํดํ๋ฉด ๋๋ค.

replay buffer๋ฅผ ์ฌ์ฉํ์ฌ Environment์์ Policy์ ์คํํ ๋ ๊ฒฝํ์ ๊ถค์ ์ ์ ์ฅํฉ๋๋ค. ํ๋ จ ์ค์, ์์ด์ ํธ์ ๊ฒฝํ์ “replay”ํ๊ธฐ ์ํด ๊ถค์ ์ ์๋ธ ์ธํธ(์์ฐจ ์๋ธ ์ธํธ ๋๋ ์ํ)์ ๋ํด ์ฌํ ๋ฒํผ๊ฐ ์กฐํ๋จ

Value Network๋ฅผ Q-Network๋ก ๊ตฌํํ ๋ด์ญ์ด๋ค.

Value Network์ ๊ตฌํ์ฒด๋ ์๋์ ๊ฐ๋ค.

Actor network
– SAC๋ด์์ continuous action space๋ด์ stochastic policy๋ฅผ ์ฌ์ฉํ๋ค.
– actor network๋ ๊ฐ๊ฐ์ action์ ๋ํด ํ๊ท ๊ณผ ํ์คํธ์ฐจ๋ฅผ ์์ฑํ๋ค.
– action์ ์ฃผ์ด์ง ํ๊ท ๊ณผ ํ์คํธ์ฐจ๋ฅผ ๊ฐ์ง๊ณ gaussian distribution์ผ๋ก๋ถํฐ sample๋์ด์ง ๊ฒ์ผ๋ก ๋ณธ๋ค.
– ๊ณ์ฐ๋ ํ์คํธ์ฐจ ๋์ ์, ์ฐ๋ฆฌ๋ network ์ฐ์ฐ๋ ๋ก๊ทธ ํธ์ฐจ์ ๊ทธ๋ฆฌ๊ณ ์ด๋ฅผ ์ถํ์ ํ์คํธ์ฐจ๋ก ๋ณํํ๋ค

Actor network
– ์ํ๊ฐ ์ฃผ์ด์ง๊ณ , actor network๋ ํ๊ท ๊ณผ log_std๋ฅผ ์์ฑํ๋ค.
– log_std๋ ๋งค์ฐ ํฌ๊ณ ๋งค์ฐ ์์ std๋ฅผ ์์ฑํ์ง ์๋๋ก ๊ณ ์ ํด ๋๋ค.



SAC agent









DIAYN CODE