简介《强化学习的数学原理》是西湖大学赵世钰教授撰写的英文专著面向具备线性代数、概率论与优化基础的研究生及算法工程师系统解决强化学习理论理解不深、数学推导脱节、算法原理模糊等核心痛点。全书以马尔可夫决策过程为起点逐章深入状态值与贝尔曼方程、最优策略与贝尔曼最优方程、值迭代与策略迭代、蒙特卡洛与时间差分方法、策略梯度与Actor-Critic框架并在附录中严谨论证序列收敛性辅以网格世界等直观示例和矩阵-向量形式的数学表达显著提升理论可读性与可计算性。资源为单文件PDF共1个18.9MB高清电子书内容完整覆盖10章正文与附录排版规范、公式清晰、章节逻辑严密便于精读推导与课堂讲义参考。目前已有845人学习下载适合希望夯实RL数学根基、开展理论研究或复现经典算法的学习者。1. 这不是又一本“调库跑通就完事”的强化学习书它用网格世界手推公式把贝尔曼方程、值迭代、策略梯度这些黑匣子全拆开给你看透你有没有试过照着《动手学强化学习》跑通一个 CartPole但一看到论文里“由贝尔曼最优方程导出的策略梯度定理”就卡住不是代码报错是根本不知道那个 ∇θ log πθ(a|s) 是从哪冒出来的更别说为什么它能和 Qπ(s,a) 相乘后还能无偏估计策略梯度。这不是你数学差——是绝大多数中文资料跳过了最关键的“数学缝合点”从马尔科夫决策过程MDP的定义到贝尔曼方程的构造再到策略改进定理的证明中间每一步的逻辑断层都被默认用“读者自行脑补”填平了。而赵世钰老师这本《Mathematical Foundations of Reinforcement Learning》就是专治这种“知道怎么写代码、但不知道为什么这么写”的认知断层。它不讲 PyTorch API不堆 RLlib 配置项而是用一个贯穿全书的 4×4 网格世界grid world从第 13 页第一个状态转移概率表开始手把手推导每一个贝尔曼方程的矩阵形式、每一次值迭代的收敛边界、每一轮策略梯度更新的期望偏差来源。它假设你懂线性代数和概率论基础附录 A/B/C 已帮你温习但绝不假设你“应该懂”随机近似中的 Dvoretzky 收敛定理——第 6 章整整 23 页就为讲清楚为什么 SGD 在非凸目标下仍能收敛。这本书不是让你“学会用强化学习”而是让你在调试一个 diverging 的 Actor-Critic 损失时能立刻反应过来“哦这里没做 baseline 减法导致梯度方差爆炸得回 Chapter 10.2.1 看 A2C 的 baseline 不变性证明”。它适合三类人刚学完《统计学习方法》想啃 RL 数学内核的研究生在工业界用 PPO 调参半年却总被问“为什么 clip ratio 设 0.2”的算法工程师还有那些翻遍 Sutton 书评却还在纠结“off-policy 和 on-policy 的本质区别到底在测度空间还是策略空间”的理论爱好者。它不承诺“7 天速成”但它保证当你合上第 10 章最后一页再看到任何一篇顶会论文里的 policy gradient theorem你第一反应不再是复制公式而是下意识去检查它的假设条件是否满足——这才是真正把强化学习从“玄学调参”变成“可验证工程”的起点。2. 把贝尔曼方程从黑板公式变成可执行的数值解状态值计算的两种路径与矩阵实现细节2.1 为什么必须先手算一个 4×4 网格世界的贝尔曼方程翻开第 2 章第 1 节你会看到一个看似简单的 4×4 网格世界起始状态 s₀ 在左上角目标状态 sₜ 在右下角每个格子有上下左右四个动作碰到边界则停留并获得 -1 奖励到达目标获得 10 奖励。这个例子绝非教学摆设。它被刻意设计成状态数足够小16 个、动作数固定4 个、转移概率完全已知确定性边界反射从而让所有数学对象都能显式写出——这是后续所有算法可验证性的基石。比如在 2.6 节“Matrix-vector form of the Bellman equation”中作者直接给出状态转移矩阵 P ∈ ℝ¹⁶ˣ¹⁶ 和奖励向量 r ∈ ℝ¹⁶其中 P[i,j] Pr(s′j | si, a↑)r[i] 是在状态 i 执行任意动作的即时奖励期望。这种显式构造使得你能在 Python 中用不到 20 行代码复现整个贝尔曼算子 T^π(v) r γPvimport numpy as np # 构建 4x4 网格世界的状态索引映射(row, col) - state_id def state_to_id(row, col): return row * 4 col # 初始化转移矩阵 P (16x16) 和奖励向量 r (16,) P np.zeros((16, 16)) r np.full(16, -1.0) # 默认碰壁惩罚 r[state_to_id(3, 3)] 10.0 # 目标状态奖励 # 填充 P以向上动作为例其他方向同理 for row in range(4): for col in range(4): s state_to_id(row, col) if row 0: # 顶部边界向上仍停留在原地 s_next s else: s_next state_to_id(row-1, col) P[s, s_next] 1.0 # 确定性转移 # 定义贝尔曼算子 T^π(v) r γ * P v def bellman_operator(v, gamma0.9): return r gamma * P v # 初始状态值向量全零 v np.zeros(16) # 迭代一次 v_new bellman_operator(v) print(第一次迭代后状态值 v[0]起始状态:, v_new[0])提示这段代码的关键不在运算符而在P的构造逻辑。P[s, s_next] 1.0显式体现了 MDP 的核心假设——状态转移是马尔可夫的、且由策略 π 决定。如果你把P换成随机策略下的加权平均如 π(a↑)0.25P就变成了策略依赖的P^π这正是 2.7.2 节“Iterative solution”中值迭代收敛的起点。没有这个显式矩阵你永远只能模糊地说“贝尔曼方程把当前值和未来值联系起来”而无法在调试时定位到底是γ设太大导致振荡还是P的某一行没归一化导致概率泄露。2.2 闭式解 vs 迭代解何时该用 (I − γP)^−¹何时必须迭代2.7.1 节给出了状态值的闭式解v^π (I − γP^π)⁻¹ r^π。这看起来很美但实际落地时它是一把双刃剑。我们来对比两种求解路径求解方式适用场景计算复杂度数值稳定性可解释性闭式解(I − γP)^−¹ r状态数 ≤ 1000P 稀疏且良态O(n³) 矩阵求逆对γ接近 1 敏感易因条件数大而失真直观显示 v^π 是 r 的线性变换便于分析扰动影响迭代解v_{k1} r γP v_k任意规模尤其适合稀疏 P 或函数逼近O(n²) 每轮收敛轮数取决于 γ鲁棒性强天然带阻尼清晰展示收敛轨迹可监控每轮误差 实践中我一般会强制自己先跑一遍闭式解哪怕只用于 16 状态的小世界目的不是为了结果而是为了校验 P 和 r 的构造是否正确。如果np.linalg.inv(np.eye(16) - 0.9 * P) r算出的v[0]是负无穷或 nan那一定是P的某一行没归一化比如边界状态的自循环概率没设为 1。而迭代解则是真正的主力——第 4 章的值迭代Value Iteration和策略迭代Policy Iteration全部基于此。注意 2.7.2 节强调的收敛判据||v_{k1} − v_k||_∞ ε。这个无穷范数max norm比 L2 范数更严格因为它要求所有状态的值更新都小于阈值避免了某些状态值已收敛、另一些却还在大幅震荡的假收敛现象。这也是为什么你在实现 VI 时看到的终止条件总是np.max(np.abs(v_new - v)) 1e-6而不是np.linalg.norm(v_new - v)。2.3 从状态值 v(s) 到动作值 q(s,a)贝尔曼方程的升维与策略解耦2.8 节是全书第一个关键跃迁把价值函数从状态空间v(s)扩展到状态-动作对空间q(s,a)。这步看似只是多了一个维度实则彻底改变了策略优化的范式。v(s)描述的是“在状态 s 下按策略 π 行动的长期收益”而q(s,a)描述的是“在状态 s 下先执行动作 a再按策略 π 行动的长期收益”。这个“先执行 a”的操作把策略 π 从价值计算中暂时剥离使得q(s,a)成为一个策略无关的评估工具——你甚至可以评估一个你从未打算执行的策略比如在悬崖行走环境中评估“向悬崖跳”这个动作。其贝尔曼方程为q^π(s,a) Σ_{s} P(s|s,a) [ r(s,a,s) γ Σ_{a} π(a|s) q^π(s,a) ]这个公式在 2.8.2 节被重写为矩阵形式但更重要的是它的实践含义q(s,a)允许你做策略改进policy improvement。第 3 章的贝尔曼最优方程q*(s,a) Σ_{s} P(s|s,a)[r(s,a,s) γ max_{a} q*(s,a)]本质上就是说最优动作a*就是让q*(s,a)最大的那个a。这直接催生了 Q-learning第 7.4 节——它不再需要知道P和r只需用采样得到的(s,a,r,s)元组通过q(s,a) ← q(s,a) α[r γ max_{a} q(s,a) − q(s,a)]来逼近q*。所以如果你现在还在用v(s)做策略选择比如argmax_a Σ_s P(s|s,a) v(s)说明你还没真正跨过从“状态价值”到“动作价值”的门槛。而这本书用整整一节2.8和三个示例2.8.1把这个门槛踩实了。3. 贝尔曼最优方程不是终点而是策略改进的起点BOE 的收缩性证明与最优策略存在性验证3.1 为什么“最优策略存在”这件事需要被严格证明初学者常误以为“最优策略”是天经地义的——既然每个策略都有一个性能指标 J(π)那取最大值的那个 π* 当然存在。但数学上这远非显然。J(π) 的定义是E_π[Σ_t γ^t r_t]这是一个在无限维策略空间上的泛函且策略 π 本身是一个从状态到动作分布的映射即 π: S → Δ(A)。如果没有额外约束这个最优化问题可能没有解例如J(π) 上确界可达但无对应策略或解不唯一。第 3 章开篇3.1 节用一个精巧的网格世界反例直击要害当折扣因子 γ1即不打折且存在零成本循环路径时J(π) 可能发散此时“最优”失去意义。因此3.2 节明确给出最优策略存在的充分条件有限状态/动作空间 0 ≤ γ 1。这个看似简单的条件背后是第 3.3.3 节“Contraction mapping theorem”的支撑——它证明了贝尔曼最优算子T*是一个压缩映射contraction mapping从而保证其不动点q*存在且唯一。这个证明不是炫技而是你后续所有算法收敛性分析的根基。比如Q-learning 的收敛性7.4.3 节直接引用了T*的压缩性而 DQN 的稳定性分析8.4.1 节则依赖于T*在神经网络参数空间上的近似压缩性。如果你跳过这一章那么当你的 DQN 在训练后期 loss 突然飙升时你只会归咎于“学习率太大”而不会想到去检查γ是否设为 0.999接近 1 导致压缩系数γ过小收敛变慢且易受噪声干扰。3.2 贝尔曼最优方程BOE的矩阵形式如何把max操作嵌入线性代数框架3.3.2 节将 BOE 写成矩阵形式q* r γ P max_{a} q*这里的max_{a}是一个非线性操作无法像P^π那样直接写成矩阵乘法。作者没有回避这个难点而是引入了策略相关矩阵P^π的集合对每个策略 π定义P^π则T* q max_π { r γ P^π q }。这个表达式揭示了 BOE 的本质——它不是一个固定算子而是所有策略对应的贝尔曼算子T^π的上包络upper envelope。这意味着求解q*等价于在所有T^π中找到那个能产生最大q值的π。这个视角直接导向了第 4 章的策略迭代Policy Iterationπ_{k1}(s) argmax_a q^{π_k}(s,a)。PI 的每一轮都在用当前q^{π_k}去“投票”选出下一个更好的π_{k1}而 BOE 的压缩性保证了这个投票序列必然收敛到π*。在代码实现中这个argmax_a就是np.argmax(q_table[s, :])但它的数学重量远不止这一行代码。它意味着策略改进不是启发式搜索而是 BOE 压缩性在离散策略空间上的自然投影。3.3 收缩映射定理Contraction Mapping Theorem的实操解读为什么γ是收敛的命门3.3.3 节的收缩映射定理是本书的数学心脏。它说若算子T满足||T u − T v|| ≤ γ ||u − v||γ ∈ [0,1)则T有唯一不动点且迭代u_{k1} T u_k必收敛。在 BOE 中T*的收缩系数就是折扣因子γ。这个γ不仅控制着未来奖励的衰减更直接决定了算法收敛的速度和鲁棒性。我们来量化这个影响γ值收缩系数迭代收敛所需轮数估算对采样噪声的敏感度典型适用场景0.80.8~15 轮达到1e-3误差低噪声被快速衰减简单控制任务如 GridWorld0.990.99~450 轮才能达到同等精度高早期噪声持续影响长期规划任务如机器人导航0.9990.999~4500 轮极易发散极高需极强正则化理论分析极少用于实践这个表格不是凭空而来它来自定理中收敛速率的显式界||q_k − q*|| ≤ γ^k / (1−γ) ||q_0 − T* q_0||。当γ0.999时γ^k衰减极慢分母1−γ0.001又极小导致初始误差被放大千倍。这就是为什么你在实现 Q-learning 时如果γ设为 0.999 却没配合适当的 learning rate decay 或 target networkloss 曲线一定会出现剧烈震荡。而这本书在 3.3.4 节专门证明了T*确实满足收缩性其系数就是γ——它不是经验参数而是数学定理的输入变量。理解这一点你就不会再盲目调γ而是会先问“我的任务 horizon 是多少γ^H是否已衰减到可忽略如 0.01”。4. 值迭代与策略迭代不只是两个算法而是“评估-改进”范式的两种实现哲学与收敛性边界4.1 值迭代VI用单个算子T*同时完成评估与改进的极致简化4.1 节的值迭代算法表面看只有一行核心q_{k1}(s,a) ← Σ_{s} P(s|s,a)[r(s,a,s) γ max_{a} q_k(s,a)]。但这行代码承载着一种深刻的工程哲学放弃对中间策略 π 的显式表示只追踪价值函数q让max操作隐式地完成策略改进。VI 的优势在于简洁和内存效率——你只需要维护一个|S|×|A|的q表无需存储策略π。但它的代价是收敛轮数多。因为每次迭代q_k只向q*靠拢γ的距离而策略π_k的变化是滞后的。在 4.1.2 的示例中作者用 4×4 网格世界展示了即使q值已基本稳定||q_{k1}−q_k||1e-5π_k可能仍在微调。这在实践中意味着如果你用 VI 训练一个智能体并在q收敛后立即部署π(s)argmax_a q(s,a)它可能是次优的因为q的微小误差会被argmax放大。这也是为什么 VI 更适合离线规划如机器人路径规划而非在线学习。4.2 策略迭代PI显式分离评估Policy Evaluation与改进Policy Improvement的稳健路径4.2 节的策略迭代则是另一种哲学承认评估和改进是两个独立且可优化的步骤。PI 的循环是评估固定π_k用迭代法2.7.2求解v^{π_k}或q^{π_k}直到收敛改进用π_{k1}(s) argmax_a q^{π_k}(s,a)更新策略。这个分离带来了两大好处收敛轮数少、策略单调提升。4.2.1 节的算法分析指出PI 的策略序列π_0, π_1, ...满足J(π_0) ≤ J(π_1) ≤ ... ≤ J(π*)即每一步都严格不降。这源于改进步骤的贪婪性π_{k1}在每个状态s都选择了比π_k更优的动作。但在实践中“评估”步骤的“直到收敛”是个陷阱。4.2.2 节明确指出完全收敛的评估是奢侈的通常只需几轮迭代即可获得足够好的q^{π_k}来进行有效改进。这直接引出了 4.3 节的截断策略迭代Truncated PI——它规定评估只做m轮如m1就是著名的“值迭代”然后改进。这揭示了一个深刻事实VI 和 PI 并非对立而是m的连续统m∞是经典 PIm1是 VIm3~5是工业界常用的折中。我在某跨平台系统中实现 PI 时就固定m3既避免了 PI 的长评估耗时又比 VI 的策略更新更稳健。4.3 截断策略迭代Truncated PI在收敛速度与计算开销间找平衡点的工程艺术4.3.1 节的对比表格清晰列出了 VI、PI、Truncated PI 的特性。但真正决定你选哪个的是你的计算瓶颈在哪。如果状态空间巨大如图像输入P和r不可得你必须用采样Monte Carlo 或 TD此时 VI 的max操作无法执行PI 的评估步骤也无从谈起——这正是第 5、7 章要解决的问题。但如果是在已知模型的中小规模问题如资源调度、游戏 AITruncated PI 往往是最佳选择。它的伪代码4.3.2非常简单for k 0,1,2,... until convergence: # Truncated Policy Evaluation: run m iterations of v_{i1} r γ P^{π_k} v_i v v^{π_k} # initial guess for i 1 to m: v r γ P^{π_k} v # Policy Improvement π_{k1}(s) argmax_a Σ_{s} P(s|s,a)[r(s,a,s) γ v(s)]这里的m是关键超参。m1就是 VIm∞是 PIm2~4是黄金区间。我一般会先用m1即 VI跑通 baseline然后逐步增加m监控J(π_k)的提升幅度。一旦J(π_{k1}) − J(π_k)的增量小于1e-3就停止增加m。这个过程本质上是在用计算资源购买策略质量而这本书给了你精确衡量这笔交易的数学标尺。5. 避坑指南强化学习数学推导中最容易翻车的五个边界情况与血泪排查记录5.1 现象贝尔曼方程迭代v_{k1} r γ P v_k发散v值爆炸增长原因γ设置过大≥1或P矩阵未归一化某行元素和 ≠ 1。γ ≥ 1违反了收缩映射定理的前提P行和不为 1 意味着概率泄露导致P^k的谱半径 1γ^k P^k项不衰减。解决首先用np.allclose(P.sum(axis1), 1.0)检查P其次确保0 ≤ γ 1若任务需长视界优先调小 learning rate 而非增大γ最后打印np.linalg.eigvals(P)确认其最大特征值模长 ≤ 1。5.2 现象策略迭代PI中π_{k1}与π_k完全相同但J(π_k)未达理论最优值原因策略评估Policy Evaluation未充分收敛。v^{π_k}的近似误差导致argmax_a q^{π_k}(s,a)选出了错误动作而该错误动作恰好又使π_{k1} π_k形成局部最优陷阱。解决提高评估迭代轮数m或改用更鲁棒的评估方法如在v更新中加入 dampingv_{i1} (1−β) v_i β (r γ P^{π_k} v_i)β0.1最根本的是用q^{π_k}而非v^{π_k}进行改进因为q直接关联动作。5.3 现象蒙特卡洛MC方法估计的q(s,a)方差极大学习曲线剧烈抖动原因MC 使用完整 episode 的回报G_t作为q(s,a)的无偏估计但G_t方差随 episode 长度指数增长尤其γ接近 1 时。单个 episode 的随机性被全额传递给梯度。解决采用 MC Exploring Starts5.3 节确保所有(s,a)对被充分访问或转向 TD 方法7.1 节用 bootstrapping 降低方差在函数逼近场景8.2 节务必使用 experience replay 和 target network 来稳定训练。5.4 现象Q-learning 更新q(s,a) ← q(s,a) α[r γ max_{a} q(s,a) − q(s,a)]中max_{a} q(s,a)总是选到同一个动作探索停滞原因q值初始化偏差或学习率α过小导致q值在早期就形成“强者恒强”的马太效应或ε-greedy的ε衰减过快5.4 节。解决q表初始化为小随机数如np.random.randn(|S|,|A|)*0.01而非全零ε衰减采用线性或指数衰减确保在训练后期仍有ε 0.01在 7.4.2 节“Off-policy vs on-policy”中作者强调 Q-learning 的 off-policy 特性允许你用ε-greedy行为策略收集数据但用greedy目标策略更新这本身就是一种探索保障。5.5 现象策略梯度REINFORCE, 9.4 节训练中梯度∇_θ log π_θ(a|s) * G_t的方差导致 loss 不下降甚至上升原因G_t是高方差的回报估计直接相乘放大了梯度噪声且log π_θ(a|s)在π_θ(a|s)极小时会产生极大梯度数值不稳定。解决引入 baselineb(s)用G_t − b(s)替代G_t10.2.1 节 A2C 的核心b(s)可用状态值函数v_φ(s)近似这就是 Actor-Critic 的起源同时对π_θ使用 softmax 输出并添加 entropy regularization 项−β H(π_θ(·|s))来鼓励探索防止π_θ(a|s)趋近于 0。6. 用“策略梯度定理”的原始推导反向验证你写的每一行 PPO 代码从 REINFORCE 到 A2C 的数学一致性检验6.1 REINFORCE 的梯度公式∇_θ J(θ) E_π[∇_θ log π_θ(a|s) · G_t]是怎么来的9.3 节花了整整 12 页9.3.1 9.3.2推导这个公式其核心是交换期望与梯度的顺序。J(θ) E_{τ∼π_θ}[R(τ)]其中τ(s₀,a₀,s₁,a₁,...)是轨迹R(τ)Σ_t γ^t r_t。关键一步是将轨迹τ的概率p(τ|θ)拆解为p(s₀) Π_t π_θ(a_t|s_t) p(s_{t1}|s_t,a_t)。由于p(s₀)和p(s_{t1}|s_t,a_t)与θ无关它们的梯度为 0只剩下∇_θ log π_θ(a_t|s_t)项。最终得到∇_θ J(θ) Σ_τ p(τ|θ) R(τ) ∇_θ log p(τ|θ) Σ_τ p(τ|θ) R(τ) Σ_t ∇_θ log π_θ(a_t|s_t) E_{τ∼π_θ}[ Σ_t ∇_θ log π_θ(a_t|s_t) · R(τ) ]而R(τ)从t开始的部分就是G_t故得 REINFORCE。这个推导的魔鬼细节在于G_t是从时间t开始的回报不是R(τ)的全部。这意味着在代码中你不能用G_0去更新所有t的梯度而必须对每个(s_t,a_t)对用对应的G_t。这是新手写 REINFORCE 时最常见的错误——用 episode 总回报G_0更新所有时间步的策略参数导致梯度污染。6.2 A2C 的 baselineb(s_t) v_φ(s_t)如何做到“减小方差而不引入偏差”10.2.1 节的“Baseline invariance”是策略梯度方法的基石。它证明对任意函数b(s)∇_θ J(θ) E_π[∇_θ log π_θ(a|s) · (G_t − b(s))]依然成立。因为E_π[∇_θ log π_θ(a|s) · b(s)] b(s) · E_π[∇_θ log π_θ(a|s)] b(s) · ∇_θ E_π[1] 0E_π[1]1是常数。所以b(s)的加入不改变期望值无偏但能显著降低方差。最优的b(s)是E_π[G_t | s_ts] v^π(s)即状态值函数。A2C10.2.2 节正是用一个神经网络v_φ(s)来近似v^π(s)并在每个(s_t,a_t)更新时计算advantage G_t − v_φ(s_t)再用∇_θ log π_θ(a_t|s_t) · advantage更新策略网络。这个advantage就是“优势函数”它回答了“在这个状态下执行这个动作比平均好多少”。在代码中这意味着你必须同步训练两个网络Actor输出π_θ(a|s)和 Critic输出v_φ(s)且 Critic 的 loss 是MSE(v_φ(s_t), G_t)。漏掉 Critic 或用G_t直接更新 Actor就退化成了高方差的 REINFORCE。6.3 从数学一致性看 PPO 的clip操作它如何在策略梯度框架下保证更新的安全性PPOProximal Policy Optimization虽未在本书中详述但其核心思想根植于第 9、10 章。PPO 的clip操作min(r_t(θ) A_t, clip(r_t(θ), 1−ε, 1ε) A_t)本质是对策略比率r_t(θ) π_θ(a_t|s_t)/π_θ_old(a_t|s_t)施加硬约束防止单步更新过大。这对应于策略梯度定理中一个隐含假设π_θ与π_θ_old足够接近使得∇_θ log π_θ ≈ ∇_θ log π_θ_old。当r_t(θ)远离 1 时该线性近似失效梯度方向可能错误。PPO 的clip就是人为制造一个“信任区域”确保更新在局部有效。从本书视角看PPO 是对 REINFORCE 和 A2C 的工程加固它保留了advantage的低方差优势来自 Critic又通过clip规避了策略更新过大的风险。所以当你调试 PPO 时如果发现clip激活率ratio被裁剪的比例持续 50%说明ε太小或learning_rate太大应优先调大ε如从 0.1 到 0.2或减小learning_rate而不是盲目增加advantage的 scale。从那以后我每次写策略梯度代码都会强制走一遍这个流程先手推一遍∇_θ J(θ)的原始表达式确认G_t的时间下标是否匹配再检查advantage计算中v_φ(s_t)是否用了当前 Critic 的输出而非 target最后用 np.histogram(ratio, bins本文还有配套的精品资源点击获取