MachineLearning
Record the basic information of machine learning here
存在reward上升趋势:
c18推荐超参
-LR 0.0001
-pk 3
-c18_k 0.1 # 空惩罚系数
-c18_c 0.9 \ 0.2 # 持奖励折扣
-c18_f ? # 重复动作惩罚值
n_envs: 平衡点2,适当增加可减少训练时间
env = DummyVecEnv([lambda: TradingEnv(self.config)] * self.args.n_envs)
stable-baselines3
pip install stable-baselines3[extra]
https://stable-baselines3.readthedocs.io/en/master/
https://gymnasium.farama.org/v0.28.1/
激活函数
如何理解激活函数:https://zhuanlan.zhihu.com/p/364620596
详细解释:https://blog.csdn.net/hy592070616/article/details/120617176
神经网络游乐场:https://playground.tensorflow.org/
Sigmoid
Sigmoid激活函数是一种常用的神经网络激活函数,它可以将任意实数映射到 [0,1] 之间的一个值。它的数学表达式是:
\[sigmoid(x) = \frac{1}{1+e^{-x}}\]Sigmoid激活函数的优点是它的输出可以表示为概率,它的导数可以用自身表示,它的函数形状接近生物神经元。它的缺点是它的计算量较大,它的输出不是以0为中心的,它容易出现梯度消失的问题。
Tanh
Tanh函数是一种双曲函数,它用于计算给定数字x的双曲正切值。它的数学表达式是:
\[tanh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}}\]Tanh函数可以作为神经网络中的一种激活函数,它解决了Sigmoid函数的不以0为中心输出问题,但仍然存在梯度消失和幂运算的问题。
ReLU
ReLU激活函数是一种常用的非线性激活函数,全称为修正线性单元。它的主要作用是将输入值限制在一个非负的范围内,即当输入值小于0时,输出值为0;当输入值大于等于0时,输出值等于输入值本身。ReLU函数的表达式为:
\[relu(x) = \max(0, x)\]ReLU函数相比于Sigmoid和Tanh等其他激活函数,有以下几个优势:
- ReLU函数可以解决梯度消失问题,因为它在正半区的梯度恒为1,不会随着输入的增大而趋近于0。
- ReLU函数可以加速收敛,因为它在负半区的输出为0,相当于减少了一半的参数,降低了模型的复杂度。
- ReLU函数可以引入稀疏性,因为它会使一部分神经元的输出为0,这样就减少了参数的相互依存关系,缓解了过拟合问题。
ReLU函数也有一些不足之处,主要是:
- ReLU函数在负半区的梯度为0,这可能导致一些神经元永远不被激活,称为神经元死亡问题。
- ReLU函数不是关于原点对称的,这可能导致输出的分布有偏移,影响训练的效率。
为了解决这些问题,人们提出了一些ReLU函数的变种,例如Leaky ReLU, PReLU, ELU等,它们在负半区都给予了一个较小的正梯度,从而避免了神经元死亡的问题,同时也保持了ReLU函数的优点。
Swish or silu
Swish激活函数是一种新型的非线性激活函数,它由谷歌大脑团队于2017年提出。它的数学表达式是:
\[swish(x) = x \cdot \sigma(\beta x)\]其中,$\sigma(x)$ 表示Sigmoid函数, $x$ 为输入, $\beta$ 是一个可学习的参数。 Swish激活函数可以看作是一个带有可学习参数的Sigmoid函数,它的形状类似于ReLU函数,但是具有Sigmoid函数的非线性特性。当 $\beta=0$ 时,Swish激活函数退化为线性函数 $f(x)=x$ ;当 $\beta \rightarrow \infty$ 时,Swish激活函数接近于ReLU函数。
Linear or None
Linear激活函数是一种线性函数,它直接将输入值作为输出值,不进行任何非线性变换。它的数学表达式是:
\[linear(x) = x\]Linear激活函数的优点是计算简单,不会出现梯度消失或爆炸的问题。但是,它的缺点也很明显,就是它没有引入任何非线性因素,无法拟合复杂的数据分布和函数关系。如果只使用Linear激活函数,那么多层神经网络就等价于一个单层神经网络,没有深度学习的意义。 因此,Linear激活函数通常只用于回归问题的输出层,或者二分类问题的输出层(配合sigmoid函数)。在隐藏层,一般使用非线性激活函数,如sigmoid, tanh, relu等,来增强神经网络的表达能力和学习能力。
sigmoid 函数两种实现性能测试
import time
import math
import numpy as np
def sigmoid_math(x):
return 1 / (1 + math.exp(-x))
def sigmoid_numpy(x):
return 1 / (1 + np.exp(-x))
x = np.random.rand(1000000)
start_time = time.time()
for i in x:
sigmoid_numpy(i)
end_time = time.time()
print("sigmoid_numpy 耗时:", end_time - start_time)
start_time = time.time()
sigmoid_numpy(x)
end_time = time.time()
print("sigmoid_numpy narray耗时:", end_time - start_time)
start_time = time.time()
for i in x:
sigmoid_math(i)
end_time = time.time()
print("sigmoid_math 耗时:", end_time - start_time)
输出:
$ ./main.py
sigmoid_numpy 耗时: 0.6583921909332275
sigmoid_numpy narray耗时: 0.008673667907714844
sigmoid_math 耗时: 0.1450803279876709
可以看出虽然numpy是c实现,但是在循环体中调用性能不及math方式。
EvalCallback类中各参数解释
eval_env: 用于评估的环境。
callback_on_new_best: 当找到新的最优模型时触发的回调。
callback_after_eval: 在每次评估后触发的回调。
n_eval_episodes: 在每次评估中测试agent的episode数。
eval_freq: 每次回调之间的timestep数。
log_path: 评估结果保存的路径。
best_model_save_path: 保存最优模型的路径。
deterministic: 在评估时是否使用确定性或随机动作。
render: 在评估时是否渲染环境。
verbose: 回调的详细程度。
warn: 是否在eval_env未被Monitor包装器包装时警告用户。
PPO
stable-baselines PPO算法的各个参数的具体含义如下:
policy: 用于指定策略网络的类型,可以是MlpPolicy, CnnPolicy等,也可以是自定义的网络类,需要继承BasePolicy类。
env: 用于指定环境的名称或对象,需要符合gym风格的接口,即包含reset, step, render等方法。
learning_rate: 用于指定学习率,可以是一个固定的数值,也可以是一个随着训练进度变化的函数。
n_steps: 用于指定每次更新前需要经过的时间步,也就是每次收集多少条轨迹数据后进行一次梯度更新,该参数会影响算法的采样效率和更新频率。
batch_size: 用于指定每次梯度更新时使用的小批量数据的大小,该参数会影响算法的内存占用和并行计算效率。
n_epochs: 用于指定每次梯度更新时对同一批数据重复优化的次数,该参数会影响算法的收敛速度和稳定性。
gamma: 用于指定折扣因子,即对未来奖励的衰减程度,该参数会影响算法对长期回报和短期回报的偏好。
gae_lambda: 用于指定广义优势估计(GAE)中平衡偏差和方差的参数,该参数会影响算法对策略改进的灵敏度和稳健性。
clip_range: 用于指定策略网络参数的裁剪范围,即限制策略改变的幅度,该参数会影响算法对探索和利用的平衡和避免过拟合的能力。
clip_range_vf: 用于指定值函数网络参数的裁剪范围,即限制值函数改变的幅度,该参数会影响算法对值函数估计的准确性和稳定性。
normalize_advantage: 用于指定是否对优势函数进行归一化处理,该参数会影响算法对不同状态下策略改进的权重分配。
ent_coef: 用于指定损失函数中熵项的系数,即对策略熵的惩罚或奖励程度,该参数会影响算法对探索行为的鼓励或抑制程度。
vf_coef: 用于指定损失函数中值函数项的系数,即对值函数误差的惩罚或奖励程度,该参数会影响算法对值函数优化和策略优化的权衡。
max_grad_norm: 用于指定梯度裁剪时的最大梯度范数,即限制梯度下降的步长,该参数会影响算法对学习率敏感度和收敛稳定性。
policy选择
MlpPolicy 是一个多层感知机(MLP)网络,可以处理各种类型的非图像数据,包括离散数据、连续数据和混合数据。
MlpPolicy 是一个具有多个隐藏层的神经网络。每个隐藏层由一个线性层和一个 ReLU 激活函数组成。输出层是一个线性层,用于生成动作概率。
CnnPolicy 是一个卷积神经网络(CNN)网络,用于处理图像数据。
CnnPolicy 是一个具有多个卷积层和池化层的神经网络。卷积层用于提取图像特征,池化层用于降低特征的维度。输出层是一个线性层,用于生成动作概率。
在选择策略网络时,需要考虑以下因素:
数据类型:如果数据是图像数据,则可以使用 CnnPolicy。如果数据是非图像数据,则可以使用 MlpPolicy。
模型复杂度:MlpPolicy 的模型复杂度比 CnnPolicy 低。如果计算资源有限,则可以使用 MlpPolicy。
模型性能:CnnPolicy 通常比 MlpPolicy 具有更好的性能。如果需要获得更好的性能,则可以使用 CnnPolicy。
梯度
策略网络
self.policy_kwargs = dict(net_arch=[128, 128])
obs
/ \
<128> <128>
| |
<128> <128>
| |
policy_net value_net
self.policy_kwargs = dict(net_arch=dict(pi=[256, 256, 256],vf=[128, 256, 128]))
obs
/ \
<256> <128>
| |
<256> <256>
| |
<256> <128>
| |
policy_net value_net
强化学习训练日志指标和参数解释
-----------------------------------------
| rollout/ | |
| ep_len_mean | 2.24e+03 |
| ep_rew_mean | 1.38e+03 |
| time/ | |
| fps | 185 |
| iterations | 298 |
| time_elapsed | 3295 |
| total_timesteps | 610304 |
| train/ | |
| approx_kl | 0.024709977 |
| clip_fraction | 0.11 |
| clip_range | 0.2 |
| entropy_loss | -0.26 |
| explained_variance | 0.936 |
| learning_rate | 0.0003 |
| loss | 0.425 |
| n_updates | 2970 |
| policy_gradient_loss | -0.016 |
| value_loss | 4.92 |
-----------------------------------------
- rollout/ep_len_mean:这是每个回合(episode)的平均长度,即每个回合中执行的平均步数(step)。回合是强化学习中的一个基本概念,指的是智能体(agent)从初始状态开始,与环境(environment)交互,直到达到终止状态的过程。回合长度越长,说明智能体能够在环境中存活越久。
-
rollout/ep_rew_mean:这是每个回合的平均奖励(reward),即每个回合中获得的平均累积奖励。奖励是强化学习中的另一个基本概念,指的是环境对智能体行为的反馈,用来评价行为的好坏。奖励越高,说明智能体表现越好。
- time/fps:这是训练过程中的帧率(frames per second),即每秒钟处理的步数。帧率越高,说明训练速度越快。
- time/iterations:这是训练过程中的迭代次数(iterations),即更新策略(policy)的次数。迭代次数越多,说明训练越充分。
- time/time_elapsed:这是训练过程中消耗的时间(time elapsed),以秒为单位。时间越短,说明训练效率越高。
-
time/total_timesteps:这是训练过程中总共执行的步数(total timesteps),即智能体与环境交互的总次数。步数越多,说明训练数据越多。
- train/approx_kl:这是训练过程中近似的KL散度(approximate Kullback-Leibler divergence),即新旧策略之间的差异程度。KL散度是一种衡量两个概率分布相似性的指标,越小说明越相似。在某些强化学习算法中,KL散度可以用来控制策略更新的步长,避免更新过大导致不稳定。
- train/clip_fraction:这是训练过程中被裁剪(clipped)的梯度比例(gradient ratio)。在某些强化学习算法中,为了防止策略更新过大,会对梯度进行裁剪,即限制梯度在一个范围内。裁剪比例越高,说明更新幅度越大。
- train/clip_range:这是训练过程中梯度裁剪的范围(gradient clipping range)。它是一个超参数(hyperparameter),可以根据实验效果进行调整。
- train/entropy_loss:这是训练过程中的熵损失(entropy loss),即策略熵(policy entropy)的相反数。熵是一种衡量不确定性的指标,越高说明越不确定。在某些强化学习算法中,为了增加策略的探索性(exploration),会给目标函数加上一个熵项,使得策略更倾向于选择不确定性高的行为。熵损失越低,说明策略更多样化。
- train/explained_variance:这是训练过程中的可解释方差(explained variance),即价值函数(value function)对回报(return)的预测准确度。可解释方差是一种衡量回归模型拟合效果的指标,越接近1说明越准确。
- train/learning_rate:这是训练过程中的学习率(learning rate),即梯度下降法中更新参数的速率。它也是一个超参数,可以根据实验效果进行调整。
- train/loss:这是训练过程中的总损失(total loss),即目标函数(objective function)的值。损失越小,说明模型性能越好。
- train/n_updates:这是训练过程中的更新次数(update times),即更新参数的次数。更新次数越多,说明训练越充分。
- train/policy_gradient_loss:这是训练过程中的策略梯度损失(policy gradient loss),即基于策略梯度法优化策略时产生的损失。策略梯度法是一种强化学习算法,它通过直接优化策略来提高期望奖励。策略梯度损失越小,说明策略性能越好。
- train/value_loss:这是训练过程中的价值损失(value loss),即基于最小二乘法优化价值函数时产生的损失。价值函数是一种估计未来回报的函数,在某些强化学习算法中,它可以辅助策略优化或者直接作为输出。价值损失越小,说明价值函数越准确。
tensorRT
安装
pip install --extra-index-url https://pypi.nvidia.com tensorrt-libs
pip install --extra-index-url https://pypi.nvidia.com tensorrt
stable-diffusion
webui
命令仓库:
https://github.com/camenduru/stable-diffusion-webui-colab
启动命令:
https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Command-Line-Arguments-and-Settings
--share --listen --enable-insecure-extension-access
扩展
汉化扩展:https://github.com/hanamizuki-ai/stable-diffusion-webui-localization-zh_Hans
图库浏览器扩展:https://github.com/AlUlkesh/stable-diffusion-webui-images-browser
提示词自动补全扩展:https://github.com/DominikDoom/a1111-sd-webui-tagcomplete.git -> 汉化提示词(复制到extensions\a1111-sd-webui-tagcomplete\tags目录):http://www.123114514.xyz/d/WebUI/Tag/a1111-sd-webui-tagcomplete.zip
反推提示词(tagg):https://github.com/toriato/stable-diffusion-webui-wd14-tagger -> 要重启命令才生效
controlnet: https://github.com/Mikubill/sd-webui-controlnet -> 模型文件(复制到models\ControlNet目录):https://huggingface.co/lllyasviel/ControlNet-v1-1/tree/main
3D Openpose Editor: https://github.com/nonnonstop/sd-webui-3d-open-pose-editor (在线直接使用)
神经网络模型可视化
神经网络图例:https://www.asimovinstitute.org/neural-network-zoo/
在tensorboard里可视化 StableBaselines3 的模型网络结构
Stable-Baselines3 默认支持 TensorBoard,但它不直接支持在 TensorBoard 中可视化模型网络结构。要在 TensorBoard 中可视化模型网络结构,可以使用 PyTorch 的 SummaryWriter
类。以下是一个示例:
首先,确保安装了所需的库:
pip install stable-baselines3 tensorboard
然后,你可以使用以下代码在 TensorBoard 中可视化模型网络结构:
import os
import torch
from torch.utils.tensorboard import SummaryWriter
from stable_baselines3 import PPO
from stable_baselines3.common.vec_env import DummyVecEnv
from stable_baselines3.common.env_util import make_atari_env
# 创建 Atari 游戏环境
env_id = "BreakoutNoFrameskip-v4"
env = make_atari_env(env_id, n_envs=1, seed=0)
env = DummyVecEnv([lambda: env])
# 使用 PPO 算法训练模型
model = PPO("CnnPolicy", env, verbose=1)
# 获取模型的神经网络
policy_net = model.policy.to("cpu")
# 为可视化创建一个虚拟输入
dummy_input = torch.randn(1, *env.observation_space.shape)
# 设置 TensorBoard 日志目录
log_dir = "tensorboard_logs"
os.makedirs(log_dir, exist_ok=True)
# 使用 PyTorch 的 SummaryWriter 将模型网络结构写入 TensorBoard
writer = SummaryWriter(log_dir)
writer.add_graph(policy_net, dummy_input)
writer.close()
这段代码首先创建一个 Atari 游戏环境,然后使用 PPO 算法训练模型。接下来,它获取模型的神经网络并将其转换为 CPU 设备。然后,它创建一个虚拟输入。接下来,它设置 TensorBoard 日志目录并使用 PyTorch 的 SummaryWriter
将模型网络结构写入 TensorBoard。
要查看 TensorBoard 中的模型网络结构,请在命令行中运行以下命令:
tensorboard --logdir tensorboard_logs
然后,在浏览器中打开显示的 URL(通常为 http://localhost:6006
),并导航到 “Graphs” 标签以查看模型网络结构。
请注意,这个示例使用了 PPO 算法和 Atari 游戏环境。你可以根据需要替换为其他算法和环境。
PyTorch 自带的可视化工具 torchviz
Windows下安装
首先pip安装:
pip install graphviz
pip install torchviz
然后安装 GraphViz 工具:
下载地址:https://graphviz.org/download/
建议用exe文件安装,安装时勾选添加graphviz路径到系统PATH环境变量中。
如果是在 git-bash 环境下,安装完成后环境变量不会自动导入,需要手动指定 或者 重启电脑即可。
安装完成后,可以在命令行终端输入dot -version验证是否已成功安装Graphviz。如果成功安装,会输出Graphviz的版本信息。
使用案例:
...
outputs = self.model(X_train)
if self.args.show_model:
# 可视化模型结构
from torchviz import make_dot
make_dot(outputs, params=dict(self.model.named_parameters())).view()
exit()
...
Windows 安装CUDA
从NVIDIA官网下载CUDA的安装包
CUDA Toolkit下载地址: https://developer.nvidia.com/cuda-downloads
Windows 下 pytoch CUDA安装
从pytorch官网下载对应CUDA版本: https://pytorch.org/get-started/locally/
WSL2安装CUDA
安装好WSL2前提下执行
1.在Windows下安装显卡驱动
CUDA on WSL 驱动下载地址:https://developer.nvidia.com/cuda/wsl
2.WSL2中安装CUDA
CUDA工具箱下载地址: https://developer.nvidia.com/cuda-downloads
可以使用以下命令来验证CUDA是否已经安装:
nvcc --version
如果输出类似于以下内容,则表示CUDA已成功安装:
nvcc: NVIDIA (R) Cuda compiler driver
nvcc命令not found
查看cuda的bin目录下是否有nvcc
ls -alh /usr/local/cuda/bin
如果存在,直接将cuda路径加入系统路径即可:
vim ~/.bashrc进入配置文件,添加以下两行:
export PATH=/usr/local/cuda/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH
WSL2下Ubuntu的Docker中使用CUDA
基本的Docker镜像托管在 https://hub.docker.com/r/nvidia/cuda
原始项目位于 https://gitlab.com/nvidia/container-images/cuda
1.Nvidia Container Toolkit安装
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update
确保拿到源信息:cat /etc/apt/sources.list.d/nvidia-docker.list
deb https://nvidia.github.io/libnvidia-container/stable/ubuntu18.04/$(ARCH) /
#deb https://nvidia.github.io/libnvidia-container/experimental/ubuntu18.04/$(ARCH) /
deb https://nvidia.github.io/nvidia-container-runtime/stable/ubuntu18.04/$(ARCH) /
#deb https://nvidia.github.io/nvidia-container-runtime/experimental/ubuntu18.04/$(ARCH) /
deb https://nvidia.github.io/nvidia-docker/ubuntu18.04/$(ARCH) /
安装 nvidia-container-toolkit 软件包 (或者安装 nvidia-docker2 试试 https://github.com/NVIDIA/nvidia-docker):
apt-get install nvidia-container-toolkit
验证是否正确安装了 nvidia-container-toolkit。您可以使用以下命令检查版本号:
dpkg -l | grep nvidia-container-toolkit
确保 nvidia-container-runtime 文件被创建
# ls -alh /usr/bin/nvidia-container-runtime
-rwxr-xr-x 1 root root 3.0M Apr 24 20:26 /usr/bin/nvidia-container-runtime*
2.配置NVIDIA容器运行时
使用命令:
nvidia-ctk runtime configure
加载(或创建)一个/etc/docker/daemon.json文件,并确保NVIDIA容器运行时被配置为名为nvidia的运行时。
cat /etc/docker/daemon.json
{
"default-runtime": "nvidia",
"runtimes": {
"nvidia": {
"args": [],
"path": "nvidia-container-runtime"
}
}
}
3.重启docker
ps -ef | grep dockerd
kill <dockerd pid>
nohup sh -c "dockerd &"
验证docker使用了nvidia容器运行时:
docker info|grep nvidia
或使用容器跑nvidia-smi命令
docker run -it --gpus=all --rm nvidia/cuda:11.4.2-base-ubuntu20.04 nvidia-smi