diff --git a/projects/README.md b/projects/README.md
index 2ad650f..c8c5d74 100644
--- a/projects/README.md
+++ b/projects/README.md
@@ -1,6 +1,6 @@
## 0、写在前面
-本项目用于学习RL基础算法,主要面向对象为RL初学者、需要结合RL的非专业学习者,尽量做到: **(中文)注释详细**,**结构清晰**。
+本项目用于学习RL基础算法,主要面向对象为RL初学者、需要结合RL的非专业学习者,尽量做到: **注释详细**,**结构清晰**。
注意本项目为实战内容,建议首先掌握相关算法的一些理论基础,再来享用本项目,理论教程参考本人参与编写的[蘑菇书](https://github.com/datawhalechina/easy-rl)。
@@ -10,25 +10,65 @@
项目内容主要包含以下几个部分:
* [Jupyter Notebook](./notebooks/):使用Notebook写的算法,有比较详细的实战引导,推荐新手食用
-* [codes](./assets/):这些是基于Python脚本写的算法,风格比较接近实际项目的写法,推荐有一定代码基础的人阅读,下面会说明其具体的一些架构
+* [codes](./codes/):这些是基于Python脚本写的算法,风格比较接近实际项目的写法,推荐有一定代码基础的人阅读,下面会说明其具体的一些架构
* [parl](./PARL/):应业务需求,写了一些基于百度飞浆平台和```parl```模块的RL实例
* [附件](./assets/):目前包含强化学习各算法的中文伪代码
[codes](./assets/)结构主要分为以下几个脚本:
* ```[algorithm_name].py```:即保存算法的脚本,例如```dqn.py```,每种算法都会有一定的基础模块,例如```Replay Buffer```、```MLP```(多层感知机)等等;
-* ```task.py```: 即保存任务的脚本,基本包括基于```argparse```模块的参数,训练以及测试函数等等;
+* ```task.py```: 即保存任务的脚本,基本包括基于```argparse```模块的参数,训练以及测试函数等等,其中训练函数即```train```遵循伪代码而设计,想读懂代码可从该函数入手;
* ```utils.py```:该脚本用于保存诸如存储结果以及画图的软件,在实际项目或研究中,推荐大家使用```Tensorboard```来保存结果,然后使用诸如```matplotlib```以及```seabron```来进一步画图。
+## 2、算法列表
-## 2、运行环境
+注:点击对应的名称会跳到[codes](./codes/)下对应的算法中,其他版本还请读者自行翻阅
-python 3.7、pytorch 1.6.0-1.9.0、gym 0.21.0
+| 算法名称 | 参考文献 | 环境 | 备注 |
+| :-----------------------: | :----------------------------------------------------------: | :--: | :--: |
+| | | | |
+| DQN-CNN | | | 待更 |
+| [SoftQ](codes/SoftQ) | [Soft Q-learning paper](https://arxiv.org/abs/1702.08165) | | |
+| [SAC](codes/SAC) | [SAC paper](https://arxiv.org/pdf/1812.05905.pdf) | | |
+| [SAC-Discrete](codes/SAC) | [SAC-Discrete paper](https://arxiv.org/pdf/1910.07207.pdf) | | |
+| SAC-V | [SAC-V paper](https://arxiv.org/abs/1801.01290) | | |
+| DSAC | [DSAC paper](https://paperswithcode.com/paper/addressing-value-estimation-errors-in) | | 待更 |
+
+
+
+## 3、运行环境
+
+Python 3.7、PyTorch 1.10.0、Gym 0.21.0
在项目根目录下执行以下命令复现环境:
```bash
pip install -r requirements.txt
```
-## 3、使用说明
+如果需要使用CUDA,则需另外安装```cudatoolkit```,推荐```10.2```或者```11.3```版本的CUDA,如下:
+```bash
+conda install cudatoolkit=11.3 -c pytorch
+```
+如果conda需要镜像加速安装的话,点击[该清华镜像链接](https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/),选择对应的操作系统,比如```win-64```,然后复制链接,执行如下命令:
+```bash
+conda install cudatoolkit=11.3 -c https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/win-64/
+```
+执行以下Python脚本,如果返回True说明cuda安装成功:
+```python
+import torch
+print(torch.cuda.is_available())
+```
+如果还是不成功,可以使用pip安装:
+```bash
+pip install torch==1.10.0+cu113 torchvision==0.11.0+cu113 torchaudio==0.10.0 --extra-index-url https://download.pytorch.org/whl/cu113
+```
+## 4、使用说明
-直接运行带有```train```的py文件或ipynb文件会进行训练默认的任务;
-也可以运行带有```task```的py文件训练不同的任务
+对于[codes](./codes/):
+* 运行带有task的py脚本
+
+对于[Jupyter Notebook](./notebooks/):
+
+* 直接运行对应的ipynb文件就行
+
+## 5、友情说明
+
+推荐使用VS Code做项目,入门可参考[VSCode上手指南](https://blog.csdn.net/JohnJim0/article/details/126366454)
\ No newline at end of file
diff --git a/projects/assets/pseudocodes/pseudocodes.aux b/projects/assets/pseudocodes/pseudocodes.aux
index 1373a7a..67d3e69 100644
--- a/projects/assets/pseudocodes/pseudocodes.aux
+++ b/projects/assets/pseudocodes/pseudocodes.aux
@@ -1,4 +1,33 @@
\relax
-\@writefile{loa}{\contentsline {algorithm}{\numberline {}{\ignorespaces }}{1}{}\protected@file@percent }
-\@writefile{loa}{\contentsline {algorithm}{\numberline {}{\ignorespaces }}{2}{}\protected@file@percent }
-\gdef \@abspage@last{2}
+\providecommand\hyper@newdestlabel[2]{}
+\providecommand\HyperFirstAtBeginDocument{\AtBeginDocument}
+\HyperFirstAtBeginDocument{\ifx\hyper@anchor\@undefined
+\global\let\oldcontentsline\contentsline
+\gdef\contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}}
+\global\let\oldnewlabel\newlabel
+\gdef\newlabel#1#2{\newlabelxx{#1}#2}
+\gdef\newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}}
+\AtEndDocument{\ifx\hyper@anchor\@undefined
+\let\contentsline\oldcontentsline
+\let\newlabel\oldnewlabel
+\fi}
+\fi}
+\global\let\hyper@last\relax
+\gdef\HyperFirstAtBeginDocument#1{#1}
+\providecommand*\HyPL@Entry[1]{}
+\HyPL@Entry{0<>}
+\@writefile{toc}{\contentsline {section}{\numberline {1}模版备用}{2}{section.1}\protected@file@percent }
+\@writefile{loa}{\contentsline {algorithm}{\numberline {}{\ignorespaces }}{2}{algorithm.}\protected@file@percent }
+\@writefile{toc}{\contentsline {section}{\numberline {2}Q learning算法}{3}{section.2}\protected@file@percent }
+\@writefile{loa}{\contentsline {algorithm}{\numberline {}{\ignorespaces }}{3}{algorithm.}\protected@file@percent }
+\@writefile{toc}{\contentsline {section}{\numberline {3}Sarsa算法}{4}{section.3}\protected@file@percent }
+\@writefile{loa}{\contentsline {algorithm}{\numberline {}{\ignorespaces }}{4}{algorithm.}\protected@file@percent }
+\@writefile{toc}{\contentsline {section}{\numberline {4}Policy Gradient算法}{5}{section.4}\protected@file@percent }
+\@writefile{loa}{\contentsline {algorithm}{\numberline {}{\ignorespaces }}{5}{algorithm.}\protected@file@percent }
+\@writefile{toc}{\contentsline {section}{\numberline {5}DQN算法}{6}{section.5}\protected@file@percent }
+\@writefile{loa}{\contentsline {algorithm}{\numberline {}{\ignorespaces }}{6}{algorithm.}\protected@file@percent }
+\@writefile{toc}{\contentsline {section}{\numberline {6}SoftQ算法}{7}{section.6}\protected@file@percent }
+\@writefile{loa}{\contentsline {algorithm}{\numberline {}{\ignorespaces }}{7}{algorithm.}\protected@file@percent }
+\@writefile{toc}{\contentsline {section}{\numberline {7}SAC算法}{8}{section.7}\protected@file@percent }
+\@writefile{loa}{\contentsline {algorithm}{\numberline {}{\ignorespaces }}{8}{algorithm.}\protected@file@percent }
+\gdef \@abspage@last{8}
diff --git a/projects/assets/pseudocodes/pseudocodes.log b/projects/assets/pseudocodes/pseudocodes.log
index 4a91f11..865cabe 100644
--- a/projects/assets/pseudocodes/pseudocodes.log
+++ b/projects/assets/pseudocodes/pseudocodes.log
@@ -1,4 +1,4 @@
-This is XeTeX, Version 3.141592653-2.6-0.999993 (TeX Live 2021) (preloaded format=xelatex 2021.8.22) 15 AUG 2022 15:05
+This is XeTeX, Version 3.141592653-2.6-0.999993 (TeX Live 2021) (preloaded format=xelatex 2021.8.22) 22 AUG 2022 16:54
entering extended mode
restricted \write18 enabled.
file:line:error style messages enabled.
@@ -292,107 +292,282 @@ LaTeX Font Info: Redeclaring font encoding OMS on input line 744.
\mathdisplay@stack=\toks24
LaTeX Info: Redefining \[ on input line 2923.
LaTeX Info: Redefining \] on input line 2924.
+) (/usr/local/texlive/2021/texmf-dist/tex/latex/hyperref/hyperref.sty
+Package: hyperref 2021-02-27 v7.00k Hypertext links for LaTeX
+ (/usr/local/texlive/2021/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty
+Package: ltxcmds 2020-05-10 v1.25 LaTeX kernel commands for general use (HO)
+) (/usr/local/texlive/2021/texmf-dist/tex/generic/iftex/iftex.sty
+Package: iftex 2020/03/06 v1.0d TeX engine tests
+) (/usr/local/texlive/2021/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty
+Package: pdftexcmds 2020-06-27 v0.33 Utility functions of pdfTeX for LuaTeX (HO)
+ (/usr/local/texlive/2021/texmf-dist/tex/generic/infwarerr/infwarerr.sty
+Package: infwarerr 2019/12/03 v1.5 Providing info/warning/error messages (HO)
+)
+Package pdftexcmds Info: \pdf@primitive is available.
+Package pdftexcmds Info: \pdf@ifprimitive is available.
+Package pdftexcmds Info: \pdfdraftmode not found.
+) (/usr/local/texlive/2021/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty
+Package: kvsetkeys 2019/12/15 v1.18 Key value parser (HO)
+) (/usr/local/texlive/2021/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty
+Package: kvdefinekeys 2019-12-19 v1.6 Define keys (HO)
+) (/usr/local/texlive/2021/texmf-dist/tex/generic/pdfescape/pdfescape.sty
+Package: pdfescape 2019/12/09 v1.15 Implements pdfTeX's escape features (HO)
+) (/usr/local/texlive/2021/texmf-dist/tex/latex/hycolor/hycolor.sty
+Package: hycolor 2020-01-27 v1.10 Color options for hyperref/bookmark (HO)
+) (/usr/local/texlive/2021/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty
+Package: letltxmacro 2019/12/03 v1.6 Let assignment for LaTeX macros (HO)
+) (/usr/local/texlive/2021/texmf-dist/tex/latex/auxhook/auxhook.sty
+Package: auxhook 2019-12-17 v1.6 Hooks for auxiliary files (HO)
+) (/usr/local/texlive/2021/texmf-dist/tex/latex/kvoptions/kvoptions.sty
+Package: kvoptions 2020-10-07 v3.14 Key value format for package options (HO)
+)
+\@linkdim=\dimen183
+\Hy@linkcounter=\count301
+\Hy@pagecounter=\count302
+ (/usr/local/texlive/2021/texmf-dist/tex/latex/hyperref/pd1enc.def
+File: pd1enc.def 2021-02-27 v7.00k Hyperref: PDFDocEncoding definition (HO)
+) (/usr/local/texlive/2021/texmf-dist/tex/latex/hyperref/hyperref-langpatches.def
+File: hyperref-langpatches.def 2021-02-27 v7.00k Hyperref: patches for babel languages
+) (/usr/local/texlive/2021/texmf-dist/tex/generic/intcalc/intcalc.sty
+Package: intcalc 2019/12/15 v1.3 Expandable calculations with integers (HO)
+) (/usr/local/texlive/2021/texmf-dist/tex/generic/etexcmds/etexcmds.sty
+Package: etexcmds 2019/12/15 v1.7 Avoid name clashes with e-TeX commands (HO)
+)
+\Hy@SavedSpaceFactor=\count303
+ (/usr/local/texlive/2021/texmf-dist/tex/latex/hyperref/puenc.def
+File: puenc.def 2021-02-27 v7.00k Hyperref: PDF Unicode definition (HO)
+)
+Package hyperref Info: Option `unicode' set `true' on input line 4073.
+Package hyperref Info: Hyper figures OFF on input line 4192.
+Package hyperref Info: Link nesting OFF on input line 4197.
+Package hyperref Info: Hyper index ON on input line 4200.
+Package hyperref Info: Plain pages OFF on input line 4207.
+Package hyperref Info: Backreferencing OFF on input line 4212.
+Package hyperref Info: Implicit mode ON; LaTeX internals redefined.
+Package hyperref Info: Bookmarks ON on input line 4445.
+\c@Hy@tempcnt=\count304
+ (/usr/local/texlive/2021/texmf-dist/tex/latex/url/url.sty
+\Urlmuskip=\muskip18
+Package: url 2013/09/16 ver 3.4 Verb mode for urls, etc.
+)
+LaTeX Info: Redefining \url on input line 4804.
+\XeTeXLinkMargin=\dimen184
+ (/usr/local/texlive/2021/texmf-dist/tex/generic/bitset/bitset.sty
+Package: bitset 2019/12/09 v1.3 Handle bit-vector datatype (HO)
+ (/usr/local/texlive/2021/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty
+Package: bigintcalc 2019/12/15 v1.5 Expandable calculations on big integers (HO)
+))
+\Fld@menulength=\count305
+\Field@Width=\dimen185
+\Fld@charsize=\dimen186
+Package hyperref Info: Hyper figures OFF on input line 6075.
+Package hyperref Info: Link nesting OFF on input line 6080.
+Package hyperref Info: Hyper index ON on input line 6083.
+Package hyperref Info: backreferencing OFF on input line 6090.
+Package hyperref Info: Link coloring OFF on input line 6095.
+Package hyperref Info: Link coloring with OCG OFF on input line 6100.
+Package hyperref Info: PDF/A mode OFF on input line 6105.
+LaTeX Info: Redefining \ref on input line 6145.
+LaTeX Info: Redefining \pageref on input line 6149.
+ (/usr/local/texlive/2021/texmf-dist/tex/latex/base/atbegshi-ltx.sty
+Package: atbegshi-ltx 2020/08/17 v1.0a Emulation of the original atbegshi package
+with kernel methods
+)
+\Hy@abspage=\count306
+\c@Item=\count307
+\c@Hfootnote=\count308
+)
+Package hyperref Info: Driver (autodetected): hxetex.
+ (/usr/local/texlive/2021/texmf-dist/tex/latex/hyperref/hxetex.def
+File: hxetex.def 2021-02-27 v7.00k Hyperref driver for XeTeX
+ (/usr/local/texlive/2021/texmf-dist/tex/generic/stringenc/stringenc.sty
+Package: stringenc 2019/11/29 v1.12 Convert strings between diff. encodings (HO)
+)
+\pdfm@box=\box54
+\c@Hy@AnnotLevel=\count309
+\HyField@AnnotCount=\count310
+\Fld@listcount=\count311
+\c@bookmark@seq@number=\count312
+ (/usr/local/texlive/2021/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty
+Package: rerunfilecheck 2019/12/05 v1.9 Rerun checks for auxiliary files (HO)
+ (/usr/local/texlive/2021/texmf-dist/tex/latex/base/atveryend-ltx.sty
+Package: atveryend-ltx 2020/08/19 v1.0a Emulation of the original atvery package
+with kernel methods
+) (/usr/local/texlive/2021/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty
+Package: uniquecounter 2019/12/15 v1.4 Provide unlimited unique counter (HO)
+)
+Package uniquecounter Info: New unique counter `rerunfilecheck' on input line 286.
+)
+\Hy@SectionHShift=\skip63
+) (/usr/local/texlive/2021/texmf-dist/tex/latex/setspace/setspace.sty
+Package: setspace 2011/12/19 v6.7a set line spacing
+) (/usr/local/texlive/2021/texmf-dist/tex/latex/titlesec/titlesec.sty
+Package: titlesec 2019/10/16 v2.13 Sectioning titles
+\ttl@box=\box55
+\beforetitleunit=\skip64
+\aftertitleunit=\skip65
+\ttl@plus=\dimen187
+\ttl@minus=\dimen188
+\ttl@toksa=\toks25
+\titlewidth=\dimen189
+\titlewidthlast=\dimen190
+\titlewidthfirst=\dimen191
) (./pseudocodes.aux)
\openout1 = `pseudocodes.aux'.
-LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 9.
-LaTeX Font Info: ... okay on input line 9.
-LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 9.
-LaTeX Font Info: ... okay on input line 9.
-LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 9.
-LaTeX Font Info: ... okay on input line 9.
-LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 9.
-LaTeX Font Info: ... okay on input line 9.
-LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 9.
-LaTeX Font Info: ... okay on input line 9.
-LaTeX Font Info: Checking defaults for TU/lmr/m/n on input line 9.
-LaTeX Font Info: ... okay on input line 9.
-LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 9.
-LaTeX Font Info: ... okay on input line 9.
-LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 9.
-LaTeX Font Info: ... okay on input line 9.
+LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 13.
+LaTeX Font Info: ... okay on input line 13.
+LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 13.
+LaTeX Font Info: ... okay on input line 13.
+LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 13.
+LaTeX Font Info: ... okay on input line 13.
+LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 13.
+LaTeX Font Info: ... okay on input line 13.
+LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 13.
+LaTeX Font Info: ... okay on input line 13.
+LaTeX Font Info: Checking defaults for TU/lmr/m/n on input line 13.
+LaTeX Font Info: ... okay on input line 13.
+LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 13.
+LaTeX Font Info: ... okay on input line 13.
+LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 13.
+LaTeX Font Info: ... okay on input line 13.
+LaTeX Font Info: Checking defaults for PD1/pdf/m/n on input line 13.
+LaTeX Font Info: ... okay on input line 13.
+LaTeX Font Info: Checking defaults for PU/pdf/m/n on input line 13.
+LaTeX Font Info: ... okay on input line 13.
ABD: EverySelectfont initializing macros
-LaTeX Info: Redefining \selectfont on input line 9.
+LaTeX Info: Redefining \selectfont on input line 13.
Package fontspec Info: Adjusting the maths setup (use [no-math] to avoid
(fontspec) this).
\symlegacymaths=\mathgroup6
LaTeX Font Info: Overwriting symbol font `legacymaths' in version `bold'
-(Font) OT1/cmr/m/n --> OT1/cmr/bx/n on input line 9.
-LaTeX Font Info: Redeclaring math accent \acute on input line 9.
-LaTeX Font Info: Redeclaring math accent \grave on input line 9.
-LaTeX Font Info: Redeclaring math accent \ddot on input line 9.
-LaTeX Font Info: Redeclaring math accent \tilde on input line 9.
-LaTeX Font Info: Redeclaring math accent \bar on input line 9.
-LaTeX Font Info: Redeclaring math accent \breve on input line 9.
-LaTeX Font Info: Redeclaring math accent \check on input line 9.
-LaTeX Font Info: Redeclaring math accent \hat on input line 9.
-LaTeX Font Info: Redeclaring math accent \dot on input line 9.
-LaTeX Font Info: Redeclaring math accent \mathring on input line 9.
-LaTeX Font Info: Redeclaring math symbol \Gamma on input line 9.
-LaTeX Font Info: Redeclaring math symbol \Delta on input line 9.
-LaTeX Font Info: Redeclaring math symbol \Theta on input line 9.
-LaTeX Font Info: Redeclaring math symbol \Lambda on input line 9.
-LaTeX Font Info: Redeclaring math symbol \Xi on input line 9.
-LaTeX Font Info: Redeclaring math symbol \Pi on input line 9.
-LaTeX Font Info: Redeclaring math symbol \Sigma on input line 9.
-LaTeX Font Info: Redeclaring math symbol \Upsilon on input line 9.
-LaTeX Font Info: Redeclaring math symbol \Phi on input line 9.
-LaTeX Font Info: Redeclaring math symbol \Psi on input line 9.
-LaTeX Font Info: Redeclaring math symbol \Omega on input line 9.
-LaTeX Font Info: Redeclaring math symbol \mathdollar on input line 9.
-LaTeX Font Info: Redeclaring symbol font `operators' on input line 9.
+(Font) OT1/cmr/m/n --> OT1/cmr/bx/n on input line 13.
+LaTeX Font Info: Redeclaring math accent \acute on input line 13.
+LaTeX Font Info: Redeclaring math accent \grave on input line 13.
+LaTeX Font Info: Redeclaring math accent \ddot on input line 13.
+LaTeX Font Info: Redeclaring math accent \tilde on input line 13.
+LaTeX Font Info: Redeclaring math accent \bar on input line 13.
+LaTeX Font Info: Redeclaring math accent \breve on input line 13.
+LaTeX Font Info: Redeclaring math accent \check on input line 13.
+LaTeX Font Info: Redeclaring math accent \hat on input line 13.
+LaTeX Font Info: Redeclaring math accent \dot on input line 13.
+LaTeX Font Info: Redeclaring math accent \mathring on input line 13.
+LaTeX Font Info: Redeclaring math symbol \Gamma on input line 13.
+LaTeX Font Info: Redeclaring math symbol \Delta on input line 13.
+LaTeX Font Info: Redeclaring math symbol \Theta on input line 13.
+LaTeX Font Info: Redeclaring math symbol \Lambda on input line 13.
+LaTeX Font Info: Redeclaring math symbol \Xi on input line 13.
+LaTeX Font Info: Redeclaring math symbol \Pi on input line 13.
+LaTeX Font Info: Redeclaring math symbol \Sigma on input line 13.
+LaTeX Font Info: Redeclaring math symbol \Upsilon on input line 13.
+LaTeX Font Info: Redeclaring math symbol \Phi on input line 13.
+LaTeX Font Info: Redeclaring math symbol \Psi on input line 13.
+LaTeX Font Info: Redeclaring math symbol \Omega on input line 13.
+LaTeX Font Info: Redeclaring math symbol \mathdollar on input line 13.
+LaTeX Font Info: Redeclaring symbol font `operators' on input line 13.
LaTeX Font Info: Encoding `OT1' has changed to `TU' for symbol font
-(Font) `operators' in the math version `normal' on input line 9.
+(Font) `operators' in the math version `normal' on input line 13.
LaTeX Font Info: Overwriting symbol font `operators' in version `normal'
-(Font) OT1/cmr/m/n --> TU/lmr/m/n on input line 9.
+(Font) OT1/cmr/m/n --> TU/lmr/m/n on input line 13.
LaTeX Font Info: Encoding `OT1' has changed to `TU' for symbol font
-(Font) `operators' in the math version `bold' on input line 9.
+(Font) `operators' in the math version `bold' on input line 13.
LaTeX Font Info: Overwriting symbol font `operators' in version `bold'
-(Font) OT1/cmr/bx/n --> TU/lmr/m/n on input line 9.
+(Font) OT1/cmr/bx/n --> TU/lmr/m/n on input line 13.
LaTeX Font Info: Overwriting symbol font `operators' in version `normal'
-(Font) TU/lmr/m/n --> TU/lmr/m/n on input line 9.
+(Font) TU/lmr/m/n --> TU/lmr/m/n on input line 13.
LaTeX Font Info: Overwriting math alphabet `\mathit' in version `normal'
-(Font) OT1/cmr/m/it --> TU/lmr/m/it on input line 9.
+(Font) OT1/cmr/m/it --> TU/lmr/m/it on input line 13.
LaTeX Font Info: Overwriting math alphabet `\mathbf' in version `normal'
-(Font) OT1/cmr/bx/n --> TU/lmr/b/n on input line 9.
+(Font) OT1/cmr/bx/n --> TU/lmr/b/n on input line 13.
LaTeX Font Info: Overwriting math alphabet `\mathsf' in version `normal'
-(Font) OT1/cmss/m/n --> TU/lmss/m/n on input line 9.
+(Font) OT1/cmss/m/n --> TU/lmss/m/n on input line 13.
LaTeX Font Info: Overwriting math alphabet `\mathtt' in version `normal'
-(Font) OT1/cmtt/m/n --> TU/lmtt/m/n on input line 9.
+(Font) OT1/cmtt/m/n --> TU/lmtt/m/n on input line 13.
LaTeX Font Info: Overwriting symbol font `operators' in version `bold'
-(Font) TU/lmr/m/n --> TU/lmr/b/n on input line 9.
+(Font) TU/lmr/m/n --> TU/lmr/b/n on input line 13.
LaTeX Font Info: Overwriting math alphabet `\mathit' in version `bold'
-(Font) OT1/cmr/bx/it --> TU/lmr/b/it on input line 9.
+(Font) OT1/cmr/bx/it --> TU/lmr/b/it on input line 13.
LaTeX Font Info: Overwriting math alphabet `\mathsf' in version `bold'
-(Font) OT1/cmss/bx/n --> TU/lmss/b/n on input line 9.
+(Font) OT1/cmss/bx/n --> TU/lmss/b/n on input line 13.
LaTeX Font Info: Overwriting math alphabet `\mathtt' in version `bold'
-(Font) OT1/cmtt/m/n --> TU/lmtt/b/n on input line 9.
-LaTeX Font Info: Trying to load font information for U+msa on input line 20.
+(Font) OT1/cmtt/m/n --> TU/lmtt/b/n on input line 13.
+Package hyperref Info: Link coloring OFF on input line 13.
+ (/usr/local/texlive/2021/texmf-dist/tex/latex/hyperref/nameref.sty
+Package: nameref 2021-04-02 v2.47 Cross-referencing by name of section
+ (/usr/local/texlive/2021/texmf-dist/tex/latex/refcount/refcount.sty
+Package: refcount 2019/12/15 v3.6 Data extraction from label references (HO)
+) (/usr/local/texlive/2021/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty
+Package: gettitlestring 2019/12/15 v1.6 Cleanup title references (HO)
+)
+\c@section@level=\count313
+)
+LaTeX Info: Redefining \ref on input line 13.
+LaTeX Info: Redefining \pageref on input line 13.
+LaTeX Info: Redefining \nameref on input line 13.
+ (./pseudocodes.out) (./pseudocodes.out)
+\@outlinefile=\write3
+\openout3 = `pseudocodes.out'.
+
+ (./pseudocodes.toc)
+\tf@toc=\write4
+\openout4 = `pseudocodes.toc'.
+
+LaTeX Font Info: Font shape `TU/SongtiSCLight(0)/m/sl' in size <10.95> not available
+(Font) Font shape `TU/SongtiSCLight(0)/m/it' tried instead on input line 16.
+ [1
+
+]
+Package hyperref Info: bookmark level for unknown algorithm defaults to 0 on input line 21.
+ [2
+
+]
+LaTeX Font Info: Trying to load font information for U+msa on input line 31.
(/usr/local/texlive/2021/texmf-dist/tex/latex/amsfonts/umsa.fd
File: umsa.fd 2013/01/14 v3.01 AMS symbols A
)
-LaTeX Font Info: Trying to load font information for U+msb on input line 20.
+LaTeX Font Info: Trying to load font information for U+msb on input line 31.
(/usr/local/texlive/2021/texmf-dist/tex/latex/amsfonts/umsb.fd
File: umsb.fd 2013/01/14 v3.01 AMS symbols B
-)
-Overfull \hbox (38.0069pt too wide) in paragraph at lines 32--33
-[] []\TU/SongtiSCLight(0)/m/n/10.95 计 算 实 际 的 $\OML/cmm/m/it/10.95 Q$ \TU/SongtiSCLight(0)/m/n/10.95 值,| 即 $\OML/cmm/m/it/10.95 y[] \OT1/cmr/m/n/10.95 = []$
+) [3
+
+] [4
+
+] [5
+
+]
+Underfull \hbox (badness 10000) in paragraph at lines 111--112
+[] []\TU/SongtiSCLight(0)/m/n/10.95 计 算 实 际 的 $\OML/cmm/m/it/10.95 Q$ \TU/SongtiSCLight(0)/m/n/10.95 值,| 即 $\OML/cmm/m/it/10.95 y[] \OT1/cmr/m/n/10.95 =
[]
-[1
+[6
-] [2
+] [7
-] (./pseudocodes.aux) )
+]
+Overfull \hbox (32.54117pt too wide) in paragraph at lines 183--183
+[][]$[]\OML/cmm/m/it/9 J[]\OT1/cmr/m/n/9 (\OML/cmm/m/it/9 ^^R\OT1/cmr/m/n/9 ) = \OMS/cmsy/m/n/9 r[]\OML/cmm/m/it/9 Q[] [] []$|
+ []
+
+
+Overfull \hbox (15.41673pt too wide) in paragraph at lines 184--184
+[][]$[]\OML/cmm/m/it/9 J[]\OT1/cmr/m/n/9 (\OML/cmm/m/it/9 ^^^\OT1/cmr/m/n/9 ) = \OMS/cmsy/m/n/9 r[]\OML/cmm/m/it/9 ^^K [] [] \OT1/cmr/m/n/9 + [] \OMS/cmsy/m/n/9 r[]\OML/cmm/m/it/9 f[] []$\TU/lmr/m/n/9 ,$[][] \OT1/cmr/m/n/9 =
+ []
+
+[8
+
+] (./pseudocodes.aux)
+Package rerunfilecheck Info: File `pseudocodes.out' has not changed.
+(rerunfilecheck) Checksum: 4575BA7458AA23D6E696EFFE39D05727;640.
+ )
Here is how much of TeX's memory you used:
- 7847 strings out of 476919
- 208964 string characters out of 5821840
- 529246 words of memory out of 5000000
- 27739 multiletter control sequences out of 15000+600000
- 410995 words of font info for 73 fonts, out of 8000000 for 9000
+ 14813 strings out of 476919
+ 312635 string characters out of 5821840
+ 653471 words of memory out of 5000000
+ 34563 multiletter control sequences out of 15000+600000
+ 413601 words of font info for 90 fonts, out of 8000000 for 9000
1348 hyphenation exceptions out of 8191
- 101i,11n,104p,414b,663s stack positions out of 5000i,500n,10000p,200000b,80000s
+ 101i,13n,104p,676b,736s stack positions out of 5000i,500n,10000p,200000b,80000s
-Output written on pseudocodes.pdf (2 pages).
+Output written on pseudocodes.pdf (8 pages).
diff --git a/projects/assets/pseudocodes/pseudocodes.out b/projects/assets/pseudocodes/pseudocodes.out
new file mode 100644
index 0000000..de023a5
--- /dev/null
+++ b/projects/assets/pseudocodes/pseudocodes.out
@@ -0,0 +1,7 @@
+\BOOKMARK [1][-]{section.1}{\376\377\152\041\162\110\131\007\165\050}{}% 1
+\BOOKMARK [1][-]{section.2}{\376\377\000Q\000\040\000l\000e\000a\000r\000n\000i\000n\000g\173\227\154\325}{}% 2
+\BOOKMARK [1][-]{section.3}{\376\377\000S\000a\000r\000s\000a\173\227\154\325}{}% 3
+\BOOKMARK [1][-]{section.4}{\376\377\000P\000o\000l\000i\000c\000y\000\040\000G\000r\000a\000d\000i\000e\000n\000t\173\227\154\325}{}% 4
+\BOOKMARK [1][-]{section.5}{\376\377\000D\000Q\000N\173\227\154\325}{}% 5
+\BOOKMARK [1][-]{section.6}{\376\377\000S\000o\000f\000t\000Q\173\227\154\325}{}% 6
+\BOOKMARK [1][-]{section.7}{\376\377\000S\000A\000C\173\227\154\325}{}% 7
diff --git a/projects/assets/pseudocodes/pseudocodes.pdf b/projects/assets/pseudocodes/pseudocodes.pdf
index 06c1da7..e1852d6 100644
Binary files a/projects/assets/pseudocodes/pseudocodes.pdf and b/projects/assets/pseudocodes/pseudocodes.pdf differ
diff --git a/projects/assets/pseudocodes/pseudocodes.synctex.gz b/projects/assets/pseudocodes/pseudocodes.synctex.gz
index 8754760..07d025c 100644
Binary files a/projects/assets/pseudocodes/pseudocodes.synctex.gz and b/projects/assets/pseudocodes/pseudocodes.synctex.gz differ
diff --git a/projects/assets/pseudocodes/pseudocodes.tex b/projects/assets/pseudocodes/pseudocodes.tex
index 4db2296..3cc47ab 100644
--- a/projects/assets/pseudocodes/pseudocodes.tex
+++ b/projects/assets/pseudocodes/pseudocodes.tex
@@ -4,17 +4,96 @@
\usepackage{algorithmic}
\usepackage{amssymb}
\usepackage{amsmath}
-
-
+\usepackage{hyperref}
+% \usepackage[hidelinks]{hyperref} 去除超链接的红色框
+\usepackage{setspace}
+\usepackage{titlesec}
+\usepackage{float} % 调用该包能够使用[H]
+% \pagestyle{plain} % 去除页眉,但是保留页脚编号,都去掉plain换empty
\begin{document}
-
-\begin{algorithm}
+\tableofcontents % 目录,注意要运行两下或者vscode保存两下才能显示
+% \singlespacing
+\clearpage
+\section{模版备用}
+\begin{algorithm}[H] % [H]固定位置
+ \floatname{algorithm}{{算法}}
+ \renewcommand{\thealgorithm}{} % 去掉算法标号
+ \caption{}
+ \begin{algorithmic}[1] % [1]显示步数
+ \STATE 测试
+ \end{algorithmic}
+\end{algorithm}
+\clearpage
+\section{Q learning算法}
+\begin{algorithm}[H] % [H]固定位置
+ \floatname{algorithm}{{Q-learning算法}\footnotemark[1]}
+ \renewcommand{\thealgorithm}{} % 去掉算法标号
+ \caption{}
+ \begin{algorithmic}[1] % [1]显示步数
+ \STATE 初始化Q表$Q(s,a)$为任意值,但其中$Q(s_{terminal},)=0$,即终止状态对应的Q值为0
+ \FOR {回合数 = $1,M$}
+ \STATE 重置环境,获得初始状态$s_1$
+ \FOR {时步 = $1,t$}
+ \STATE 根据$\varepsilon-greedy$策略采样动作$a_t$
+ \STATE 环境根据$a_t$反馈奖励$r_t$和下一个状态$s_{t+1}$
+ \STATE {\bfseries 更新策略:}
+ \STATE $Q(s_t,a_t) \leftarrow Q(s_t,a_t)+\alpha[r_t+\gamma\max _{a}Q(s_{t+1},a)-Q(s_t,a_t)]$
+ \STATE 更新状态$s_{t+1} \leftarrow s_t$
+ \ENDFOR
+ \ENDFOR
+ \end{algorithmic}
+\end{algorithm}
+\footnotetext[1]{Reinforcement Learning: An Introduction}
+\clearpage
+\section{Sarsa算法}
+\begin{algorithm}[H] % [H]固定位置
+ \floatname{algorithm}{{Sarsa算法}\footnotemark[1]}
+ \renewcommand{\thealgorithm}{} % 去掉算法标号
+ \caption{}
+ \begin{algorithmic}[1] % [1]显示步数
+ \STATE 初始化Q表$Q(s,a)$为任意值,但其中$Q(s_{terminal},)=0$,即终止状态对应的Q值为0
+ \FOR {回合数 = $1,M$}
+ \STATE 重置环境,获得初始状态$s_1$
+ \STATE 根据$\varepsilon-greedy$策略采样初始动作$a_1$
+ \FOR {时步 = $1,t$}
+ \STATE 环境根据$a_t$反馈奖励$r_t$和下一个状态$s_{t+1}$
+ \STATE 根据$\varepsilon-greedy$策略$s_{t+1}$和采样动作$a_{t+1}$
+ \STATE {\bfseries 更新策略:}
+ \STATE $Q(s_t,a_t) \leftarrow Q(s_t,a_t)+\alpha[r_t+\gamma Q(s_{t+1},a_{t+1})-Q(s_t,a_t)]$
+ \STATE 更新状态$s_{t+1} \leftarrow s_t$
+ \STATE 更新动作$a_{t+1} \leftarrow a_t$
+ \ENDFOR
+ \ENDFOR
+ \end{algorithmic}
+\end{algorithm}
+\footnotetext[1]{Reinforcement Learning: An Introduction}
+\clearpage
+\section{Policy Gradient算法}
+\begin{algorithm}[H] % [H]固定位置
+ \floatname{algorithm}{{REINFORCE算法:Monte-Carlo Policy Gradient}\footnotemark[1]}
+ \renewcommand{\thealgorithm}{} % 去掉算法标号
+ \caption{}
+ \begin{algorithmic}[1] % [1]显示步数
+ \STATE 初始化策略参数$\boldsymbol{\theta} \in \mathbb{R}^{d^{\prime}}($ e.g., to $\mathbf{0})$
+ \FOR {回合数 = $1,M$}
+ \STATE 根据策略$\pi(\cdot \mid \cdot, \boldsymbol{\theta})$采样一个(或几个)回合的transition
+ \FOR {时步 = $1,t$}
+ \STATE 计算回报$G \leftarrow \sum_{k=t+1}^{T} \gamma^{k-t-1} R_{k}$
+ \STATE 更新策略$\boldsymbol{\theta} \leftarrow {\boldsymbol{\theta}+\alpha \gamma^{t}} G \nabla \ln \pi\left(A_{t} \mid S_{t}, \boldsymbol{\theta}\right)$
+ \ENDFOR
+ \ENDFOR
+ \end{algorithmic}
+\end{algorithm}
+\footnotetext[1]{Reinforcement Learning: An Introduction}
+\clearpage
+\section{DQN算法}
+\begin{algorithm}[H] % [H]固定位置
\floatname{algorithm}{{DQN算法}}
\renewcommand{\thealgorithm}{} % 去掉算法标号
\caption{}
\renewcommand{\algorithmicrequire}{\textbf{输入:}}
\renewcommand{\algorithmicensure}{\textbf{输出:}}
- \begin{algorithmic}
+ \begin{algorithmic}[1]
% \REQUIRE $n \geq 0 \vee x \neq 0$ % 输入
% \ENSURE $y = x^n$ % 输出
\STATE 初始化策略网络参数$\theta$ % 初始化
@@ -24,40 +103,85 @@
\STATE 重置环境,获得初始状态$s_t$
\FOR {时步 = $1,t$}
\STATE 根据$\varepsilon-greedy$策略采样动作$a_t$
- \STATE 环境根据$a_t$反馈奖励$s_t$和下一个状态$s_{t+1}$
+ \STATE 环境根据$a_t$反馈奖励$r_t$和下一个状态$s_{t+1}$
\STATE 存储transition即$(s_t,a_t,r_t,s_{t+1})$到经验回放$D$中
\STATE 更新环境状态$s_{t+1} \leftarrow s_t$
\STATE {\bfseries 更新策略:}
\STATE 从$D$中采样一个batch的transition
\STATE 计算实际的$Q$值,即$y_{j}= \begin{cases}r_{j} & \text {对于终止状态} s_{j+1} \\ r_{j}+\gamma \max _{a^{\prime}} Q\left(s_{j+1}, a^{\prime} ; \theta\right) & \text {对于非终止状态} s_{j+1}\end{cases}$
\STATE 对损失 $\left(y_{j}-Q\left(s_{j}, a_{j} ; \theta\right)\right)^{2}$关于参数$\theta$做随机梯度下降
- \STATE 每$C$步复制参数$\hat{Q} \leftarrow Q$
\ENDFOR
+ \STATE 每$C$个回合复制参数$\hat{Q}\leftarrow Q$(此处也可像原论文中放到小循环中改成每$C$步,但没有每$C$个回合稳定)
\ENDFOR
\end{algorithmic}
\end{algorithm}
-
\clearpage
-\begin{algorithm}
+\section{SoftQ算法}
+\begin{algorithm}[H]
\floatname{algorithm}{{SoftQ算法}}
\renewcommand{\thealgorithm}{} % 去掉算法标号
\caption{}
- \begin{algorithmic}
+ \begin{algorithmic}[1]
\STATE 初始化参数$\theta$和$\phi$% 初始化
\STATE 复制参数$\bar{\theta} \leftarrow \theta, \bar{\phi} \leftarrow \phi$
\STATE 初始化经验回放$D$
\FOR {回合数 = $1,M$}
\FOR {时步 = $1,t$}
- \STATE 根据$a_{t} \leftarrow f^{\phi}\left(\xi ; \mathbf{s}_{t}\right)$采样动作,其中$\xi \sim \mathcal{N}(\mathbf{0}, \boldsymbol{I})$
+ \STATE 根据$\mathbf{a}_{t} \leftarrow f^{\phi}\left(\xi ; \mathbf{s}_{t}\right)$采样动作,其中$\xi \sim \mathcal{N}(\mathbf{0}, \boldsymbol{I})$
\STATE 环境根据$a_t$反馈奖励$s_t$和下一个状态$s_{t+1}$
\STATE 存储transition即$(s_t,a_t,r_t,s_{t+1})$到经验回放$D$中
\STATE 更新环境状态$s_{t+1} \leftarrow s_t$
- \STATE 待完善
+ \STATE {\bfseries 更新soft Q函数参数:}
+ \STATE 对于每个$s^{(i)}_{t+1}$采样$\left\{\mathbf{a}^{(i, j)}\right\}_{j=0}^{M} \sim q_{\mathbf{a}^{\prime}}$
+ \STATE 计算empirical soft values $V_{\mathrm{soft}}^{\theta}\left(\mathbf{s}_{t}\right)$\footnotemark[1]
+ \STATE 计算empirical gradient $J_{Q}(\theta)$\footnotemark[2]
+ \STATE 根据$J_{Q}(\theta)$使用ADAM更新参数$\theta$
+ \STATE {\bfseries 更新策略:}
+ \STATE 对于每个$s^{(i)}_{t}$采样$\left\{\xi^{(i, j)}\right\}_{j=0}^{M} \sim \mathcal{N}(\mathbf{0}, \boldsymbol{I})$
+ \STATE 计算$\mathbf{a}_{t}^{(i, j)}=f^{\phi}\left(\xi^{(i, j)}, \mathbf{s}_{t}^{(i)}\right)$
+ \STATE 使用经验估计计算$\Delta f^{\phi}\left(\cdot ; \mathbf{s}_{t}\right)$\footnotemark[3]
+ \STATE 计算经验估计$\frac{\partial J_{\pi}\left(\phi ; \mathbf{s}_{t}\right)}{\partial \phi} \propto \mathbb{E}_{\xi}\left[\Delta f^{\phi}\left(\xi ; \mathbf{s}_{t}\right) \frac{\partial f^{\phi}\left(\xi ; \mathbf{s}_{t}\right)}{\partial \phi}\right]$,即$\hat{\nabla}_{\phi} J_{\pi}$
+ \STATE 根据$\hat{\nabla}_{\phi} J_{\pi}$使用ADAM更新参数$\phi$
+ \STATE
\ENDFOR
- \ENDFOR
-
+ \STATE 每$C$个回合复制参数$\bar{\theta} \leftarrow \theta, \bar{\phi} \leftarrow \phi$
+ \ENDFOR
\end{algorithmic}
\end{algorithm}
-
+\footnotetext[1]{$V_{\mathrm{soft}}^{\theta}\left(\mathbf{s}_{t}\right)=\alpha \log \mathbb{E}_{q_{\mathbf{a}^{\prime}}}\left[\frac{\exp \left(\frac{1}{\alpha} Q_{\mathrm{soft}}^{\theta}\left(\mathbf{s}_{t}, \mathbf{a}^{\prime}\right)\right)}{q_{\mathbf{a}^{\prime}}\left(\mathbf{a}^{\prime}\right)}\right]$}
+\footnotetext[2]{$J_{Q}(\theta)=\mathbb{E}_{\mathbf{s}_{t} \sim q_{\mathbf{s}_{t}}, \mathbf{a}_{t} \sim q_{\mathbf{a}_{t}}}\left[\frac{1}{2}\left(\hat{Q}_{\mathrm{soft}}^{\bar{\theta}}\left(\mathbf{s}_{t}, \mathbf{a}_{t}\right)-Q_{\mathrm{soft}}^{\theta}\left(\mathbf{s}_{t}, \mathbf{a}_{t}\right)\right)^{2}\right]$}
+\footnotetext[3]{$\begin{aligned} \Delta f^{\phi}\left(\cdot ; \mathbf{s}_{t}\right)=& \mathbb{E}_{\mathbf{a}_{t} \sim \pi^{\phi}}\left[\left.\kappa\left(\mathbf{a}_{t}, f^{\phi}\left(\cdot ; \mathbf{s}_{t}\right)\right) \nabla_{\mathbf{a}^{\prime}} Q_{\mathrm{soft}}^{\theta}\left(\mathbf{s}_{t}, \mathbf{a}^{\prime}\right)\right|_{\mathbf{a}^{\prime}=\mathbf{a}_{t}}\right.\\ &\left.+\left.\alpha \nabla_{\mathbf{a}^{\prime}} \kappa\left(\mathbf{a}^{\prime}, f^{\phi}\left(\cdot ; \mathbf{s}_{t}\right)\right)\right|_{\mathbf{a}^{\prime}=\mathbf{a}_{t}}\right] \end{aligned}$}
+\clearpage
+\section{SAC算法}
+\begin{algorithm}[H] % [H]固定位置
+ \floatname{algorithm}{{Soft Actor Critic算法}}
+ \renewcommand{\thealgorithm}{} % 去掉算法标号
+ \caption{}
+ \begin{algorithmic}[1]
+ \STATE 初始化两个Actor的网络参数$\theta_1,\theta_2$以及一个Critic网络参数$\phi$ % 初始化
+ \STATE 复制参数到目标网络$\bar{\theta_1} \leftarrow \theta_1,\bar{\theta_2} \leftarrow \theta_2,$
+ \STATE 初始化经验回放$D$
+ \FOR {回合数 = $1,M$}
+ \STATE 重置环境,获得初始状态$s_t$
+ \FOR {时步 = $1,t$}
+ \STATE 根据$\boldsymbol{a}_{t} \sim \pi_{\phi}\left(\boldsymbol{a}_{t} \mid \mathbf{s}_{t}\right)$采样动作$a_t$
+ \STATE 环境反馈奖励和下一个状态,$\mathbf{s}_{t+1} \sim p\left(\mathbf{s}_{t+1} \mid \mathbf{s}_{t}, \mathbf{a}_{t}\right)$
+ \STATE 存储transition到经验回放中,$\mathcal{D} \leftarrow \mathcal{D} \cup\left\{\left(\mathbf{s}_{t}, \mathbf{a}_{t}, r\left(\mathbf{s}_{t}, \mathbf{a}_{t}\right), \mathbf{s}_{t+1}\right)\right\}$
+ \STATE 更新环境状态$s_{t+1} \leftarrow s_t$
+ \STATE {\bfseries 更新策略:}
+ \STATE 更新$Q$函数,$\theta_{i} \leftarrow \theta_{i}-\lambda_{Q} \hat{\nabla}_{\theta_{i}} J_{Q}\left(\theta_{i}\right)$ for $i \in\{1,2\}$\footnotemark[1]\footnotemark[2]
+ \STATE 更新策略权重,$\phi \leftarrow \phi-\lambda_{\pi} \hat{\nabla}_{\phi} J_{\pi}(\phi)$ \footnotemark[3]
+ \STATE 调整temperature,$\alpha \leftarrow \alpha-\lambda \hat{\nabla}_{\alpha} J(\alpha)$ \footnotemark[4]
+ \STATE 更新目标网络权重,$\bar{\theta}_{i} \leftarrow \tau \theta_{i}+(1-\tau) \bar{\theta}_{i}$ for $i \in\{1,2\}$
+ \ENDFOR
+ \ENDFOR
+ \end{algorithmic}
+
+\end{algorithm}
+\footnotetext[1]{$J_{Q}(\theta)=\mathbb{E}_{\left(\mathbf{s}_{t}, \mathbf{a}_{t}\right) \sim \mathcal{D}}\left[\frac{1}{2}\left(Q_{\theta}\left(\mathbf{s}_{t}, \mathbf{a}_{t}\right)-\left(r\left(\mathbf{s}_{t}, \mathbf{a}_{t}\right)+\gamma \mathbb{E}_{\mathbf{s}_{t+1} \sim p}\left[V_{\bar{\theta}}\left(\mathbf{s}_{t+1}\right)\right]\right)\right)^{2}\right]$}
+\footnotetext[2]{$\hat{\nabla}_{\theta} J_{Q}(\theta)=\nabla_{\theta} Q_{\theta}\left(\mathbf{a}_{t}, \mathbf{s}_{t}\right)\left(Q_{\theta}\left(\mathbf{s}_{t}, \mathbf{a}_{t}\right)-\left(r\left(\mathbf{s}_{t}, \mathbf{a}_{t}\right)+\gamma\left(Q_{\bar{\theta}}\left(\mathbf{s}_{t+1}, \mathbf{a}_{t+1}\right)-\alpha \log \left(\pi_{\phi}\left(\mathbf{a}_{t+1} \mid \mathbf{s}_{t+1}\right)\right)\right)\right)\right.$}
+\footnotetext[3]{$\hat{\nabla}_{\phi} J_{\pi}(\phi)=\nabla_{\phi} \alpha \log \left(\pi_{\phi}\left(\mathbf{a}_{t} \mid \mathbf{s}_{t}\right)\right)+\left(\nabla_{\mathbf{a}_{t}} \alpha \log \left(\pi_{\phi}\left(\mathbf{a}_{t} \mid \mathbf{s}_{t}\right)\right)-\nabla_{\mathbf{a}_{t}} Q\left(\mathbf{s}_{t}, \mathbf{a}_{t}\right)\right) \nabla_{\phi} f_{\phi}\left(\epsilon_{t} ; \mathbf{s}_{t}\right)$,$\mathbf{a}_{t}=f_{\phi}\left(\epsilon_{t} ; \mathbf{s}_{t}\right)$}
+\footnotetext[4]{$J(\alpha)=\mathbb{E}_{\mathbf{a}_{t} \sim \pi_{t}}\left[-\alpha \log \pi_{t}\left(\mathbf{a}_{t} \mid \mathbf{s}_{t}\right)-\alpha \overline{\mathcal{H}}\right]$}
+\clearpage
\end{document}
\ No newline at end of file
diff --git a/projects/assets/pseudocodes/pseudocodes.toc b/projects/assets/pseudocodes/pseudocodes.toc
new file mode 100644
index 0000000..85e0526
--- /dev/null
+++ b/projects/assets/pseudocodes/pseudocodes.toc
@@ -0,0 +1,7 @@
+\contentsline {section}{\numberline {1}模版备用}{2}{section.1}%
+\contentsline {section}{\numberline {2}Q learning算法}{3}{section.2}%
+\contentsline {section}{\numberline {3}Sarsa算法}{4}{section.3}%
+\contentsline {section}{\numberline {4}Policy Gradient算法}{5}{section.4}%
+\contentsline {section}{\numberline {5}DQN算法}{6}{section.5}%
+\contentsline {section}{\numberline {6}SoftQ算法}{7}{section.6}%
+\contentsline {section}{\numberline {7}SAC算法}{8}{section.7}%
diff --git a/projects/codes/DQN/README.md b/projects/codes/DQN/README.md
deleted file mode 100644
index 33e7397..0000000
--- a/projects/codes/DQN/README.md
+++ /dev/null
@@ -1,218 +0,0 @@
-# DQN
-
-## 原理简介
-
-DQN是Q-leanning算法的优化和延伸,Q-leaning中使用有限的Q表存储值的信息,而DQN中则用神经网络替代Q表存储信息,这样更适用于高维的情况,相关知识基础可参考[datawhale李宏毅笔记-Q学习](https://datawhalechina.github.io/easy-rl/#/chapter6/chapter6)。
-
-论文方面主要可以参考两篇,一篇就是2013年谷歌DeepMind团队的[Playing Atari with Deep Reinforcement Learning](https://www.cs.toronto.edu/~vmnih/docs/dqn.pdf),一篇是也是他们团队后来在Nature杂志上发表的[Human-level control through deep reinforcement learning](https://web.stanford.edu/class/psych209/Readings/MnihEtAlHassibis15NatureControlDeepRL.pdf)。后者在算法层面增加target q-net,也可以叫做Nature DQN。
-
-Nature DQN使用了两个Q网络,一个当前Q网络𝑄用来选择动作,更新模型参数,另一个目标Q网络𝑄′用于计算目标Q值。目标Q网络的网络参数不需要迭代更新,而是每隔一段时间从当前Q网络𝑄复制过来,即延时更新,这样可以减少目标Q值和当前的Q值相关性。
-
-要注意的是,两个Q网络的结构是一模一样的。这样才可以复制网络参数。Nature DQN和[Playing Atari with Deep Reinforcement Learning](https://www.cs.toronto.edu/~vmnih/docs/dqn.pdf)相比,除了用一个新的相同结构的目标Q网络来计算目标Q值以外,其余部分基本是完全相同的。细节也可参考[强化学习(九)Deep Q-Learning进阶之Nature DQN](https://www.cnblogs.com/pinard/p/9756075.html)。
-
-https://blog.csdn.net/JohnJim0/article/details/109557173)
-
-## 伪代码
-
-
-
-## 代码实现
-
-### RL接口
-
-首先是强化学习训练的基本接口,即通用的训练模式:
-```python
-for i_episode in range(MAX_EPISODES):
- state = env.reset() # reset环境状态
- for i_step in range(MAX_STEPS):
- action = agent.choose_action(state) # 根据当前环境state选择action
- next_state, reward, done, _ = env.step(action) # 更新环境参数
- agent.memory.push(state, action, reward, next_state, done) # 将state等这些transition存入memory
- agent.update() # 每步更新网络
- state = next_state # 跳转到下一个状态
- if done:
- break
-```
-每个episode加一个MAX_STEPS,也可以使用while not done, 加这个max_steps有时是因为比如gym环境训练目标就是在200个step下达到200的reward,或者是当完成一个episode的步数较多时也可以设置,基本流程跟所有伪代码一致,如下:
-1. agent选择动作
-2. 环境根据agent的动作反馈出next_state和reward
-3. agent进行更新,如有memory就会将transition(包含state,reward,action等)存入memory中
-4. 跳转到下一个状态
-5. 如果done了,就跳出循环,进行下一个episode的训练。
-
-想要实现完整的算法还需要创建Qnet,Replaybuffer等类
-
-### 两个Q网络
-
-上文讲了Nature DQN中有两个Q网络,一个是policy_net,一个是延时更新的target_net,两个网络的结构是一模一样的,如下(见```model.py```),注意DQN使用的Qnet就是全连接网络即FCH:
-```python
-import torch.nn as nn
-import torch.nn.functional as F
-
-class FCN(nn.Module):
- def __init__(self, n_states=4, n_actions=18):
- """ 初始化q网络,为全连接网络
- n_states: 输入的feature即环境的state数目
- n_actions: 输出的action总个数
- """
- super(FCN, self).__init__()
- self.fc1 = nn.Linear(n_states, 128) # 输入层
- self.fc2 = nn.Linear(128, 128) # 隐藏层
- self.fc3 = nn.Linear(128, n_actions) # 输出层
-
- def forward(self, x):
- # 各层对应的激活函数
- x = F.relu(self.fc1(x))
- x = F.relu(self.fc2(x))
- return self.fc3(x)
-```
-输入为n_states,输出为n_actions,包含一个128维度的隐藏层,这里根据需要可增加隐藏层维度和数量,然后一般使用relu激活函数,这里跟深度学习的网路设置是一样的。
-
-### Replay Buffer
-
-然后就是Replay Memory了,其作用主要是是克服经验数据的相关性(correlated data)和非平稳分布(non-stationary distribution)问题,实现如下(见```memory.py```):
-
-```python
-import random
-import numpy as np
-
-class ReplayBuffer:
-
- def __init__(self, capacity):
- 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 = zip(*batch)
- return state, action, reward, next_state, done
-
- def __len__(self):
- return len(self.buffer)
-```
-
-参数capacity表示buffer的容量,主要包括push和sample两个步骤,push是将transitions放到memory中,sample是从memory随机抽取一些transition。
-
-### Agent类
-
-在```agent.py```中我们定义强化学习算法类,包括```choose_action```(选择动作,使用e-greedy策略时会多一个```predict```函数,下面会将到)和```update```(更新)等函数。
-
-在类中建立两个网络,以及optimizer和memory,
-
-```python
-self.policy_net = MLP(n_states, n_actions,hidden_dim=cfg.hidden_dim).to(self.device)
-self.target_net = MLP(n_states, n_actions,hidden_dim=cfg.hidden_dim).to(self.device)
-for target_param, param in zip(self.target_net.parameters(),self.policy_net.parameters()): # copy params from policy net
- target_param.data.copy_(param.data)
-self.optimizer = optim.Adam(self.policy_net.parameters(), lr=cfg.lr)
-self.memory = ReplayBuffer(cfg.memory_capacity)
-```
-然后是选择action:
-
-```python
-def choose_action(self, state):
- '''选择动作
- '''
- self.frame_idx += 1
- if random.random() > self.epsilon(self.frame_idx):
- action = self.predict(state)
- else:
- action = random.randrange(self.n_actions)
- return action
-```
-
-这里使用e-greedy策略,即设置一个参数epsilon,如果生成的随机数大于epsilon,就根据网络预测的选择action,否则还是随机选择action,这个epsilon是会逐渐减小的,可以使用线性或者指数减小的方式,但不会减小到零,这样在训练稳定时还能保持一定的探索,这部分可以学习探索与利用(exploration and exploition)相关知识。
-
-上面讲到的预测函数其实就是根据state选取q值最大的action,如下:
-
-```python
-def predict(self,state):
- with torch.no_grad():
- state = torch.tensor([state], device=self.device, dtype=torch.float32)
- q_values = self.policy_net(state)
- action = q_values.max(1)[1].item()
-```
-
-然后是更新函数了:
-
-```python
-def update(self):
-
- if len(self.memory) < self.batch_size:
- return
- # 从memory中随机采样transition
- state_batch, action_batch, reward_batch, next_state_batch, done_batch = self.memory.sample(
- self.batch_size)
- '''转为张量
- 例如tensor([[-4.5543e-02, -2.3910e-01, 1.8344e-02, 2.3158e-01],...,[-1.8615e-02, -2.3921e-01, -1.1791e-02, 2.3400e-01]])'''
- state_batch = torch.tensor(
- state_batch, device=self.device, dtype=torch.float)
- action_batch = torch.tensor(action_batch, device=self.device).unsqueeze(
- 1) # 例如tensor([[1],...,[0]])
- reward_batch = torch.tensor(
- reward_batch, device=self.device, dtype=torch.float) # tensor([1., 1.,...,1])
- next_state_batch = torch.tensor(
- next_state_batch, device=self.device, dtype=torch.float)
- done_batch = torch.tensor(np.float32(
- done_batch), device=self.device)
-
- '''计算当前(s_t,a)对应的Q(s_t, a)'''
- '''torch.gather:对于a=torch.Tensor([[1,2],[3,4]]),那么a.gather(1,torch.Tensor([[0],[1]]))=torch.Tensor([[1],[3]])'''
- q_values = self.policy_net(state_batch).gather(
- dim=1, index=action_batch) # 等价于self.forward
- # 计算所有next states的V(s_{t+1}),即通过target_net中选取reward最大的对应states
- next_q_values = self.target_net(next_state_batch).max(
- 1)[0].detach() # 比如tensor([ 0.0060, -0.0171,...,])
- # 计算 expected_q_value
- # 对于终止状态,此时done_batch[0]=1, 对应的expected_q_value等于reward
- expected_q_values = reward_batch + \
- self.gamma * next_q_values * (1-done_batch)
- # self.loss = F.smooth_l1_loss(q_values,expected_q_values.unsqueeze(1)) # 计算 Huber loss
- loss = nn.MSELoss()(q_values, expected_q_values.unsqueeze(1)) # 计算 均方误差loss
- # 优化模型
- self.optimizer.zero_grad() # zero_grad清除上一步所有旧的gradients from the last step
- # loss.backward()使用backpropagation计算loss相对于所有parameters(需要gradients)的微分
- loss.backward()
- # for param in self.policy_net.parameters(): # clip防止梯度爆炸
- # param.grad.data.clamp_(-1, 1)
- self.optimizer.step() # 更新模型
-```
-
-更新遵循伪代码的以下部分:
-
-
-
-首先从replay buffer中选取一个batch的数据,计算loss,然后进行minibatch SGD。
-
-然后是保存与加载模型的部分,如下:
-
-```python
-def save(self, path):
- torch.save(self.target_net.state_dict(), path+'dqn_checkpoint.pth')
-def load(self, path):
- self.target_net.load_state_dict(torch.load(path+'dqn_checkpoint.pth'))
- for target_param, param in zip(self.target_net.parameters(), self.policy_net.parameters()):
- param.data.copy_(target_param.data)
-```
-
-
-
-### 实验结果
-
-训练结果如下:
-
-
-
-
-
-## 参考
-
-[with torch.no_grad()](https://www.jianshu.com/p/1cea017f5d11)
-
diff --git a/projects/codes/DQN/assets/eval_rewards_curve.png b/projects/codes/DQN/assets/eval_rewards_curve.png
deleted file mode 100644
index 0327b47..0000000
Binary files a/projects/codes/DQN/assets/eval_rewards_curve.png and /dev/null differ
diff --git a/projects/codes/DQN/assets/image-20210507162813393.png b/projects/codes/DQN/assets/image-20210507162813393.png
deleted file mode 100644
index 3c4ae33..0000000
Binary files a/projects/codes/DQN/assets/image-20210507162813393.png and /dev/null differ
diff --git a/projects/codes/DQN/assets/rewards_curve_train.png b/projects/codes/DQN/assets/rewards_curve_train.png
deleted file mode 100644
index a077d9d..0000000
Binary files a/projects/codes/DQN/assets/rewards_curve_train.png and /dev/null differ
diff --git a/projects/codes/DQN/assets/train_rewards_curve.png b/projects/codes/DQN/assets/train_rewards_curve.png
deleted file mode 100644
index b9667f1..0000000
Binary files a/projects/codes/DQN/assets/train_rewards_curve.png and /dev/null differ
diff --git a/projects/codes/DQN/assets/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0pvaG5KaW0w,size_16,color_FFFFFF,t_70.png b/projects/codes/DQN/assets/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0pvaG5KaW0w,size_16,color_FFFFFF,t_70.png
deleted file mode 100644
index c55ac87..0000000
Binary files a/projects/codes/DQN/assets/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0pvaG5KaW0w,size_16,color_FFFFFF,t_70.png and /dev/null differ
diff --git a/projects/codes/DQN/dqn.py b/projects/codes/DQN/dqn.py
index 2b28757..de071cc 100644
--- a/projects/codes/DQN/dqn.py
+++ b/projects/codes/DQN/dqn.py
@@ -5,7 +5,7 @@
@Email: johnjim0816@gmail.com
@Date: 2020-06-12 00:50:49
@LastEditor: John
-LastEditTime: 2022-08-11 09:52:23
+LastEditTime: 2022-08-18 14:27:18
@Discription:
@Environment: python 3.7.7
'''
@@ -23,10 +23,10 @@ class DQN:
def __init__(self,n_actions,model,memory,cfg):
self.n_actions = n_actions
- self.device = torch.device(cfg.device) # cpu or cuda
- self.gamma = cfg.gamma # 奖励的折扣因子
- # e-greedy策略相关参数
- self.sample_count = 0 # 用于epsilon的衰减计数
+ self.device = torch.device(cfg.device)
+ self.gamma = cfg.gamma
+ ## e-greedy parameters
+ self.sample_count = 0 # sample count for epsilon decay
self.epsilon = cfg.epsilon_start
self.sample_count = 0
self.epsilon_start = cfg.epsilon_start
@@ -35,61 +35,78 @@ class DQN:
self.batch_size = cfg.batch_size
self.policy_net = model.to(self.device)
self.target_net = model.to(self.device)
- for target_param, param in zip(self.target_net.parameters(),self.policy_net.parameters()): # 复制参数到目标网路targe_net
+ ## copy parameters from policy net to target net
+ for target_param, param in zip(self.target_net.parameters(),self.policy_net.parameters()):
target_param.data.copy_(param.data)
- self.optimizer = optim.Adam(self.policy_net.parameters(), lr=cfg.lr) # 优化器
- self.memory = memory # 经验回放
+ # self.target_net.load_state_dict(self.policy_net.state_dict()) # or use this to copy parameters
+ self.optimizer = optim.Adam(self.policy_net.parameters(), lr=cfg.lr)
+ self.memory = memory
+ self.update_flag = False
- def sample(self, state):
- ''' 选择动作
+ def sample_action(self, state):
+ ''' sample action with e-greedy policy
'''
self.sample_count += 1
+ # epsilon must decay(linear,exponential and etc.) for balancing exploration and exploitation
self.epsilon = self.epsilon_end + (self.epsilon_start - self.epsilon_end) * \
- math.exp(-1. * self.sample_count / self.epsilon_decay) # epsilon是会递减的,这里选择指数递减
+ math.exp(-1. * self.sample_count / self.epsilon_decay)
if random.random() > self.epsilon:
with torch.no_grad():
state = torch.tensor(state, device=self.device, dtype=torch.float32).unsqueeze(dim=0)
q_values = self.policy_net(state)
- action = q_values.max(1)[1].item() # 选择Q值最大的动作
+ action = q_values.max(1)[1].item() # choose action corresponding to the maximum q value
else:
action = random.randrange(self.n_actions)
return action
- def predict(self,state):
+ def predict_action(self,state):
+ ''' predict action
+ '''
with torch.no_grad():
state = torch.tensor(state, device=self.device, dtype=torch.float32).unsqueeze(dim=0)
q_values = self.policy_net(state)
- action = q_values.max(1)[1].item() # 选择Q值最大的动作
+ action = q_values.max(1)[1].item() # choose action corresponding to the maximum q value
return action
def update(self):
- if len(self.memory) < self.batch_size: # 当memory中不满足一个批量时,不更新策略
+ if len(self.memory) < self.batch_size: # when transitions in memory donot meet a batch, not update
return
- # 从经验回放中(replay memory)中随机采样一个批量的转移(transition)
-
+ else:
+ if not self.update_flag:
+ print("begin to update!")
+ self.update_flag = True
+ # sample a batch of transitions from replay buffer
state_batch, action_batch, reward_batch, next_state_batch, done_batch = self.memory.sample(
self.batch_size)
- state_batch = torch.tensor(np.array(state_batch), device=self.device, dtype=torch.float)
- action_batch = torch.tensor(action_batch, device=self.device).unsqueeze(1)
- reward_batch = torch.tensor(reward_batch, device=self.device, dtype=torch.float)
- next_state_batch = torch.tensor(np.array(next_state_batch), device=self.device, dtype=torch.float)
- done_batch = torch.tensor(np.float32(done_batch), device=self.device)
- q_values = self.policy_net(state_batch).gather(dim=1, index=action_batch) # 计算当前状态(s_t,a)对应的Q(s_t, a)
- next_q_values = self.target_net(next_state_batch).max(1)[0].detach() # 计算下一时刻的状态(s_t_,a)对应的Q值
- # 计算期望的Q值,对于终止状态,此时done_batch[0]=1, 对应的expected_q_value等于reward
- expected_q_values = reward_batch + self.gamma * next_q_values * (1-done_batch)
- loss = nn.MSELoss()(q_values, expected_q_values.unsqueeze(1)) # 计算均方根损失
- # 优化更新模型
+ state_batch = torch.tensor(np.array(state_batch), device=self.device, dtype=torch.float) # shape(batchsize,n_states)
+ action_batch = torch.tensor(action_batch, device=self.device).unsqueeze(1) # shape(batchsize,1)
+ reward_batch = torch.tensor(reward_batch, device=self.device, dtype=torch.float).unsqueeze(1) # shape(batchsize)
+ next_state_batch = torch.tensor(np.array(next_state_batch), device=self.device, dtype=torch.float) # shape(batchsize,n_states)
+ done_batch = torch.tensor(np.float32(done_batch), device=self.device).unsqueeze(1) # shape(batchsize,1)
+ # print(state_batch.shape,action_batch.shape,reward_batch.shape,next_state_batch.shape,done_batch.shape)
+ # compute current Q(s_t,a), it is 'y_j' in pseucodes
+ q_value_batch = self.policy_net(state_batch).gather(dim=1, index=action_batch) # shape(batchsize,1),requires_grad=True
+ # print(q_values.requires_grad)
+ # compute max(Q(s_t+1,A_t+1)) respects to actions A, next_max_q_value comes from another net and is just regarded as constant for q update formula below, thus should detach to requires_grad=False
+ next_max_q_value_batch = self.target_net(next_state_batch).max(1)[0].detach().unsqueeze(1)
+ # print(q_values.shape,next_q_values.shape)
+ # compute expected q value, for terminal state, done_batch[0]=1, and expected_q_value=rewardcorrespondingly
+ expected_q_value_batch = reward_batch + self.gamma * next_max_q_value_batch* (1-done_batch)
+ # print(expected_q_value_batch.shape,expected_q_value_batch.requires_grad)
+ loss = nn.MSELoss()(q_value_batch, expected_q_value_batch) # shape same to
+ # backpropagation
self.optimizer.zero_grad()
loss.backward()
- for param in self.policy_net.parameters(): # clip防止梯度爆炸
+ # clip to avoid gradient explosion
+ for param in self.policy_net.parameters():
param.grad.data.clamp_(-1, 1)
self.optimizer.step()
- def save(self, path):
+ def save_model(self, path):
from pathlib import Path
+ # create path
Path(path).mkdir(parents=True, exist_ok=True)
- torch.save(self.target_net.state_dict(), path+'checkpoint.pth')
+ torch.save(self.target_net.state_dict(), f"{path}/checkpoint.pt")
- def load(self, path):
- self.target_net.load_state_dict(torch.load(path+'checkpoint.pth'))
+ def load_model(self, path):
+ self.target_net.load_state_dict(torch.load(f"{path}/checkpoint.pt"))
for target_param, param in zip(self.target_net.parameters(), self.policy_net.parameters()):
param.data.copy_(target_param.data)
diff --git a/projects/codes/DQN/outputs/CartPole-v0/20220815-185119/models/checkpoint.pth b/projects/codes/DQN/outputs/CartPole-v0/20220815-185119/models/checkpoint.pth
deleted file mode 100644
index 8172745..0000000
Binary files a/projects/codes/DQN/outputs/CartPole-v0/20220815-185119/models/checkpoint.pth and /dev/null differ
diff --git a/projects/codes/DQN/outputs/CartPole-v0/20220815-185119/results/params.json b/projects/codes/DQN/outputs/CartPole-v0/20220815-185119/results/params.json
deleted file mode 100644
index 7749c42..0000000
--- a/projects/codes/DQN/outputs/CartPole-v0/20220815-185119/results/params.json
+++ /dev/null
@@ -1 +0,0 @@
-{"algo_name": "DQN", "env_name": "CartPole-v0", "train_eps": 200, "test_eps": 20, "gamma": 0.95, "epsilon_start": 0.95, "epsilon_end": 0.01, "epsilon_decay": 500, "lr": 0.0001, "memory_capacity": 100000, "batch_size": 64, "target_update": 4, "hidden_dim": 256, "device": "cpu", "result_path": "/Users/jj/Desktop/rl-tutorials/codes/DQN/outputs/CartPole-v0/20220815-185119/results/", "model_path": "/Users/jj/Desktop/rl-tutorials/codes/DQN/outputs/CartPole-v0/20220815-185119/models/", "show_fig": false, "save_fig": true}
\ No newline at end of file
diff --git a/projects/codes/DQN/outputs/CartPole-v0/20220815-185119/results/test_rewards.npy b/projects/codes/DQN/outputs/CartPole-v0/20220815-185119/results/test_rewards.npy
deleted file mode 100644
index 14bca8b..0000000
Binary files a/projects/codes/DQN/outputs/CartPole-v0/20220815-185119/results/test_rewards.npy and /dev/null differ
diff --git a/projects/codes/DQN/outputs/CartPole-v0/20220815-185119/results/train_rewards.npy b/projects/codes/DQN/outputs/CartPole-v0/20220815-185119/results/train_rewards.npy
deleted file mode 100644
index b96ce50..0000000
Binary files a/projects/codes/DQN/outputs/CartPole-v0/20220815-185119/results/train_rewards.npy and /dev/null differ
diff --git a/projects/codes/DQN/outputs/CartPole-v0/20220815-185119/results/training_curve.png b/projects/codes/DQN/outputs/CartPole-v0/20220815-185119/results/training_curve.png
deleted file mode 100644
index 3e09a74..0000000
Binary files a/projects/codes/DQN/outputs/CartPole-v0/20220815-185119/results/training_curve.png and /dev/null differ
diff --git a/projects/codes/DQN/outputs/CartPole-v0/20220818-143132/models/checkpoint.pt b/projects/codes/DQN/outputs/CartPole-v0/20220818-143132/models/checkpoint.pt
new file mode 100644
index 0000000..c7455d1
Binary files /dev/null and b/projects/codes/DQN/outputs/CartPole-v0/20220818-143132/models/checkpoint.pt differ
diff --git a/projects/codes/DQN/outputs/CartPole-v0/20220818-143132/results/params.json b/projects/codes/DQN/outputs/CartPole-v0/20220818-143132/results/params.json
new file mode 100644
index 0000000..dbd1ff7
--- /dev/null
+++ b/projects/codes/DQN/outputs/CartPole-v0/20220818-143132/results/params.json
@@ -0,0 +1 @@
+{"algo_name": "DQN", "env_name": "CartPole-v0", "train_eps": 200, "test_eps": 20, "gamma": 0.95, "epsilon_start": 0.95, "epsilon_end": 0.01, "epsilon_decay": 500, "lr": 0.0001, "memory_capacity": 100000, "batch_size": 64, "target_update": 4, "hidden_dim": 256, "device": "cpu", "seed": 10, "result_path": "/Users/jj/Desktop/rl-tutorials/codes/DQN/outputs/CartPole-v0/20220818-143132/results", "model_path": "/Users/jj/Desktop/rl-tutorials/codes/DQN/outputs/CartPole-v0/20220818-143132/models", "show_fig": false, "save_fig": true}
\ No newline at end of file
diff --git a/projects/codes/DQN/outputs/CartPole-v0/20220815-185119/results/testing_curve.png b/projects/codes/DQN/outputs/CartPole-v0/20220818-143132/results/testing_curve.png
similarity index 100%
rename from projects/codes/DQN/outputs/CartPole-v0/20220815-185119/results/testing_curve.png
rename to projects/codes/DQN/outputs/CartPole-v0/20220818-143132/results/testing_curve.png
diff --git a/projects/codes/DQN/outputs/CartPole-v0/20220818-143132/results/testing_results.csv b/projects/codes/DQN/outputs/CartPole-v0/20220818-143132/results/testing_results.csv
new file mode 100644
index 0000000..fb73fd6
--- /dev/null
+++ b/projects/codes/DQN/outputs/CartPole-v0/20220818-143132/results/testing_results.csv
@@ -0,0 +1,21 @@
+episodes,rewards
+0,200.0
+1,200.0
+2,200.0
+3,200.0
+4,200.0
+5,200.0
+6,200.0
+7,200.0
+8,200.0
+9,200.0
+10,200.0
+11,200.0
+12,200.0
+13,200.0
+14,200.0
+15,200.0
+16,200.0
+17,200.0
+18,200.0
+19,200.0
diff --git a/projects/codes/DQN/outputs/CartPole-v0/20220818-143132/results/training_curve.png b/projects/codes/DQN/outputs/CartPole-v0/20220818-143132/results/training_curve.png
new file mode 100644
index 0000000..0e7b997
Binary files /dev/null and b/projects/codes/DQN/outputs/CartPole-v0/20220818-143132/results/training_curve.png differ
diff --git a/projects/codes/DQN/outputs/CartPole-v0/20220818-143132/results/training_results.csv b/projects/codes/DQN/outputs/CartPole-v0/20220818-143132/results/training_results.csv
new file mode 100644
index 0000000..4429b6a
--- /dev/null
+++ b/projects/codes/DQN/outputs/CartPole-v0/20220818-143132/results/training_results.csv
@@ -0,0 +1,201 @@
+episodes,rewards
+0,38.0
+1,16.0
+2,37.0
+3,15.0
+4,22.0
+5,34.0
+6,20.0
+7,12.0
+8,16.0
+9,14.0
+10,13.0
+11,21.0
+12,14.0
+13,12.0
+14,17.0
+15,12.0
+16,10.0
+17,14.0
+18,10.0
+19,10.0
+20,16.0
+21,9.0
+22,14.0
+23,13.0
+24,10.0
+25,9.0
+26,12.0
+27,12.0
+28,14.0
+29,11.0
+30,9.0
+31,8.0
+32,9.0
+33,11.0
+34,12.0
+35,10.0
+36,11.0
+37,10.0
+38,10.0
+39,18.0
+40,13.0
+41,15.0
+42,10.0
+43,9.0
+44,14.0
+45,14.0
+46,23.0
+47,17.0
+48,15.0
+49,15.0
+50,20.0
+51,28.0
+52,36.0
+53,36.0
+54,23.0
+55,27.0
+56,53.0
+57,19.0
+58,35.0
+59,62.0
+60,57.0
+61,38.0
+62,61.0
+63,65.0
+64,58.0
+65,43.0
+66,67.0
+67,56.0
+68,91.0
+69,128.0
+70,71.0
+71,126.0
+72,100.0
+73,200.0
+74,200.0
+75,200.0
+76,200.0
+77,200.0
+78,200.0
+79,200.0
+80,200.0
+81,200.0
+82,200.0
+83,200.0
+84,200.0
+85,200.0
+86,200.0
+87,200.0
+88,200.0
+89,200.0
+90,200.0
+91,200.0
+92,200.0
+93,200.0
+94,200.0
+95,200.0
+96,200.0
+97,200.0
+98,200.0
+99,200.0
+100,200.0
+101,200.0
+102,200.0
+103,200.0
+104,200.0
+105,200.0
+106,200.0
+107,200.0
+108,200.0
+109,200.0
+110,200.0
+111,200.0
+112,200.0
+113,200.0
+114,200.0
+115,200.0
+116,200.0
+117,200.0
+118,200.0
+119,200.0
+120,200.0
+121,200.0
+122,200.0
+123,200.0
+124,200.0
+125,200.0
+126,200.0
+127,200.0
+128,200.0
+129,200.0
+130,200.0
+131,200.0
+132,200.0
+133,200.0
+134,200.0
+135,200.0
+136,200.0
+137,200.0
+138,200.0
+139,200.0
+140,200.0
+141,200.0
+142,200.0
+143,200.0
+144,200.0
+145,200.0
+146,200.0
+147,200.0
+148,200.0
+149,200.0
+150,200.0
+151,200.0
+152,200.0
+153,200.0
+154,200.0
+155,200.0
+156,200.0
+157,200.0
+158,200.0
+159,200.0
+160,200.0
+161,200.0
+162,200.0
+163,200.0
+164,200.0
+165,200.0
+166,200.0
+167,200.0
+168,200.0
+169,200.0
+170,200.0
+171,200.0
+172,200.0
+173,200.0
+174,200.0
+175,200.0
+176,200.0
+177,200.0
+178,200.0
+179,200.0
+180,200.0
+181,200.0
+182,200.0
+183,200.0
+184,200.0
+185,200.0
+186,200.0
+187,200.0
+188,200.0
+189,200.0
+190,200.0
+191,200.0
+192,200.0
+193,200.0
+194,200.0
+195,200.0
+196,200.0
+197,200.0
+198,200.0
+199,200.0
diff --git a/projects/codes/DQN/task0.py b/projects/codes/DQN/task0.py
index 8985103..5a6f9a5 100644
--- a/projects/codes/DQN/task0.py
+++ b/projects/codes/DQN/task0.py
@@ -1,23 +1,23 @@
import sys,os
-curr_path = os.path.dirname(os.path.abspath(__file__)) # 当前文件所在绝对路径
-parent_path = os.path.dirname(curr_path) # 父路径
-sys.path.append(parent_path) # 添加路径到系统路径
+curr_path = os.path.dirname(os.path.abspath(__file__)) # current path
+parent_path = os.path.dirname(curr_path) # parent path
+sys.path.append(parent_path) # add path to system path
import gym
import torch
import datetime
import numpy as np
import argparse
-from common.utils import save_results
+from common.utils import save_results,all_seed
from common.utils import plot_rewards,save_args
from common.models import MLP
from common.memories import ReplayBuffer
from dqn import DQN
def get_args():
- """ 超参数
+ """ hyperparameters
"""
- curr_time = datetime.datetime.now().strftime("%Y%m%d-%H%M%S") # 获取当前时间
+ curr_time = datetime.datetime.now().strftime("%Y%m%d-%H%M%S") # obtain current time
parser = argparse.ArgumentParser(description="hyperparameters")
parser.add_argument('--algo_name',default='DQN',type=str,help="name of algorithm")
parser.add_argument('--env_name',default='CartPole-v0',type=str,help="name of environment")
@@ -33,102 +33,101 @@ def get_args():
parser.add_argument('--target_update',default=4,type=int)
parser.add_argument('--hidden_dim',default=256,type=int)
parser.add_argument('--device',default='cpu',type=str,help="cpu or cuda")
+ parser.add_argument('--seed',default=10,type=int,help="seed")
parser.add_argument('--result_path',default=curr_path + "/outputs/" + parser.parse_args().env_name + \
- '/' + curr_time + '/results/' )
+ '/' + curr_time + '/results' )
parser.add_argument('--model_path',default=curr_path + "/outputs/" + parser.parse_args().env_name + \
- '/' + curr_time + '/models/' )
+ '/' + curr_time + '/models' )
parser.add_argument('--show_fig',default=False,type=bool,help="if show figure or not")
parser.add_argument('--save_fig',default=True,type=bool,help="if save figure or not")
args = parser.parse_args()
return args
-def env_agent_config(cfg,seed=1):
- ''' 创建环境和智能体
+def env_agent_config(cfg):
+ ''' create env and agent
'''
- env = gym.make(cfg.env_name) # 创建环境
- n_states = env.observation_space.shape[0] # 状态维度
- n_actions = env.action_space.n # 动作维度
- print(f"状态数:{n_states},动作数:{n_actions}")
+ env = gym.make(cfg.env_name) # create env
+ if cfg.seed !=0: # set random seed
+ all_seed(env,seed=cfg.seed)
+ n_states = env.observation_space.shape[0] # state dimension
+ n_actions = env.action_space.n # action dimension
+ print(f"state dim: {n_states}, action dim: {n_actions}")
model = MLP(n_states,n_actions,hidden_dim=cfg.hidden_dim)
- memory = ReplayBuffer(cfg.memory_capacity) # 经验回放
- agent = DQN(n_actions,model,memory,cfg) # 创建智能体
- if seed !=0: # 设置随机种子
- torch.manual_seed(seed)
- env.seed(seed)
- np.random.seed(seed)
+ memory = ReplayBuffer(cfg.memory_capacity) # replay buffer
+ agent = DQN(n_actions,model,memory,cfg) # create agent
return env, agent
def train(cfg, env, agent):
''' 训练
'''
- print("开始训练!")
- print(f"回合:{cfg.env_name}, 算法:{cfg.algo_name}, 设备:{cfg.device}")
- rewards = [] # 记录所有回合的奖励
+ print("start training!")
+ print(f"Env: {cfg.env_name}, Algo: {cfg.algo_name}, Device: {cfg.device}")
+ rewards = [] # record rewards for all episodes
steps = []
for i_ep in range(cfg.train_eps):
- ep_reward = 0 # 记录一回合内的奖励
+ ep_reward = 0 # reward per episode
ep_step = 0
- state = env.reset() # 重置环境,返回初始状态
+ state = env.reset() # reset and obtain initial state
while True:
ep_step += 1
- action = agent.sample(state) # 选择动作
- next_state, reward, done, _ = env.step(action) # 更新环境,返回transition
+ action = agent.sample_action(state) # sample action
+ next_state, reward, done, _ = env.step(action) # update env and return transitions
agent.memory.push(state, action, reward,
- next_state, done) # 保存transition
- state = next_state # 更新下一个状态
- agent.update() # 更新智能体
- ep_reward += reward # 累加奖励
+ next_state, done) # save transitions
+ state = next_state # update next state for env
+ agent.update() # update agent
+ ep_reward += reward #
if done:
break
- if (i_ep + 1) % cfg.target_update == 0: # 智能体目标网络更新
+ if (i_ep + 1) % cfg.target_update == 0: # target net update, target_update means "C" in pseucodes
agent.target_net.load_state_dict(agent.policy_net.state_dict())
steps.append(ep_step)
rewards.append(ep_reward)
if (i_ep + 1) % 10 == 0:
- print(f'回合:{i_ep+1}/{cfg.train_eps},奖励:{ep_reward:.2f},Epislon:{agent.epsilon:.3f}')
- print("完成训练!")
+ print(f'Episode: {i_ep+1}/{cfg.train_eps}, Reward: {ep_reward:.2f}: Epislon: {agent.epsilon:.3f}')
+ print("finish training!")
env.close()
- res_dic = {'rewards':rewards}
+ res_dic = {'episodes':range(len(rewards)),'rewards':rewards}
return res_dic
def test(cfg, env, agent):
- print("开始测试!")
- print(f"回合:{cfg.env_name}, 算法:{cfg.algo_name}, 设备:{cfg.device}")
- rewards = [] # 记录所有回合的奖励
+ print("start testing!")
+ print(f"Env: {cfg.env_name}, Algo: {cfg.algo_name}, Device: {cfg.device}")
+ rewards = [] # record rewards for all episodes
steps = []
for i_ep in range(cfg.test_eps):
- ep_reward = 0 # 记录一回合内的奖励
+ ep_reward = 0 # reward per episode
ep_step = 0
- state = env.reset() # 重置环境,返回初始状态
+ state = env.reset() # reset and obtain initial state
while True:
ep_step+=1
- action = agent.predict(state) # 选择动作
- next_state, reward, done, _ = env.step(action) # 更新环境,返回transition
- state = next_state # 更新下一个状态
- ep_reward += reward # 累加奖励
+ action = agent.predict_action(state) # predict action
+ next_state, reward, done, _ = env.step(action)
+ state = next_state
+ ep_reward += reward
if done:
break
steps.append(ep_step)
rewards.append(ep_reward)
- print(f'回合:{i_ep+1}/{cfg.test_eps},奖励:{ep_reward:.2f}')
- print("完成测试")
+ print(f'Episode: {i_ep+1}/{cfg.test_eps},Reward: {ep_reward:.2f}')
+ print("finish testing!")
env.close()
- return {'rewards':rewards}
+ return {'episodes':range(len(rewards)),'rewards':rewards}
if __name__ == "__main__":
cfg = get_args()
- # 训练
+ # training
env, agent = env_agent_config(cfg)
res_dic = train(cfg, env, agent)
- save_args(cfg,path = cfg.result_path) # 保存参数到模型路径上
- agent.save(path = cfg.model_path) # 保存模型
- save_results(res_dic, tag = 'train', path = cfg.result_path)
- plot_rewards(res_dic['rewards'], cfg, path = cfg.result_path,tag = "train")
- # 测试
- env, agent = env_agent_config(cfg) # 也可以不加,加这一行的是为了避免训练之后环境可能会出现问题,因此新建一个环境用于测试
- agent.load(path = cfg.model_path) # 导入模型
+ save_args(cfg,path = cfg.result_path) # save parameters
+ agent.save_model(path = cfg.model_path) # save models
+ save_results(res_dic, tag = 'train', path = cfg.result_path) # save results
+ plot_rewards(res_dic['rewards'], cfg, path = cfg.result_path,tag = "train") # plot results
+ # testing
+ env, agent = env_agent_config(cfg) # create new env for testing, sometimes can ignore this step
+ agent.load_model(path = cfg.model_path) # load model
res_dic = test(cfg, env, agent)
save_results(res_dic, tag='test',
- path = cfg.result_path) # 保存结果
- plot_rewards(res_dic['rewards'], cfg, path = cfg.result_path,tag = "test") # 画出结果
+ path = cfg.result_path)
+ plot_rewards(res_dic['rewards'], cfg, path = cfg.result_path,tag = "test")
diff --git a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/models/pg_checkpoint.pt b/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/models/pg_checkpoint.pt
deleted file mode 100644
index 64c6702..0000000
Binary files a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/models/pg_checkpoint.pt and /dev/null differ
diff --git a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/results/test_ma_rewards.npy b/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/results/test_ma_rewards.npy
deleted file mode 100644
index 343fcc6..0000000
Binary files a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/results/test_ma_rewards.npy and /dev/null differ
diff --git a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/results/test_rewards.npy b/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/results/test_rewards.npy
deleted file mode 100644
index 343fcc6..0000000
Binary files a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/results/test_rewards.npy and /dev/null differ
diff --git a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/results/test_rewards_curve.png b/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/results/test_rewards_curve.png
deleted file mode 100644
index 7ff5198..0000000
Binary files a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/results/test_rewards_curve.png and /dev/null differ
diff --git a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/results/train_ma_rewards.npy b/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/results/train_ma_rewards.npy
deleted file mode 100644
index 8aea751..0000000
Binary files a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/results/train_ma_rewards.npy and /dev/null differ
diff --git a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/results/train_rewards.npy b/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/results/train_rewards.npy
deleted file mode 100644
index 2198ca9..0000000
Binary files a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/results/train_rewards.npy and /dev/null differ
diff --git a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/results/train_rewards_curve.png b/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/results/train_rewards_curve.png
deleted file mode 100644
index 03b4c24..0000000
Binary files a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220210-061325/results/train_rewards_curve.png and /dev/null differ
diff --git a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/models/checkpoint.pt b/projects/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/models/checkpoint.pt
new file mode 100644
index 0000000..2676e7a
Binary files /dev/null and b/projects/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/models/checkpoint.pt differ
diff --git a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/results/params.json b/projects/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/results/params.json
new file mode 100644
index 0000000..0dca316
--- /dev/null
+++ b/projects/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/results/params.json
@@ -0,0 +1,16 @@
+{
+ "algo_name": "PolicyGradient",
+ "env_name": "CartPole-v0",
+ "train_eps": 200,
+ "test_eps": 20,
+ "gamma": 0.99,
+ "lr": 0.005,
+ "update_fre": 8,
+ "hidden_dim": 36,
+ "device": "cpu",
+ "seed": 1,
+ "result_path": "/Users/jj/Desktop/rl-tutorials/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/results/",
+ "model_path": "/Users/jj/Desktop/rl-tutorials/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/models/",
+ "save_fig": true,
+ "show_fig": false
+}
\ No newline at end of file
diff --git a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/results/testing_curve.png b/projects/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/results/testing_curve.png
new file mode 100644
index 0000000..a38dd4b
Binary files /dev/null and b/projects/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/results/testing_curve.png differ
diff --git a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/results/testing_results.csv b/projects/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/results/testing_results.csv
new file mode 100644
index 0000000..958b0ef
--- /dev/null
+++ b/projects/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/results/testing_results.csv
@@ -0,0 +1,21 @@
+episodes,rewards
+0,200.0
+1,200.0
+2,165.0
+3,200.0
+4,200.0
+5,200.0
+6,200.0
+7,200.0
+8,200.0
+9,200.0
+10,200.0
+11,168.0
+12,200.0
+13,200.0
+14,200.0
+15,115.0
+16,198.0
+17,200.0
+18,200.0
+19,200.0
diff --git a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/results/training_curve.png b/projects/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/results/training_curve.png
new file mode 100644
index 0000000..3e0db7c
Binary files /dev/null and b/projects/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/results/training_curve.png differ
diff --git a/projects/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/results/training_results.csv b/projects/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/results/training_results.csv
new file mode 100644
index 0000000..daeb8f2
--- /dev/null
+++ b/projects/codes/PolicyGradient/outputs/CartPole-v0/20220822-174059/results/training_results.csv
@@ -0,0 +1,201 @@
+episodes,rewards
+0,26.0
+1,53.0
+2,10.0
+3,37.0
+4,22.0
+5,21.0
+6,12.0
+7,34.0
+8,38.0
+9,40.0
+10,23.0
+11,14.0
+12,16.0
+13,25.0
+14,15.0
+15,23.0
+16,11.0
+17,28.0
+18,21.0
+19,62.0
+20,33.0
+21,27.0
+22,15.0
+23,17.0
+24,26.0
+25,35.0
+26,26.0
+27,14.0
+28,42.0
+29,45.0
+30,34.0
+31,39.0
+32,31.0
+33,17.0
+34,42.0
+35,41.0
+36,31.0
+37,39.0
+38,28.0
+39,12.0
+40,36.0
+41,33.0
+42,47.0
+43,40.0
+44,63.0
+45,36.0
+46,64.0
+47,79.0
+48,49.0
+49,40.0
+50,65.0
+51,47.0
+52,51.0
+53,30.0
+54,26.0
+55,41.0
+56,86.0
+57,61.0
+58,38.0
+59,200.0
+60,49.0
+61,70.0
+62,61.0
+63,101.0
+64,200.0
+65,152.0
+66,108.0
+67,46.0
+68,72.0
+69,87.0
+70,27.0
+71,126.0
+72,46.0
+73,25.0
+74,14.0
+75,42.0
+76,38.0
+77,55.0
+78,42.0
+79,51.0
+80,67.0
+81,83.0
+82,178.0
+83,115.0
+84,140.0
+85,97.0
+86,85.0
+87,61.0
+88,153.0
+89,200.0
+90,200.0
+91,200.0
+92,200.0
+93,64.0
+94,200.0
+95,200.0
+96,157.0
+97,128.0
+98,160.0
+99,35.0
+100,140.0
+101,113.0
+102,200.0
+103,154.0
+104,200.0
+105,200.0
+106,200.0
+107,198.0
+108,137.0
+109,200.0
+110,200.0
+111,102.0
+112,200.0
+113,200.0
+114,200.0
+115,200.0
+116,148.0
+117,200.0
+118,200.0
+119,200.0
+120,200.0
+121,200.0
+122,194.0
+123,200.0
+124,200.0
+125,200.0
+126,183.0
+127,200.0
+128,200.0
+129,200.0
+130,200.0
+131,200.0
+132,200.0
+133,200.0
+134,200.0
+135,200.0
+136,93.0
+137,96.0
+138,84.0
+139,103.0
+140,79.0
+141,104.0
+142,82.0
+143,105.0
+144,200.0
+145,200.0
+146,171.0
+147,200.0
+148,200.0
+149,200.0
+150,200.0
+151,197.0
+152,133.0
+153,142.0
+154,147.0
+155,156.0
+156,131.0
+157,181.0
+158,163.0
+159,146.0
+160,200.0
+161,176.0
+162,200.0
+163,173.0
+164,177.0
+165,200.0
+166,200.0
+167,200.0
+168,200.0
+169,200.0
+170,200.0
+171,200.0
+172,200.0
+173,200.0
+174,200.0
+175,200.0
+176,200.0
+177,200.0
+178,200.0
+179,200.0
+180,200.0
+181,200.0
+182,200.0
+183,200.0
+184,200.0
+185,200.0
+186,200.0
+187,200.0
+188,200.0
+189,200.0
+190,200.0
+191,200.0
+192,200.0
+193,200.0
+194,200.0
+195,200.0
+196,190.0
+197,200.0
+198,189.0
+199,200.0
diff --git a/projects/codes/PolicyGradient/pg.py b/projects/codes/PolicyGradient/pg.py
index 688895f..8cd8688 100644
--- a/projects/codes/PolicyGradient/pg.py
+++ b/projects/codes/PolicyGradient/pg.py
@@ -5,7 +5,7 @@ Author: John
Email: johnjim0816@gmail.com
Date: 2020-11-22 23:27:44
LastEditor: John
-LastEditTime: 2022-02-10 01:25:27
+LastEditTime: 2022-08-22 17:35:34
Discription:
Environment:
'''
@@ -16,35 +16,27 @@ from torch.distributions import Bernoulli
from torch.autograd import Variable
import numpy as np
-class MLP(nn.Module):
-
- ''' 多层感知机
- 输入:state维度
- 输出:概率
- '''
- def __init__(self,input_dim,hidden_dim = 36):
- super(MLP, self).__init__()
- # 24和36为hidden layer的层数,可根据input_dim, n_actions的情况来改变
- self.fc1 = nn.Linear(input_dim, hidden_dim)
- self.fc2 = nn.Linear(hidden_dim,hidden_dim)
- self.fc3 = nn.Linear(hidden_dim, 1) # Prob of Left
-
- def forward(self, x):
- x = F.relu(self.fc1(x))
- x = F.relu(self.fc2(x))
- x = F.sigmoid(self.fc3(x))
- return x
class PolicyGradient:
- def __init__(self, n_states,cfg):
+ def __init__(self, n_states,model,memory,cfg):
self.gamma = cfg.gamma
- self.policy_net = MLP(n_states,hidden_dim=cfg.hidden_dim)
+ self.device = torch.device(cfg.device)
+ self.memory = memory
+ self.policy_net = model.to(self.device)
self.optimizer = torch.optim.RMSprop(self.policy_net.parameters(), lr=cfg.lr)
- self.batch_size = cfg.batch_size
- def choose_action(self,state):
-
+ def sample_action(self,state):
+
+ state = torch.from_numpy(state).float()
+ state = Variable(state)
+ probs = self.policy_net(state)
+ m = Bernoulli(probs) # 伯努利分布
+ action = m.sample()
+ action = action.data.numpy().astype(int)[0] # 转为标量
+ return action
+ def predict_action(self,state):
+
state = torch.from_numpy(state).float()
state = Variable(state)
probs = self.policy_net(state)
@@ -53,7 +45,9 @@ class PolicyGradient:
action = action.data.numpy().astype(int)[0] # 转为标量
return action
- def update(self,reward_pool,state_pool,action_pool):
+ def update(self):
+ state_pool,action_pool,reward_pool= self.memory.sample()
+ state_pool,action_pool,reward_pool = list(state_pool),list(action_pool),list(reward_pool)
# Discount reward
running_add = 0
for i in reversed(range(len(reward_pool))):
@@ -83,7 +77,11 @@ class PolicyGradient:
# print(loss)
loss.backward()
self.optimizer.step()
- def save(self,path):
- torch.save(self.policy_net.state_dict(), path+'pg_checkpoint.pt')
- def load(self,path):
- self.policy_net.load_state_dict(torch.load(path+'pg_checkpoint.pt'))
\ No newline at end of file
+ self.memory.clear()
+ def save_model(self,path):
+ from pathlib import Path
+ # create path
+ Path(path).mkdir(parents=True, exist_ok=True)
+ torch.save(self.policy_net.state_dict(), path+'checkpoint.pt')
+ def load_model(self,path):
+ self.policy_net.load_state_dict(torch.load(path+'checkpoint.pt'))
\ No newline at end of file
diff --git a/projects/codes/PolicyGradient/task0.py b/projects/codes/PolicyGradient/task0.py
index b9e11a0..8f42f25 100644
--- a/projects/codes/PolicyGradient/task0.py
+++ b/projects/codes/PolicyGradient/task0.py
@@ -5,7 +5,7 @@ Author: John
Email: johnjim0816@gmail.com
Date: 2020-11-22 23:21:53
LastEditor: John
-LastEditTime: 2022-07-21 21:44:00
+LastEditTime: 2022-08-22 17:40:07
Discription:
Environment:
'''
@@ -19,10 +19,11 @@ import torch
import datetime
import argparse
from itertools import count
-
+import torch.nn.functional as F
from pg import PolicyGradient
-from common.utils import save_results, make_dir
-from common.utils import plot_rewards
+from common.utils import save_results, make_dir,all_seed,save_args,plot_rewards
+from common.models import MLP
+from common.memories import PGReplay
def get_args():
@@ -32,112 +33,107 @@ def get_args():
parser = argparse.ArgumentParser(description="hyperparameters")
parser.add_argument('--algo_name',default='PolicyGradient',type=str,help="name of algorithm")
parser.add_argument('--env_name',default='CartPole-v0',type=str,help="name of environment")
- parser.add_argument('--train_eps',default=300,type=int,help="episodes of training")
+ parser.add_argument('--train_eps',default=200,type=int,help="episodes of training")
parser.add_argument('--test_eps',default=20,type=int,help="episodes of testing")
parser.add_argument('--gamma',default=0.99,type=float,help="discounted factor")
- parser.add_argument('--lr',default=0.01,type=float,help="learning rate")
- parser.add_argument('--batch_size',default=8,type=int)
+ parser.add_argument('--lr',default=0.005,type=float,help="learning rate")
+ parser.add_argument('--update_fre',default=8,type=int)
parser.add_argument('--hidden_dim',default=36,type=int)
parser.add_argument('--device',default='cpu',type=str,help="cpu or cuda")
+ parser.add_argument('--seed',default=1,type=int,help="seed")
parser.add_argument('--result_path',default=curr_path + "/outputs/" + parser.parse_args().env_name + \
'/' + curr_time + '/results/' )
parser.add_argument('--model_path',default=curr_path + "/outputs/" + parser.parse_args().env_name + \
'/' + curr_time + '/models/' ) # path to save models
- parser.add_argument('--save_fig',default=True,type=bool,help="if save figure or not")
- args = parser.parse_args()
+ parser.add_argument('--save_fig',default=True,type=bool,help="if save figure or not")
+ parser.add_argument('--show_fig',default=False,type=bool,help="if show figure or not")
+ args = parser.parse_args([])
return args
+class PGNet(MLP):
+ ''' instead of outputing action, PG Net outputs propabilities of actions, we can use class inheritance from MLP here
+ '''
+ def forward(self, x):
+ x = F.relu(self.fc1(x))
+ x = F.relu(self.fc2(x))
+ x = F.sigmoid(self.fc3(x))
+ return x
-def env_agent_config(cfg,seed=1):
+def env_agent_config(cfg):
env = gym.make(cfg.env_name)
- env.seed(seed)
+ if cfg.seed !=0: # set random seed
+ all_seed(env,seed=cfg.seed)
n_states = env.observation_space.shape[0]
- agent = PolicyGradient(n_states,cfg)
+ n_actions = env.action_space.n # action dimension
+ print(f"state dim: {n_states}, action dim: {n_actions}")
+ model = PGNet(n_states,1,hidden_dim=cfg.hidden_dim)
+ memory = PGReplay()
+ agent = PolicyGradient(n_states,model,memory,cfg)
return env,agent
def train(cfg,env,agent):
print('Start training!')
- print(f'Env:{cfg.env_name}, Algorithm:{cfg.algo_name}, Device:{cfg.device}')
- state_pool = [] # temp states pool per several episodes
- action_pool = []
- reward_pool = []
+ print(f'Env:{cfg.env_name}, Algo:{cfg.algo_name}, Device:{cfg.device}')
rewards = []
- ma_rewards = []
for i_ep in range(cfg.train_eps):
state = env.reset()
ep_reward = 0
for _ in count():
- action = agent.choose_action(state) # 根据当前环境state选择action
+ action = agent.sample_action(state) # sample action
next_state, reward, done, _ = env.step(action)
ep_reward += reward
if done:
reward = 0
- state_pool.append(state)
- action_pool.append(float(action))
- reward_pool.append(reward)
+ agent.memory.push((state,float(action),reward))
state = next_state
if done:
print(f'Episode:{i_ep+1}/{cfg.train_eps}, Reward:{ep_reward:.2f}')
break
- if i_ep > 0 and i_ep % cfg.batch_size == 0:
- agent.update(reward_pool,state_pool,action_pool)
- state_pool = []
- action_pool = []
- reward_pool = []
+ if (i_ep+1) % cfg.update_fre == 0:
+ agent.update()
rewards.append(ep_reward)
- if ma_rewards:
- ma_rewards.append(
- 0.9*ma_rewards[-1]+0.1*ep_reward)
- else:
- ma_rewards.append(ep_reward)
print('Finish training!')
env.close() # close environment
- return rewards, ma_rewards
+ res_dic = {'episodes':range(len(rewards)),'rewards':rewards}
+ return res_dic
def test(cfg,env,agent):
- print('开始测试!')
- print(f'环境:{cfg.env_name}, 算法:{cfg.algo_name}, 设备:{cfg.device}')
+ print("start testing!")
+ print(f"Env: {cfg.env_name}, Algo: {cfg.algo_name}, Device: {cfg.device}")
rewards = []
- ma_rewards = []
for i_ep in range(cfg.test_eps):
state = env.reset()
ep_reward = 0
for _ in count():
- action = agent.choose_action(state) # 根据当前环境state选择action
+ action = agent.predict_action(state)
next_state, reward, done, _ = env.step(action)
ep_reward += reward
if done:
reward = 0
state = next_state
if done:
- print('回合:{}/{}, 奖励:{}'.format(i_ep + 1, cfg.train_eps, ep_reward))
+ print(f'Episode: {i_ep+1}/{cfg.test_eps},Reward: {ep_reward:.2f}')
break
rewards.append(ep_reward)
- if ma_rewards:
- ma_rewards.append(
- 0.9*ma_rewards[-1]+0.1*ep_reward)
- else:
- ma_rewards.append(ep_reward)
- print('完成测试!')
+ print("finish testing!")
env.close()
- return rewards, ma_rewards
+ return {'episodes':range(len(rewards)),'rewards':rewards}
if __name__ == "__main__":
- cfg = Config()
- # 训练
+ cfg = get_args()
env, agent = env_agent_config(cfg)
- rewards, ma_rewards = train(cfg, env, agent)
- make_dir(cfg.result_path, cfg.model_path) # 创建保存结果和模型路径的文件夹
- agent.save(path=cfg.model_path) # 保存模型
- save_results(rewards, ma_rewards, tag='train',
- path=cfg.result_path) # 保存结果
- plot_rewards(rewards, ma_rewards, cfg, tag="train") # 画出结果
- # 测试
- env, agent = env_agent_config(cfg)
- agent.load(path=cfg.model_path) # 导入模型
- rewards, ma_rewards = test(cfg, env, agent)
- save_results(rewards, ma_rewards, tag='test',
- path=cfg.result_path) # 保存结果
- plot_rewards(rewards, ma_rewards, cfg, tag="test") # 画出结果
+ res_dic = train(cfg, env, agent)
+ save_args(cfg,path = cfg.result_path) # save parameters
+ agent.save_model(path = cfg.model_path) # save models
+ save_results(res_dic, tag = 'train', path = cfg.result_path) # save results
+ plot_rewards(res_dic['rewards'], cfg, path = cfg.result_path,tag = "train") # plot results
+ # testing
+ env, agent = env_agent_config(cfg) # create new env for testing, sometimes can ignore this step
+ agent.load_model(path = cfg.model_path) # load model
+ res_dic = test(cfg, env, agent)
+ save_results(res_dic, tag='test',
+ path = cfg.result_path)
+ plot_rewards(res_dic['rewards'], cfg, path = cfg.result_path,tag = "test")
+
diff --git a/projects/codes/SAC/sac.py b/projects/codes/SAC/sac.py
new file mode 100644
index 0000000..e907520
--- /dev/null
+++ b/projects/codes/SAC/sac.py
@@ -0,0 +1,4 @@
+
+class SAC:
+ def __init__(self,n_actions,model,memory,cfg):
+ pass
\ No newline at end of file
diff --git a/projects/codes/SoftQ/outputs/CartPole-v0/20220818-154333/models/checkpoint.pth b/projects/codes/SoftQ/outputs/CartPole-v0/20220818-154333/models/checkpoint.pth
new file mode 100644
index 0000000..fc80e6f
Binary files /dev/null and b/projects/codes/SoftQ/outputs/CartPole-v0/20220818-154333/models/checkpoint.pth differ
diff --git a/projects/codes/SoftQ/outputs/CartPole-v0/20220818-154333/results/params.json b/projects/codes/SoftQ/outputs/CartPole-v0/20220818-154333/results/params.json
new file mode 100644
index 0000000..988c303
--- /dev/null
+++ b/projects/codes/SoftQ/outputs/CartPole-v0/20220818-154333/results/params.json
@@ -0,0 +1 @@
+{"algo_name": "SoftQ", "env_name": "CartPole-v0", "train_eps": 200, "test_eps": 20, "max_steps": 200, "gamma": 0.99, "alpha": 4, "lr": 0.0001, "memory_capacity": 50000, "batch_size": 128, "target_update": 2, "device": "cpu", "seed": 10, "result_path": "/Users/jj/Desktop/rl-tutorials/codes/SoftQ/outputs/CartPole-v0/20220818-154333/results/", "model_path": "/Users/jj/Desktop/rl-tutorials/codes/SoftQ/outputs/CartPole-v0/20220818-154333/models/", "show_fig": false, "save_fig": true}
\ No newline at end of file
diff --git a/projects/codes/SoftQ/outputs/CartPole-v0/20220818-154333/results/testing_curve.png b/projects/codes/SoftQ/outputs/CartPole-v0/20220818-154333/results/testing_curve.png
new file mode 100644
index 0000000..83750e7
Binary files /dev/null and b/projects/codes/SoftQ/outputs/CartPole-v0/20220818-154333/results/testing_curve.png differ
diff --git a/projects/codes/SoftQ/outputs/CartPole-v0/20220818-154333/results/testing_results.csv b/projects/codes/SoftQ/outputs/CartPole-v0/20220818-154333/results/testing_results.csv
new file mode 100644
index 0000000..b74878b
--- /dev/null
+++ b/projects/codes/SoftQ/outputs/CartPole-v0/20220818-154333/results/testing_results.csv
@@ -0,0 +1,21 @@
+episodes,rewards
+0,200.0
+1,200.0
+2,200.0
+3,200.0
+4,200.0
+5,200.0
+6,200.0
+7,200.0
+8,199.0
+9,200.0
+10,200.0
+11,200.0
+12,200.0
+13,200.0
+14,200.0
+15,200.0
+16,200.0
+17,200.0
+18,200.0
+19,200.0
diff --git a/projects/codes/SoftQ/outputs/CartPole-v0/20220818-154333/results/training_curve.png b/projects/codes/SoftQ/outputs/CartPole-v0/20220818-154333/results/training_curve.png
new file mode 100644
index 0000000..9f3164b
Binary files /dev/null and b/projects/codes/SoftQ/outputs/CartPole-v0/20220818-154333/results/training_curve.png differ
diff --git a/projects/codes/SoftQ/outputs/CartPole-v0/20220818-154333/results/training_results.csv b/projects/codes/SoftQ/outputs/CartPole-v0/20220818-154333/results/training_results.csv
new file mode 100644
index 0000000..0f52c1c
--- /dev/null
+++ b/projects/codes/SoftQ/outputs/CartPole-v0/20220818-154333/results/training_results.csv
@@ -0,0 +1,201 @@
+episodes,rewards
+0,21.0
+1,23.0
+2,24.0
+3,27.0
+4,33.0
+5,18.0
+6,47.0
+7,18.0
+8,18.0
+9,21.0
+10,26.0
+11,31.0
+12,11.0
+13,17.0
+14,22.0
+15,16.0
+16,17.0
+17,34.0
+18,20.0
+19,11.0
+20,50.0
+21,15.0
+22,11.0
+23,39.0
+24,11.0
+25,28.0
+26,37.0
+27,26.0
+28,63.0
+29,18.0
+30,17.0
+31,13.0
+32,9.0
+33,15.0
+34,13.0
+35,21.0
+36,17.0
+37,22.0
+38,20.0
+39,31.0
+40,9.0
+41,10.0
+42,11.0
+43,15.0
+44,18.0
+45,10.0
+46,30.0
+47,14.0
+48,36.0
+49,26.0
+50,21.0
+51,15.0
+52,9.0
+53,14.0
+54,10.0
+55,27.0
+56,14.0
+57,15.0
+58,22.0
+59,12.0
+60,20.0
+61,10.0
+62,12.0
+63,29.0
+64,11.0
+65,13.0
+66,27.0
+67,50.0
+68,29.0
+69,40.0
+70,29.0
+71,18.0
+72,27.0
+73,11.0
+74,15.0
+75,10.0
+76,13.0
+77,11.0
+78,17.0
+79,13.0
+80,18.0
+81,24.0
+82,15.0
+83,34.0
+84,11.0
+85,35.0
+86,26.0
+87,9.0
+88,19.0
+89,19.0
+90,16.0
+91,25.0
+92,18.0
+93,37.0
+94,46.0
+95,88.0
+96,26.0
+97,55.0
+98,43.0
+99,141.0
+100,89.0
+101,151.0
+102,47.0
+103,56.0
+104,64.0
+105,56.0
+106,49.0
+107,87.0
+108,58.0
+109,55.0
+110,57.0
+111,165.0
+112,31.0
+113,200.0
+114,57.0
+115,107.0
+116,46.0
+117,45.0
+118,64.0
+119,69.0
+120,67.0
+121,65.0
+122,47.0
+123,63.0
+124,134.0
+125,60.0
+126,89.0
+127,99.0
+128,51.0
+129,109.0
+130,131.0
+131,156.0
+132,118.0
+133,185.0
+134,86.0
+135,149.0
+136,138.0
+137,143.0
+138,114.0
+139,130.0
+140,139.0
+141,106.0
+142,135.0
+143,164.0
+144,156.0
+145,155.0
+146,200.0
+147,186.0
+148,64.0
+149,200.0
+150,135.0
+151,135.0
+152,168.0
+153,200.0
+154,200.0
+155,200.0
+156,167.0
+157,198.0
+158,188.0
+159,200.0
+160,200.0
+161,200.0
+162,200.0
+163,200.0
+164,200.0
+165,200.0
+166,200.0
+167,200.0
+168,189.0
+169,200.0
+170,146.0
+171,200.0
+172,200.0
+173,200.0
+174,115.0
+175,170.0
+176,200.0
+177,200.0
+178,178.0
+179,200.0
+180,200.0
+181,200.0
+182,200.0
+183,200.0
+184,200.0
+185,200.0
+186,120.0
+187,200.0
+188,200.0
+189,200.0
+190,200.0
+191,200.0
+192,200.0
+193,200.0
+194,200.0
+195,200.0
+196,200.0
+197,200.0
+198,200.0
+199,200.0
diff --git a/projects/codes/SoftQ/softq.py b/projects/codes/SoftQ/softq.py
new file mode 100644
index 0000000..a9a38e1
--- /dev/null
+++ b/projects/codes/SoftQ/softq.py
@@ -0,0 +1,71 @@
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+from collections import deque
+import random
+from torch.distributions import Categorical
+import gym
+import numpy as np
+
+class SoftQ:
+ def __init__(self,n_actions,model,memory,cfg):
+ self.memory = memory
+ self.alpha = cfg.alpha
+ self.gamma = cfg.gamma # discount factor
+ self.batch_size = cfg.batch_size
+ self.device = torch.device(cfg.device)
+ self.policy_net = model.to(self.device)
+ self.target_net = model.to(self.device)
+ self.target_net.load_state_dict(self.policy_net.state_dict()) # copy parameters
+ self.optimizer = torch.optim.Adam(self.policy_net.parameters(), lr=cfg.lr)
+ self.losses = [] # save losses
+
+ def sample_action(self,state):
+ state = torch.FloatTensor(state).unsqueeze(0).to(self.device)
+ with torch.no_grad():
+ q = self.policy_net(state)
+ v = self.alpha * torch.log(torch.sum(torch.exp(q/self.alpha), dim=1, keepdim=True)).squeeze()
+ dist = torch.exp((q-v)/self.alpha)
+ dist = dist / torch.sum(dist)
+ c = Categorical(dist)
+ a = c.sample()
+ return a.item()
+ def predict_action(self,state):
+ state = torch.tensor(np.array(state), device=self.device, dtype=torch.float).unsqueeze(0)
+ with torch.no_grad():
+ q = self.policy_net(state)
+ v = self.alpha * torch.log(torch.sum(torch.exp(q/self.alpha), dim=1, keepdim=True)).squeeze()
+ dist = torch.exp((q-v)/self.alpha)
+ dist = dist / torch.sum(dist)
+ c = Categorical(dist)
+ a = c.sample()
+ return a.item()
+ def update(self):
+ if len(self.memory) < self.batch_size: # when the memory capacity does not meet a batch, the network will not update
+ return
+ state_batch, action_batch, reward_batch, next_state_batch, done_batch = self.memory.sample(self.batch_size)
+ state_batch = torch.tensor(np.array(state_batch), device=self.device, dtype=torch.float) # shape(batchsize,n_states)
+ action_batch = torch.tensor(np.array(action_batch), device=self.device, dtype=torch.float).unsqueeze(1) # shape(batchsize,1)
+ reward_batch = torch.tensor(np.array(reward_batch), device=self.device, dtype=torch.float).unsqueeze(1) # shape(batchsize,1)
+ next_state_batch = torch.tensor(np.array(next_state_batch), device=self.device, dtype=torch.float) # shape(batchsize,n_states)
+ done_batch = torch.tensor(np.array(done_batch), device=self.device, dtype=torch.float).unsqueeze(1) # shape(batchsize,1)
+ # print(state_batch.shape,action_batch.shape,reward_batch.shape,next_state_batch.shape,done_batch.shape)
+ with torch.no_grad():
+ next_q = self.target_net(next_state_batch)
+ next_v = self.alpha * torch.log(torch.sum(torch.exp(next_q/self.alpha), dim=1, keepdim=True))
+ y = reward_batch + (1 - done_batch ) * self.gamma * next_v
+ loss = F.mse_loss(self.policy_net(state_batch).gather(1, action_batch.long()), y)
+ self.losses.append(loss)
+ self.optimizer.zero_grad()
+ loss.backward()
+ self.optimizer.step()
+ def save_model(self, path):
+ from pathlib import Path
+ # create path
+ Path(path).mkdir(parents=True, exist_ok=True)
+ torch.save(self.target_net.state_dict(), path+'checkpoint.pth')
+
+ def load_model(self, path):
+ self.target_net.load_state_dict(torch.load(path+'checkpoint.pth'))
+ for target_param, param in zip(self.target_net.parameters(), self.policy_net.parameters()):
+ param.data.copy_(target_param.data)
\ No newline at end of file
diff --git a/projects/codes/SoftQ/task0.py b/projects/codes/SoftQ/task0.py
new file mode 100644
index 0000000..fd67aa4
--- /dev/null
+++ b/projects/codes/SoftQ/task0.py
@@ -0,0 +1,142 @@
+import sys,os
+curr_path = os.path.dirname(os.path.abspath(__file__)) # current path
+parent_path = os.path.dirname(curr_path) # parent path
+sys.path.append(parent_path) # add path to system path
+
+import argparse
+import datetime
+import gym
+import torch
+import random
+import numpy as np
+import torch.nn as nn
+from common.memories import ReplayBufferQue
+from common.models import MLP
+from common.utils import save_results,all_seed,plot_rewards,save_args
+from softq import SoftQ
+
+def get_args():
+ """ hyperparameters
+ """
+ curr_time = datetime.datetime.now().strftime("%Y%m%d-%H%M%S") # obtain current time
+ parser = argparse.ArgumentParser(description="hyperparameters")
+ parser.add_argument('--algo_name',default='SoftQ',type=str,help="name of algorithm")
+ parser.add_argument('--env_name',default='CartPole-v0',type=str,help="name of environment")
+ parser.add_argument('--train_eps',default=200,type=int,help="episodes of training")
+ parser.add_argument('--test_eps',default=20,type=int,help="episodes of testing")
+ parser.add_argument('--max_steps',default=200,type=int,help="maximum steps per episode")
+ parser.add_argument('--gamma',default=0.99,type=float,help="discounted factor")
+ parser.add_argument('--alpha',default=4,type=float,help="alpha")
+ parser.add_argument('--lr',default=0.0001,type=float,help="learning rate")
+ parser.add_argument('--memory_capacity',default=50000,type=int,help="memory capacity")
+ parser.add_argument('--batch_size',default=128,type=int)
+ parser.add_argument('--target_update',default=2,type=int)
+ parser.add_argument('--device',default='cpu',type=str,help="cpu or cuda")
+ parser.add_argument('--seed',default=10,type=int,help="seed")
+ parser.add_argument('--result_path',default=curr_path + "/outputs/" + parser.parse_args().env_name + \
+ '/' + curr_time + '/results/' )
+ parser.add_argument('--model_path',default=curr_path + "/outputs/" + parser.parse_args().env_name + \
+ '/' + curr_time + '/models/' )
+ parser.add_argument('--show_fig',default=False,type=bool,help="if show figure or not")
+ parser.add_argument('--save_fig',default=True,type=bool,help="if save figure or not")
+ args = parser.parse_args()
+ return args
+
+class SoftQNetwork(nn.Module):
+ '''Actually almost same to common.models.MLP
+ '''
+ def __init__(self,input_dim,output_dim):
+ super(SoftQNetwork,self).__init__()
+ self.fc1 = nn.Linear(input_dim, 64)
+ self.relu = nn.ReLU()
+ self.fc2 = nn.Linear(64, 256)
+ self.fc3 = nn.Linear(256, output_dim)
+
+ def forward(self, x):
+ x = self.relu(self.fc1(x))
+ x = self.relu(self.fc2(x))
+ x = self.fc3(x)
+ return x
+
+def env_agent_config(cfg):
+ ''' create env and agent
+ '''
+ env = gym.make(cfg.env_name) # create env
+ if cfg.seed !=0: # set random seed
+ all_seed(env,seed=cfg.seed)
+ n_states = env.observation_space.shape[0] # state dimension
+ n_actions = env.action_space.n # action dimension
+ print(f"state dim: {n_states}, action dim: {n_actions}")
+ # model = MLP(n_states,n_actions)
+ model = SoftQNetwork(n_states,n_actions)
+ memory = ReplayBufferQue(cfg.memory_capacity) # replay buffer
+ agent = SoftQ(n_actions,model,memory,cfg) # create agent
+ return env, agent
+
+def train(cfg, env, agent):
+ ''' training
+ '''
+ print("start training!")
+ print(f"Env: {cfg.env_name}, Algo: {cfg.algo_name}, Device: {cfg.device}")
+ rewards = [] # record rewards for all episodes
+ steps = [] # record steps for all episodes, sometimes need
+ for i_ep in range(cfg.train_eps):
+ ep_reward = 0 # reward per episode
+ ep_step = 0
+ state = env.reset() # reset and obtain initial state
+ while True:
+ # for _ in range(cfg.max_steps):
+ ep_step += 1
+ action = agent.sample_action(state) # sample action
+ next_state, reward, done, _ = env.step(action) # update env and return transitions
+ agent.memory.push((state, action, reward, next_state, done)) # save transitions
+ state = next_state # update next state for env
+ agent.update() # update agent
+ ep_reward += reward
+ if done:
+ break
+ if (i_ep + 1) % cfg.target_update == 0: # target net update, target_update means "C" in pseucodes
+ agent.target_net.load_state_dict(agent.policy_net.state_dict())
+ steps.append(ep_step)
+ rewards.append(ep_reward)
+ if (i_ep + 1) % 10 == 0:
+ print(f'Episode: {i_ep+1}/{cfg.train_eps}, Reward: {ep_reward:.2f}')
+ print("finish training!")
+ res_dic = {'episodes':range(len(rewards)),'rewards':rewards}
+ return res_dic
+def test(cfg, env, agent):
+ print("start testing!")
+ print(f"Env: {cfg.env_name}, Algo: {cfg.algo_name}, Device: {cfg.device}")
+ rewards = [] # record rewards for all episodes
+ for i_ep in range(cfg.test_eps):
+ ep_reward = 0 # reward per episode
+ state = env.reset() # reset and obtain initial state
+ while True:
+ action = agent.predict_action(state) # predict action
+ next_state, reward, done, _ = env.step(action)
+ state = next_state
+ ep_reward += reward
+ if done:
+ break
+ rewards.append(ep_reward)
+ print(f'Episode: {i_ep+1}/{cfg.test_eps},Reward: {ep_reward:.2f}')
+ print("finish testing!")
+ env.close()
+ return {'episodes':range(len(rewards)),'rewards':rewards}
+
+if __name__ == "__main__":
+ cfg = get_args()
+ # 训练
+ env, agent = env_agent_config(cfg)
+ res_dic = train(cfg, env, agent)
+ save_args(cfg,path = cfg.result_path) # 保存参数到模型路径上
+ agent.save_model(path = cfg.model_path) # 保存模型
+ save_results(res_dic, tag = 'train', path = cfg.result_path)
+ plot_rewards(res_dic['rewards'], cfg, path = cfg.result_path,tag = "train")
+ # 测试
+ env, agent = env_agent_config(cfg) # 也可以不加,加这一行的是为了避免训练之后环境可能会出现问题,因此新建一个环境用于测试
+ agent.load_model(path = cfg.model_path) # 导入模型
+ res_dic = test(cfg, env, agent)
+ save_results(res_dic, tag='test',
+ path = cfg.result_path) # 保存结果
+ plot_rewards(res_dic['rewards'], cfg, path = cfg.result_path,tag = "test") # 画出结果
\ No newline at end of file
diff --git a/projects/codes/common/memories.py b/projects/codes/common/memories.py
index a238696..255333a 100644
--- a/projects/codes/common/memories.py
+++ b/projects/codes/common/memories.py
@@ -5,11 +5,12 @@
@Email: johnjim0816@gmail.com
@Date: 2020-06-10 15:27:16
@LastEditor: John
-LastEditTime: 2021-09-15 14:52:37
+LastEditTime: 2022-08-22 17:23:21
@Discription:
@Environment: python 3.7.7
'''
import random
+from collections import deque
class ReplayBuffer:
def __init__(self, capacity):
self.capacity = capacity # 经验回放的容量
@@ -34,3 +35,40 @@ class ReplayBuffer:
'''
return len(self.buffer)
+class ReplayBufferQue:
+ def __init__(self, capacity: int) -> None:
+ self.capacity = capacity
+ self.buffer = deque(maxlen=self.capacity)
+ def push(self,trainsitions):
+ '''_summary_
+ Args:
+ trainsitions (tuple): _description_
+ '''
+ self.buffer.append(trainsitions)
+ def sample(self, batch_size: int, sequential: bool = False):
+ if batch_size > len(self.buffer):
+ batch_size = len(self.buffer)
+ if sequential: # sequential sampling
+ rand = random.randint(0, len(self.buffer) - batch_size)
+ batch = [self.buffer[i] for i in range(rand, rand + batch_size)]
+ return zip(*batch)
+ else:
+ batch = random.sample(self.buffer, batch_size)
+ return zip(*batch)
+ def clear(self):
+ self.buffer.clear()
+ def __len__(self):
+ return len(self.buffer)
+
+class PGReplay(ReplayBufferQue):
+ '''replay buffer for policy gradient based methods, each time these methods will sample all transitions
+ Args:
+ ReplayBufferQue (_type_): _description_
+ '''
+ def __init__(self):
+ self.buffer = deque()
+ def sample(self):
+ ''' sample all the transitions
+ '''
+ batch = list(self.buffer)
+ return zip(*batch)
\ No newline at end of file
diff --git a/projects/codes/common/utils.py b/projects/codes/common/utils.py
index dd21163..e63d1e6 100644
--- a/projects/codes/common/utils.py
+++ b/projects/codes/common/utils.py
@@ -5,7 +5,7 @@ Author: John
Email: johnjim0816@gmail.com
Date: 2021-03-12 16:02:24
LastEditor: John
-LastEditTime: 2022-08-15 18:11:27
+LastEditTime: 2022-08-22 17:41:28
Discription:
Environment:
'''
@@ -15,6 +15,7 @@ from pathlib import Path
import matplotlib.pyplot as plt
import seaborn as sns
import json
+import pandas as pd
from matplotlib.font_manager import FontProperties # 导入字体模块
@@ -84,12 +85,12 @@ def plot_losses(losses, algo="DQN", save=True, path='./'):
plt.savefig(path+"losses_curve")
plt.show()
-def save_results(dic, tag='train', path = None):
+def save_results(res_dic, tag='train', path = None):
''' 保存奖励
'''
Path(path).mkdir(parents=True, exist_ok=True)
- for key,value in dic.items():
- np.save(path+'{}_{}.npy'.format(tag,key),value)
+ df = pd.DataFrame(res_dic)
+ df.to_csv(f"{path}/{tag}ing_results.csv",index=None)
print('Results saved!')
@@ -115,4 +116,26 @@ def save_args(args,path=None):
Path(path).mkdir(parents=True, exist_ok=True)
with open(f"{path}/params.json", 'w') as fp:
json.dump(args_dict, fp)
- print("参数已保存!")
+ print("Parameters saved!")
+
+def all_seed(env,seed = 1):
+ ''' omnipotent seed for RL, attention the position of seed function, you'd better put it just following the env create function
+ Args:
+ env (_type_):
+ seed (int, optional): _description_. Defaults to 1.
+ '''
+ import torch
+ import numpy as np
+ import random
+ print(f"seed = {seed}")
+ env.seed(seed) # env config
+ np.random.seed(seed)
+ random.seed(seed)
+ torch.manual_seed(seed) # config for CPU
+ torch.cuda.manual_seed(seed) # config for GPU
+ os.environ['PYTHONHASHSEED'] = str(seed) # config for python scripts
+ # config for cudnn
+ torch.backends.cudnn.deterministic = True
+ torch.backends.cudnn.benchmark = False
+ torch.backends.cudnn.enabled = False
+
\ No newline at end of file
diff --git a/projects/requirements.txt b/projects/requirements.txt
index 42e65c6..8db643c 100644
--- a/projects/requirements.txt
+++ b/projects/requirements.txt
@@ -1,10 +1,11 @@
gym==0.21.0
-torch==1.9.0
-torchvision==0.10.0
-torchaudio==0.9.0
+torch==1.10.0
+torchvision==0.11.0
+torchaudio==0.10.0
ipykernel==6.15.1
jupyter==1.0.0
matplotlib==3.5.2
seaborn==0.11.2
dill==0.3.5.1
-argparse==1.4.0
\ No newline at end of file
+argparse==1.4.0
+pandas==1.3.5
\ No newline at end of file