强化学习与智能代理的深度学习:原理、方法与实践
立即解锁
发布时间: 2025-08-30 01:10:53 阅读量: 12 订阅数: 22 AIGC 

# 强化学习与智能代理的深度学习:从基础到实践
## 1. 强化学习基础
### 1.1 Q 函数与梯度更新
在反向传播过程中,我们会针对 Q 函数的参数计算梯度更新。最后一层的输出是在当前状态下每个可能动作的 Q 值近似值。然而,这种方法存在问题,连续样本学习是不可取的。因为这些样本是相关的,很容易使我们偏离正确方向,就像游戏角色可能会根据周围的即时反馈走错方向一样,这会导致有偏差的样本和负反馈循环。
### 1.2 经验回放
为了解决上述问题,我们可以使用经验回放技术。经验回放本质上是一个记录从状态到动作、奖励再到新状态转换的表格。这个表格就像是网络的经验记忆库,当面临某种情况时可以从中提取信息。在训练过程中,我们从记忆中随机抽取这些转换的小批量数据,让网络学习不同的经验。
### 1.3 策略优化
策略优化方法是 Q 学习和值函数逼近的替代方案。它不是学习状态 - 动作对的 Q 值,而是通过计算梯度直接学习一个将状态映射到动作的策略 π。从根本上说,对于优化问题的搜索,策略方法是从潜在策略动作的随机分布中学习正确策略的一种手段。
在深度强化学习中,每个情节代表一个游戏或任务,而轨迹代表游戏或任务中的玩法或方向。我们可以将轨迹定义为状态、动作和奖励组合的路径,用希腊字母 tau (Τ) 表示。
以机器人学习走路为例,如果使用 Q 学习或其他动态规划方法,算法需要为每个可能轨迹的每个关节运动精确分配奖励,还需要学习时间安排、机器人肢体弯曲的精确角度等。而直接学习策略,算法可以专注于机器人行走时移动脚部的整体任务。
当使用策略梯度方法时,我们可以像 Q 学习一样简单地定义单个策略,即未来折扣奖励的预期总和。因此,网络的目标是最大化某个策略 J,以最大化预期的未来奖励。
学习策略的一种方法是使用梯度方法,即策略梯度。由于我们要找到最大化奖励的策略,所以在潜在策略分布上执行梯度上升(与梯度下降相反)。新神经网络的参数成为我们策略的参数,通过执行梯度上升并更新网络参数,策略得到优化。
策略梯度方法试图增加采取导致最高奖励路径的概率。数学上,标准的策略梯度方法如下:
梯度 g 是梯度的期望值乘以给定动作 - 状态对的策略对数,再乘以优势。优势就是动作值函数减去状态值函数。
然而,在实现中,原始的策略梯度方法仍然存在问题,特别是信用分配问题。当从长时间的交互轨迹中获得的奖励信号在轨迹结束时才出现,策略梯度方法很难确定是哪个动作导致了这个奖励,也难以对该动作进行信用分配。
### 1.4 策略优化的扩展
#### 1.4.1 Reinforce 算法
计算策略梯度的一种常见方法是使用 Reinforce 算法。它是一种蒙特卡罗策略梯度方法,使用似然比来估计给定策略在某一点的值,但该算法可能导致高方差。
#### 1.4.2 近端策略优化(PPO)
原始的策略梯度方法对步长参数非常敏感。步长选择过大,正确的策略会被噪声淹没;步长过小,训练会变得极其缓慢。近端策略优化(PPO)是 OpenAI 在 2017 年发布的一类新的强化学习算法,它通过裁剪损失函数使计算和优化更加有效。
裁剪表达式表明,如果最优策略参数的奖励导致损失超过某个阈值,损失将被裁剪。如果优势 A 的值大于 0,说明某个动作比该状态下所有其他可能动作的平均情况更好,裁剪函数会通过增加奖励来鼓励该动作;如果 A 的值小于 0,则会减少奖励并阻止该动作。本质上,这限制了新策略与旧策略的变化范围,克服了原始策略梯度方法的步长问题。
### 1.5 强化学习总结
强化学习基于智能体在环境中行动并根据周围环境采取行动的概念。智能体的行动由策略优化方法或动态规划方法引导,帮助它学习如何与环境交互。当我们更关注探索和离策略学习时,使用动态规划方法;当面对密集、连续的问题空间且只希望优化我们关心的内容时,使用策略优化方法。
## 2. 智能代理的深度学习
### 2.1 技术要求
在智能代理的深度学习中,我们将使用 Python 3 以及一些常见的 Python 包,如 Numpy、TensorFlow。还需要一台支持 GPU 的计算机,或者一个用于云计算的 AWS 账户。
### 2.2 词嵌入
#### 2.2.1 词嵌入的概念
在处理非结构化的文本数据时,我们使用词嵌入技术。词嵌入本身不是一类预测模型,而是一种预处理文本的方法,使文本能够作为预测模型的输入,或者作为数据挖掘的探索技术。它将单词和句子转换为数字向量,即词嵌入。用于训练嵌入算法的文档或文档组称为语料库,它为嵌入算法提供了词汇表。
#### 2.2.2 传统方法 - 词袋模型
基本的词嵌入技术包括词袋模型,它只关注词频(一个单词在文档中出现的次数)。词袋模型输出一个词频矩阵,矩阵的一行成为一个句子的嵌入。但这种方法不太有效,因为它忽略了语法和词序,会产生非常大的向量。
#### 2.2.3 现代词嵌入方法的优势
现代词嵌入方法的好处是提供紧凑的向量,减少了使用这些向量的模型的计算负担。这些嵌入是文本的低维向量表示,保留了文本的含义和相似性。例如,在一个现代嵌入模型中,“男人”和“女人”的距离应该与“国王”和“女王”的距离相同,保留了单词之间的内在语言关系,甚至可以进行向量运算,如“国王 - 男人 + 女人 = 女王”。
#### 2.2.4 获得词嵌入的方法
有两种获得词嵌入的方法:
- 降维:类似于主成分分析(PCA),可以将句子压缩成更紧凑的表示,便于处理,提高效率。
- 上下文相似性:这种方法保留特定信息以产生更强的类比关系,但效率较低。
这些模型还可以是预测性的,根据训练的预测算法预测一个单词、序列或对;也可以是基于计数的,通过共现关系确定单词关系。在本文中,我们将介绍两种最流行的方法:预测性的 Word2vec 和基于计数的 GloVe。
### 2.3 Word2vec 算法
#### 2.3.1 算法概述
Word2vec 算法是 Tomas Mikolav 在 2013 年谷歌工作时发明的,是最早的现代嵌入方法之一。它是一个浅层的两层神经网络,类似于自编码器,经过训练执行学习自然语言表示的任务,但实际上并不用于执行该任务。它基于分布假设,即每个单词的上下文可以从其相邻单词中找到。
在基本形式下,Word2vec 具有与许多前馈神经网络相似的结构,包括输入层、隐藏层和输出层,所有这些都由矩阵 W 参数化。它逐字遍历输入语料库并为每个单词生成向量。该算法有两种不同的变体:连续词袋(CBOW)模型和跳字模型,它们处理词向量创建的方式不同,在架构上,跳字模型和 CBOW 模型本质上是彼此的反转版本。
#### 2.3.2 跳字模型
跳字模型查看单词序列,试图预测某些单词组合出现的可能性。它根据特定单词预测上下文,输入一个单一字母 w,输出一个单词向量 w1, w2... wn。在训练过程中,模型接收输入单词的独热编码表示。输入层和隐藏层之间的矩阵代表网络正在构建的词汇表,矩阵的行将成为我们的向量。随着新数据流经网络,矩阵逐行更新新的嵌入。这种方法在少量训练数据上效果良好,擅长嵌入稀有单词。
例如,对于句子 “The dog jumped over the fence”,跳字模型将句子解析为:{The dog jumped, The dog over, dog jumped over, dog jumped the .... 等等}
#### 2.3.3 CBOW 模型
CBOW 模型的输入是当前要嵌入单词周围的单词 w1, w2 ... wn,它根据上下文预测单词。CBOW 方法比跳字模型快,更擅长嵌入频繁出现的单词,但由于依赖上下文作为输入,需要大量数据。
对于上述句子,CBOW 方法的处理方式为:{The dog jumped, dog jumped over, jumped over the, over the fence}
#### 2.3.4 训练 Word2vec 模型
由于 Word2vec 模型本身是神经网络,我们可以像训练标准前馈网络一样使用损失函数和随机梯度下降来训练它们。在训练过程中,算法扫描输入语料库并批量输入数据,每次批量后计算损失,优化时我们希望最小化损失。
以下是在 TensorFlow 中创建和训练 Word2vec 模型的步骤:
1. **导入必要的库**:
```python
import numpy as np
import tensorflow as tf
from itertools import compress
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.metrics.pairwise import pairwise_distances
```
2. **导入数据**:
```python
with open('/users/patricksmith/desktop/corpus.txt') as f:
words = [word for line in f.readlines() for word in line.split()]
words = words[:10000]
vocabulary_size = 500
```
3. **编写构建数据集的函数**:
```python
from collections import Counter
def prepareData(words, vocabulary_size=50000):
# 我们使用一个标记 UNK 来替换语料库中的稀有单词
count = [['UNK', -1]]
count.extend(collections.Counter(words).most_common(vocabulary_size - 1))
# 初始化一个字典来存储单词计数
dictionary = dict()
for word, _ in count:
dictionary[word] = len(dictionary)
data = list()
unk_count = 0
# 将单词添加到词汇表中
for word in words:
if word in dictionary:
index = dictionary[word]
else:
index = 0
unk_count += 1
data.append(index)
count[0][1] = unk_count
reverse_dictionary = dict(zip(dictionary.values(), dictionary.keys()))
# 返回数据、高频单词计数和字典
return data, count, dictionary, reverse_dictionary
```
4. **构建跳字模型**:
```python
def skipgram(data, batch_size, num_skips, skip_window):
global data_index
# 将输入数据拆分为批次
batch = np.ndarray(shape=(batch_size), dtype=np.int32)
labels = np.ndarray(shape=(batch_size, 1), dtype=np.int32)
span = 2 * skip_window + 1 # [ skip_window target skip_window ]
# 收集窗口大小内的数据
buffer = collections.deque(maxlen=span)
for _ in range(span):
buffer.append(data[data_index])
data_index = (data_index + 1) % len(data)
# 目标位于缓冲区的中心
for i in range(batch_size // num_skips):
target = skip_window
targets_to_avoid = [ skip_window ]
for j in range(num_skips):
while target in targets_to_avoid:
target = random.randint(0, span - 1)
targets_to_avoid.append(target)
batch[i * num_skips + j] = buffer[skip_window]
labels[i * num_skips + j, 0] = buffer[target]
buffer.append(data[data_index])
data_index = (data_index + 1) % len(data)
return batch, labels
```
5. **构建 CBOW 模型**:
```python
def cbow(data, batch_size, num_skips, skip_window):
batch = np.ndarray(s
```
0
0
复制全文