0%

1. 有模型数值迭代

1.1 主要思想

有模型数值迭代主要利用动态规划(Dynamic Programming,DP)的思想。

动态规划迭代算法运用了自益的思想。但在实际问题中,直接使用动态规划算法常出现困难,从下面的状态动作价值迭代可以看出,实际问题的状态空间非常大,仅仅是扫描一遍所有的状态都是不可能的事情。
$$
q_{pi}(s_t,a_t)=r(s_t,a_t)+\gamma \sum_{s’}p(s’|s_t,a_t)v_{\pi}(s’)
$$

自益:用一个估计值来估计另外一个估计值

方法改进:异步动态规划

异步动态规划的思想是,每次扫描不再完整的更新一整套状态价值函数,而只是部分更新感兴趣的值。例如,有的状态s不会转移到另一些状态($p(s’|s,a)=0$$的状态$$s’$)

1.2 理论基础

理论基础:度量空间上的Banach不动点定理

之所以是有模型的价值迭代,是因为我们知道其动力系统$p(s’|s,a)$,即转移概率,这样我们就可以从从一个确定性策略出发,经过不断策略评估,策略改进……最后收敛到最优策略。背后的数学证明就是度量空间上的Banach不动点定理。

DP的特点

  1. 利用bootstraping自益的思想
  2. 没有利用异步动态规划的方法,每次迭代需要更新所有的状态

2. 无模型的数值迭代

2.1 Monte Carlo(MC)

基本思想:利用MC估计期望值$V_{\pi}(s)$和$Q_{\pi}(s,a)$

举例:对于一个具体的策略$\pi$来说,利用这个策略玩n个回合

$S_0^1=s,A_0^1=a,R_1^1,S_1^1,A_1^1,R_2^1…… \qquad G^1$

$S_0^2=s,A_0^2=a,R_1^2,S_1^2,A_1^2,R_2^2…… \qquad G^2$

$……$

$S_0^n,A_0^n,R_1^n,S_1^n,A_1^n,R_2^n…… \qquad G^n$

利用Monte Carlo来估计价值函数$V_{\pi}(s)=\frac{1}{k}(G^1+G^2+……)$,从相同状态s出发的回合累计回报平均值。$Q_{\pi}(s,a)=\frac{1}{k}(G^1+G^2+……)$,从相同状态动作对出发的回合累计回报平均值。

利用Monte Carlo进行更新,实际应用中又分为每次访问回合更新首次访问回合更新

MC的特点

  1. 没有利用自益的思想
  2. 利用经验平均回报的方法来估计
  3. 局限:只能用在有终止的MDP,每一步的R 都是一个变量,累积后的G方差较大。
  4. 每个回合只需要更新一条该回合轨迹上的状态

2.2 Temporal Difference(TD)

2.2.1 TD(n)

对于状态价值来说,n步时序差分$TD(n)$目标为:

$U_{t:t+n}^{(v)}=R_{t+1}+\gamma R_{t+2}+…+\gamma ^nq(S_{t+n},A_{t+n})$

TD(n)

对于动作状态价值来说,将上图的白圆和黑圆互换。以TD(0)为例,更新动作状态价值可以表示为
$$
U_t=R_{t+1}+\gamma q(S_{t+1},A_{t+1}) \
q(S_t,A_t)\gets q(S_t,A_t)+\alpha[U_t-q(S_t,A_t)]
$$
从上式可以看出,TD(n)是利用了自益的思想。

对于时序差分来说
$$
q_{target}(S_t,A_t)=E[R_{t+1}+ q(S_{t+1},A_{t+1}]
$$
在实际应用中我们用
$$
U_t=R_{t+1}+\gamma q(S_{t+1},A_{t+1})\approx q_{target}(S_t,A_t)
$$

2.2.2 SARSA

  1. 单步SARSA:单步时序差分目标(策略评估) + 策略改进

  2. 多步SARSA:多步时序差分目标(策略评估) + 策略改进

  3. 期望SARSA:$U_t=R_{t+1}+\gamma \sum_{a\in \mathcal{A}}\pi(a|S_{t+1})q(S_{t+1},a)$ 也有单步和多步

TD的特点:

  1. 可以从不完整的轨迹中学习
  2. 介于MC和DP之间的方法
  3. 有sampling(期望的近似)和bootstraping
  4. 方差较于MC更小
  5. 可以在线学习,每走一步就更新

Homebrew 镜像

中科大:https://lug.ustc.edu.cn/wiki/mirrors/help/brew.git

清华:https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git

阿里:https://mirrors.aliyun.com/homebrew/

对于bash用户:

1
2
echo 'export HOMEBREW_BOTTLE_DOMAIN=https://mirrors.cloud.tencent.com/homebrew-bottles' >> ~/.bash_profile
source ~/.bash_profile

对于zsh用户

1
2
echo 'export HOMEBREW_BOTTLE_DOMAIN=https://mirrors.cloud.tencent.com/homebrew-bottles' >> ~/.zshrc
source ~/.zshrc

作者:码客
链接:https://zhuanlan.zhihu.com/p/72251385
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

以清华大学镜像源为例(https://pypi.tuna.tsinghua.edu.cn/simple/)

pypi镜像

临时使用

1
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple some_package

设为默认

升级pip到最新的版本(>=10.0.0)后进行配置

1
2
pip install pip -U
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

如果 pip 默认源的网络连接较差,临时使用本镜像站来升级 pip:

1
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pip -U

pip安装本地包

pip install ~/Downloads/a.whl

国内常用PyPI镜像网站

豆瓣: https://pypi.doubanio.com/simple/

网易: https://mirrors.163.com/pypi/simple/

阿里云: https://mirrors.aliyun.com/pypi/simple/

腾讯云: https://mirrors.cloud.tencent.com/pypi/simple

清华大学: https://pypi.tuna.tsinghua.edu.cn/simple/

conda常用命令及如何切换镜像

常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
conda activate xxxx #开启xxxx环境
conda deactivate #关闭环境

conda env list #显示所有的虚拟环境
conda info --envs #显示所有的虚拟环境
conda info -e #显示所有已经创建的环境

conda update -n base conda #update最新版本的conda

conda create -n xxxx python=3.6 #创建python3.6的xxxx虚拟环境

conda remove --name xxxx --all #彻底删除旧环境

conda remove -n tensorflow --all #彻底删除旧环境

#Conda是没有重命名环境的功能, 要实现这个基本需求, 可以通过克隆-删除的过程。
#切记不要直接mv移动环境的文件夹来重命名, 会导致一系列无法想象的错误的发生!
conda create --name newname --clone oldname #克隆环境
conda remove --name oldname --all #彻底删除旧环境

conda list #查看已经安装的文件包
conda list -n xxx #指定查看xxx虚拟环境下安装的package
conda update xxx #更新xxx文件包
conda uninstall xxx #卸载xxx文件包

#conda 安装本地包
conda install --use-local ~/Downloads/a.tar.bz2

#显示目前conda的数据源有哪些
conda config --show channels

#添加数据源:例如, 添加清华anaconda镜像:
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --set show_channel_urls yes

#删除数据源
conda config --remove channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/

Conda配置国内镜像源

方法1:用vim打开文件,添加以下镜像源。推荐使用中科大镜像源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
vim ~/.condarc
#清华源
channels:
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/
ssl_verify: true
#中科大源
channels:
- https://mirrors.ustc.edu.cn/anaconda/pkgs/main/
- https://mirrors.ustc.edu.cn/anaconda/pkgs/free/
- https://mirrors.ustc.edu.cn/anaconda/cloud/conda-forge/
ssl_verify: true
#上交大源
channels:
- https://mirrors.sjtug.sjtu.edu.cn/anaconda/pkgs/main/
- https://mirrors.sjtug.sjtu.edu.cn/anaconda/pkgs/free/
- https://mirrors.sjtug.sjtu.edu.cn/anaconda/cloud/conda-forge/
ssl_verify: true

方法2: 在命令终端输入以下命令,添加镜像源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 中科大镜像源
conda config --add channels https://mirrors.ustc.edu.cn/anaconda/pkgs/main/
conda config --add channels https://mirrors.ustc.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.ustc.edu.cn/anaconda/cloud/conda-forge/
conda config --add channels https://mirrors.ustc.edu.cn/anaconda/cloud/msys2/
conda config --add channels https://mirrors.ustc.edu.cn/anaconda/cloud/bioconda/
conda config --add channels https://mirrors.ustc.edu.cn/anaconda/cloud/menpo/
conda config --add channels https://mirrors.ustc.edu.cn/anaconda/cloud/

# 阿里镜像源
conda config --add channels https://mirrors.aliyun.com/pypi/simple/

# 豆瓣的python的源

conda config --add channels http://pypi.douban.com/simple/

# 显示检索路径,每次安装包时会将包源路径显示出来

conda config --set show_channel_urls yes

conda config --set always_yes True

# 显示所有镜像通道路径命令

conda config --show channels

遇到一些问题

conda无法创建虚拟环境

1.通过conda创建虚拟环境出错,关掉网络代理以后,重新打开终端再试试;

2.更换conda源试试;

注意事项

宁愿新安装虚拟环境,也不要区折腾python升级和降级的问题,更不要去动系统自带的python版本!!!否则操作失误,终端打不开那就尴尬了!

参考来源

  1. 知乎:https://zhuanlan.zhihu.com/p/345251737
  2. 清华镜像网站帮助:https://mirrors.tuna.tsinghua.edu.cn/help/pypi/

本文为转载自:ZMonster’s Blog

切片操作

Numpy 中多维数组的切片操作与 Python 中 list 的切片操作一样,同样由 start, stop, step 三个部分组成。

1
2
3
4
5
6
7
8
9
10
11
12
13
import numpy as np

arr = np.arange(12)
print('array is:', arr)

slice_one = arr[:4]
print('slice begins at 0 and ends at 4 is:', slice_one)

slice_two = arr[7:10]
print('slice begins at 7 and ends at 10 is:', slice_two)

slice_three = arr[0:12:4]
print('slice begins at 0 and ends at 12 with step 4 is:', slice_three)
1
2
3
4
array is: [ 0  1  2  3  4  5  6  7  8  9 10 11]
slice begins at 0 and ends at 4 is: [0 1 2 3]
slice begins at 7 and ends at 10 is: [7 8 9]
slice begins at 0 and ends at 12 with step 4 is: [0 4 8]

上述例子是一维数组的例子,如果是多维数组,将不同维度上的切片操作用 逗号分开就好了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# coding: utf-8
import numpy as np

arr = np.arange(12).reshape((3, 4))
print('array is:')
print(arr)

# 取第一维的索引 1 到索引 2 之间的元素,也就是第二行
# 取第二维的索引 1 到索引 3 之间的元素,也就是第二列和第三列
slice_one = arr[1:2, 1:3]
print('first slice is:')
print(slice_one)

# 取第一维的全部
# 按步长为 2 取第二维的索引 0 到末尾 之间的元素,也就是第一列和第三列
slice_two = arr[:, ::2]
print('second slice is:')
print(slice_two)
1
2
3
4
5
6
7
8
9
10
array is:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
first slice is:
[[5 6]]
second slice is:
[[ 0 2]
[ 4 6]
[ 8 10]]

对于 slice_two,如果 arr 是用 Python 的 list 表示的,那么要得到相同的结果得像下面这样,相对来说就麻烦多了:

1
2
3
4
5
6
7
8
import numpy as np

arr = np.arange(12).reshape((3, 4)).tolist()

slice_two = [
row[::2] for row in arr
]
print(slice_two)
1
[[0, 2], [4, 6], [8, 10]]

对于维数超过 3 的多维数组,还可以通过 ‘…’ 来简化操作

1
2
3
4
5
6
7
# coding: utf-8
import numpy as np

arr = np.arange(24).reshape((2, 3, 4))

print(arr[1, ...]) # 等价于 arr[1, :, :]
print(arr[..., 1]) # 等价于 arr[:, :, 1]
1
2
3
4
5
[[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]
[[ 1 5 9]
[13 17 21]]

索引操作

最简单的情况

对于一个多维数组来说,最简单的情况就是访问其中一个特定位置的元素了,如下所示:

1
2
3
4
5
6
7
8
9
10
# coding: utf-8
import numpy as np

arr = np.array([
[1, 2, 3, 4],
[2, 4, 6, 8],
[3, 6, 9, 12],
[4, 8, 12, 16]
])
print('第二行第二列的值:', arr[1, 1])
1
第二行第二列的值: 4

相比之下,如果用 Python 的 list 来表示上述二维数组,获取同一个位置的元素的方法为:

1
2
3
4
5
6
7
8
9
10
11
12
# coding: utf-8
arr = [
[1, 2, 3, 4],
[2, 4, 6, 8],
[3, 6, 9, 12],
[4, 8, 12, 16]
]
print '第二行第二列的值:', arr[1][1]
try:
print('第二行第二列的值(尝试用 Numpy 的方式获取):', arr[1, 1])
except Exception as e:
print(str(e))
1
2
第二行第二列的值: 4
第二行第二列的值(尝试用 Numpy 的方式获取): list indices must be integers, not tuple

如果只是二维数组,这种差别可能看起来并不大,但想象一下假如有一个 10 维的数组,用 Python 的标准做法需要写 10 对中括号,而用 Numpy 依然只需要一对。

获取多个元素

事实上,在 Numpy 的索引操作方式 x = arr[obj] 中, obj 不仅仅可以是一个用逗号分隔开的数字序列,还可以是更复杂的内容。

  1. 用逗号分隔的数组序列

    • 序列的长度和多维数组的维数要一致
    • 序列中每个数组的长度要一致
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import numpy as np

    arr = np.array([
    [1, 2, 3, 4],
    [2, 4, 6, 8],
    [3, 6, 9, 12],
    [4, 8, 12, 16]
    ])

    print(arr[[0, 2], [3, 1]])
    1
    [4 6]

    以上面这个例子来说,其含义是: 选择第一行和第三行,然后对第一行选择第四列,对第三行选择第二列。

  2. boolean/mask index

    这个不太好翻译,所以就用原来的英语表达。

    所谓 boolean index,就是用一个由 boolean 类型值组成的数组来选择元素的方法。比如说对下面这样多维数组

    1
    2
    3
    4
    array([[1, 2, 3, 4],
    [2, 4, 6, 8],
    [3, 6, 9, 12],
    [4, 8, 12, 16]])

    如果要取其中 值大于 5 的元素,就可以用上 boolean index 了,如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import numpy as np

    arr = np.array([[1, 2, 3, 4],
    [2, 4, 6, 8],
    [3, 6, 9, 12],
    [4, 8, 12, 16]])
    mask = arr > 5

    print('boolean mask is:')
    print(mask)

    print(arr[mask])
    1
    2
    3
    4
    5
    6
    boolean mask is:
    [[False False False False]
    [False False True True]
    [False True True True]
    [False True True True]]
    [ 6 8 6 9 12 8 12 16]

    除了比较运算能产生 boolean mask 数组以外, Numpy 本身也提供了一些工具方法:

    • numpy.iscomplex
    • numpy.isreal
    • numpy.isfinite
    • numpy.isinf
    • numpy.isnan