深度强化学习3——蒙特卡罗方法(MC)

前面我们介绍了用动态规划求解马尔科夫决策过程(MDP),然而需要已知环境信息,然而现实环境很多都是未知的,我们会用什么方法求解呢?蒙特卡罗方法(MC),时序差分学习(TD)都可以求解未知环境下的强化学习问题,本章主要介绍蒙特卡罗方法。

蒙特卡洛方法基本思想

当我们无法得到模型内容时,就需要通过不断模拟的方式得到大量相关的样本,并通过样本得到我们预期得到的结果,通常蒙特卡罗方法可以粗略地分成两类:

一、所求解的问题本身具有内在的随机性,借助计算机的运算能力可以直接模拟这种随机的过程。
二、所求解问题可以转化为某种随机分布的特征数,比如随机事件出现的概率,或者随机变量的期望值。通过随机抽样的方法,以随机事件出现的频率估计其概率,或者以抽样的数字特征估算随机变量的数字特征,并将其作为问题的解。

一个经典的用蒙特卡洛方法求π值

基本思路:正方形内部有一个相切的圆,它们的面积之比是π/4。现在,在这个正方形内部,随机产生n个点,计算它们与中心点的距离,并且判断是否落在圆的内部。若这些点均匀分布,则圆周率 pi=4 * count/n(count表示落到圆内投点数,n表示总的投点数),python程序如下: 

def calpi():
    n = 1000000
    r = 1.0
    a, b = (0.0, 0.0)
    x_neg, x_pos = a - r, a + r
    y_neg, y_pos = b - r, b + r

    count = 0
    for i in range(0, n):
        x = random.uniform(x_neg, x_pos)
        y = random.uniform(y_neg, y_pos)
        if x*x + y*y <= 1.0:
            count += 1

    print((count / float(n)) * 4)

calpi()

蒙特卡洛方法

MC prediction

对于某种策略π,我们从起始状态s0出发,根据该策略获取状态的轨迹

这里表示t时刻的动作,表示的t时刻的reward。

在MC prediction中主要计算状态价值v(s),根据上一章的Bellman方程

现在我们没有了模型,不知道状态转移即的情况,于是就需要对状态价值函数进行估计。我们将回到价值函数v(x)的定义

由于不知道概率无法求出期望, MC方法就是反复多次试验,求取每一个实验中每一个状态s的值函数,也就是说,只要这个MDP是有终点的,我们就可以计算出每一个状态下的Return,然后利用大数据的力量求出估计值,然后得出策略评估的结果。

在一次试验中,对于某个状态s,可能只经历一次,也可能经历多次,也可能不经历,对于没有经历状态s的实验,在求取s的值函数时直接忽略该次实验就好。那么,对于其他两种情况时,在MC prediction中,计算状态价值有两种方法,第一种是first-visit,第二种是every-visit。

first-visit MC

first-visit在计算状态价值的时候是对于在每个episode中,选取该episode第一次出现状态以后的序列reward值来计算,然后对所有的episode中的状态价值v(s)按照出现次数取平均值

算法参考如下:

every-visit MC

对应的every-visit则返回的是每次以后的序列reward值,然后在全部的episode里面取平均值

MC Control

当有模型时,只需要状态价值就可以确定一个规则,这时只需要选择会引向最好的 reward 和下一个状态的 action 即可,但是在没有模型的时候,单单具有状态价值是不足确定一个规则的,这时就需要明确地知道每个行为价值。因此,当模型未知时,获得 行为价值比状态价值更重要,也就是引入行为价值函数 Q(s, a)。

同样,这里的MC Control也可以分成两种:first-visit MC 与 every-visit MC,其中 first-visit MC 方法是对 (s, a) 的所有 first visits 进行平均,而 every-visit MC 方法是对 (s, a) 的所有 visits 进行平均。

Exploring Starts MC

对于MC来说,经验也就是训练样本的完备性至关重要,因为完备的训练样本才能估计出准确的值函数。但是,正如前面所说的,很多情况下,我们无法保证在多次试验后,可以获得一个较为完备的分布,很可能大部分都是极为相似的试验,导致一部分状态根本无法遍历到,遇到这种情况我们该怎么办呢?很明显,我们需要再MC方法中保证每个状态都能被访问到才行。这时候,就有人提出了,我们不是有起始状态,可以设置一个随机概率,使得所有可能的状态都有一定不为0的概率作为初始状态,这样不就能遍历到每一个状态了吗,这就是Exploring Starts MC的思想。

算法参考如下:

MC control with epsilon-greedy

事实上,上面为了保证 MC 方法的收敛性,我们做了两个假设:我们获得的 episodes 具有 exploring starts,我们可以这样理解,在状态很多的情况下,如果要每一个状态作为起始状态被选中的话,按照随机不为0的概率,可能需要无限次之多。

所以,如果我们不能假设我们可以从任何任意状态开始和采取任意动作,又如何呢?那么只要我们不太贪婪并且多次无限地探索所有状态,那么我们就可以确保收敛,是这样吗?

上述内容本质上是在线策略(on-policy)方法的主要特性之一。在策略方法是要试图改善当前正在运行试验的策略,而离线策略(off-policy)方法则是想试图提升不同于当前运行试验的策略的另一个策略。

有了这个说法,我们借鉴了所谓的 k-摇臂赌博机(ϵ-贪婪方法),简单来说,给定一个状态,我们有 ϵ 概率会从所有动作的均匀分布中选取,有 1-ϵ 的概率选取  动作,伪代码如下

on-policy和off-policy

1.On-policy MC:同策略MC是指产生数据的策略与评估改进的策略是同一个策略。

2.Off-policy MC:离策略是指产生数据策略与评估改进的策略不是同一种策略,离策略方法通常有 2 个或更多智能体,其中一个会生成数据,以让另一个智能体在这些数据上进行优化。当然了,数据也不是随便选择的,而是必须满足一定的条件。这个条件简单说就是:数据生成策略产生的状态要覆盖评估和改进策略的所有可能性。

根据上面离线策略说法,我们就要涉及到了重要度采样,可以这样理解如果 b 选择 a 很多次且 π 也选择 a 很多次,则 b 的行为对确定 π 的行为而言应该是重要的。反过来讲:如果 b 选择 a 很多次且 π 从未选择 a,则 b 在 a 上的行为对 π 在 a 上的行为而言应该没有任何重要性。重要度采样介绍

离线策略伪代码如下

总结

至此我们了解了未知环境下的强化学习,然而在强化学习下的蒙特卡洛方法在实际应用却不多,因为需要每次走完才能得到,从而更新一次。我们能不能每走一步都可以更新一次?下一篇我们将介绍时序差分学习(TD)的Q learning和Sarsa learning。

个人相关深度强化学习github地址:https://github.com/demomagic

PS: 如果觉得本篇本章对您有所帮助,欢迎关注、评论、赞!如果要转发请注明作者和出处

参考文献:

    [1]强化学习总结(4)--蒙特卡洛方法:https://www.cnblogs.com/xiachongkun/p/7767976.html

  • 7
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
蒙特卡罗模拟是一种常见的风险量化方法,可以用于评估投资组合的风险、估计金融工具价格等。以下是一个简单的蒙特卡罗模拟的 C++ 实现及案例: ```c++ #include <iostream> #include <cmath> #include <cstdlib> #include <ctime> using namespace std; double option_price(double S, double K, double r, double sigma, double T, int N) { double dt = T / N; double u = exp(sigma * sqrt(dt)); double d = 1 / u; double p = (exp(r * dt) - d) / (u - d); double **stock_price = new double*[N + 1]; // 存储股票价格的数组 for (int i = 0; i <= N; i++) { stock_price[i] = new double[i + 1]; } stock_price[0][0] = S; for (int i = 1; i <= N; i++) { for (int j = 0; j <= i; j++) { stock_price[i][j] = S * pow(u, j) * pow(d, i - j); } } double **option_value = new double*[N + 1]; // 存储期权价值的数组 for (int i = 0; i <= N; i++) { option_value[i] = new double[i + 1]; } for (int j = 0; j <= N; j++) { option_value[N][j] = fmax(stock_price[N][j] - K, 0); } for (int i = N - 1; i >= 0; i--) { for (int j = 0; j <= i; j++) { option_value[i][j] = exp(-r * dt) * (p * option_value[i + 1][j] + (1 - p) * option_value[i + 1][j + 1]); } } double price = option_value[0][0]; for (int i = 0; i <= N; i++) { delete[] stock_price[i]; delete[] option_value[i]; } delete[] stock_price; delete[] option_value; return price; } double monte_carlo_simulation(double S, double K, double r, double sigma, double T, int N, int M) { double dt = T / N; double sum = 0.0; srand(time(NULL)); for (int i = 0; i < M; i++) { double S_t = S; for (int j = 0; j < N; j++) { double epsilon = ((double) rand() / RAND_MAX - 0.5) * 2.0; S_t = S_t * exp((r - 0.5 * sigma * sigma) * dt + sigma * sqrt(dt) * epsilon); } double payoff = fmax(S_t - K, 0); sum += payoff; } double price = exp(-r * T) * sum / M; return price; } int main() { double S = 100.0; // 股票价格 double K = 100.0; // 行权价格 double r = 0.05; // 无风险利率 double sigma = 0.2; // 波动率 double T = 1.0; // 到期时间 int N = 252; // 模拟的时间步数 int M = 1000000; // 模拟的次数 double option_price_mc = monte_carlo_simulation(S, K, r, sigma, T, N, M); double option_price_bs = option_price(S, K, r, sigma, T, N); cout << "Monte Carlo simulation price: " << option_price_mc << endl; cout << "Black-Scholes formula price: " << option_price_bs << endl; return 0; } ``` 本案例中,我们使用了两种方法来估计一个欧式看涨期权的价格:蒙特卡罗模拟和 Black-Scholes 公式。其中,Black-Scholes 公式是一种解析解,可以直接求出期权价格。而蒙特卡罗模拟则是一种数值方法,通过多次模拟股票价格的随机演化,来估计期权价格。 在本案例中,我们首先实现了一个 Black-Scholes 公式的求解函数 `option_price`,然后实现了一个蒙特卡罗模拟的函数 `monte_carlo_simulation`。最后,我们分别使用这两种方法来估计期权价格,并比较它们的结果。在模拟中,我们使用了 100 万次模拟,并将模拟的时间步数设为 252,即一年的交易日数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值