梯度引导的分子生成扩散模型- GaUDI 评测

GaUDI模型来自于以色列理工Tomer Weiss的2023年发表在预印本ChemRxiv上的工作 《Guided Diffusion for Inverse Molecular Design》。原文链接:Guided Diffusion for Inverse Molecular Design | Materials Chemistry | ChemRxiv | Cambridge Open Engage

GaUDI模型有点像强化学习,目的都是生成特定性质的分子,且效果均非常显著,而且生成过程均存在迭代更新过程。

写在前面

GaUDI模型有点像强化学习,目的都是生成特定性质的分子,且效果均非常显著,而且生成过程均存在迭代更新过程。

但是,二者原理不同。

从迭代过程来说,强化学习生成特定属性的分子迭代发生在生成的批次分子之间,而梯度引导扩散模型是发生在生成一个分子的过程中,因此,从速度上来说,GaUDI模型非常快,很有优势。

从目标函数的形式来说,强化学习是使用目标函数计算生成的分子,获得reward。reward是 一个数值,而是通过数值,调节分子生成器的梯度强度,让分子生成器降低目标分子的损失,于是分子生成器生成更多特定属性的分子。GaUDI模型则不同,目标函数产生的梯度,并未返回到分子生成器中,而是直接用于引导Zt-1,使Zt-1亲向特定属性(方向)。因此,对于任何的分子性质要求,GaUDI模型的分子生成器,即扩散模型,都可以通用,无需重新训练。

从联合概率分布来说,GaUDI模型是联合概率分布,而强化学习不是。GaUDI模型生成的分子更加”平滑“,更具有实用性。强化学习更容易钻模型的漏洞,生成一些奇怪的分子。

一、背景介绍

GaUDI是用于逆向分子设计的一个引导扩散模型,因此文章的题目是《Guided Diffusion for Inverse Molecular Design》。GaUDI对扩散模型中的分子生成器进行了改造,将分子生成过程使用性质预测的函数进行梯度引导,更新Zt-1,使Zt-1更靠近我们期待的性质(例如:logP等)。我们期待的性质可以使单目标也可以是多目标,一切取决于我们的梯度函数f(x,t)。

引导分子生成的梯度来自于目标函数f(x,t), 函数f(x,t)用于根据输入的去噪过程中的Zt-1,预测Zt-1(即:分子)对应的性质。利用预测性质与目标性质之间的损失梯度,更新Zt-1,那么在去噪生成过程中,生成的Zt-1就会越来越靠近我们的期望的性质。当然目标函数f(x,t)需要另外训练。梯度对Zt-1的更新程度可使用调节系数(gradient scalar values, s)来控制。整个去噪采样逻辑如下图:

伪代码如下:

二、文章案例

2.1 多目标优化(全局最优)

作者以 图 A 的 cc-PBHs 为例,目标是增加改分子的稳定性(更低的Erel)。这里作者是进行全局最优的例子,目标函数是生成分子与cc-PBHs 的LUMO, HLG, IP, EA 的MSE加上Erel。作者尝试了不同的调节系数(gradient scalar values, s)结果如图B所示。图C展示了一些具体的例子。

2.2 Out-of-distribution生成

验证GaUDI模型是否可以生成更高的HLG值的分子,限定条件是在相同的环数量下。结果如下图:

图A是数据集中不同环数下的最高HLG分子,图B是生成的分子,图C是不同调节系数下的结果。从结果上来看,生成分子的效果非常显著。

2.3 多目标优化

将目标设置为:ℓ(HLG,IP, EA) = 3 · HLG + IP − EA, 结果如下下图:

整体结果还是非常惊喜的。因为没有任何的强化学习,但是实现了类似的结果,效果非常明显。非常好的弥补了强化学习只能身材个核那个smiles的缺点。

原文代码开源:porannegroup / GaUDI · GitLab

三、模型应用测试

3.1 环境安装

首先,复制代码:

git clone https://github.com/tomer196/GaUDI.git

代码目录:

.
├── analyze
├── cond_prediction
├── data
├── edm
├── environment.yml
├── eval_validity.py
├── GaUDI.png
├── generation_guidance.py
├── __init__.py
├── LICENSE
├── models_edm.py
├── __pycache__
├── README.md
├── sampling_edm.py
├── train_edm.py
└── utils

安装环境目录,并激活环境:

conda env create -n GaUDI --file environment.yml
conda activate GaUDI

如果不行,就分开安装rdkit, pytorch等,注意版本:

conda install pytorch==2.1.0 torchvision==0.16.0 torchaudio==2.1.0 pytorch-cuda=11.8 -c pytorch -c nvidia
conda install -c conda-forge rdkit
pip install matplotlib networkx tensorboard pandas scipy tqdm imageio

安装过程,比较顺利,没有特殊问题。但是centos和win系统比较麻烦,估计要摸索一下。

另外,需要安装几个附属模块:

pip install tensorboard
pip install imgaug

3.2 数据准备&下载数据

作者使用到两个数据集:COMPAS 和 PASS,下载链接:

COMPAS:porannegroup / COMPAS · GitLab

PASS:PASS molecular dataset

需要从上述网址中,下载三个文件,分别是:PASs_csv.tar.gz, PASs_xyz.tar.gz, compas-main-COMPAS-1.zip

在data目录下,创建一个all_data文件夹,将下载的PASs_csv.tar.gz, PASs_xyz.tar.gz, compas-main-COMPAS-1.zip文件上传。然后,分别解压:

unzip compas-main-COMPAS-1.zip
tar -zxvf PASs_csv.tar.gz
tar -zxvf PASs_xyz.tar.gz#删除压缩文件
rm compas-main-COMPAS-1.zip PASs_csv.tar.gz PASs_xyz.tar.gz
然后去更改./data/aromatic_dataloaders.py中get_path函数,关于数据的路径。
def get_paths(args):if not hasattr(args, "dataset"):csv_path = args.csv_filexyz_path = args.xyz_rootelif args.dataset == "cata":csv_path = "/home/tomerweiss/PBHs-design/data/COMPAS-1x.csv"xyz_path = "/home/tomerweiss/PBHs-design/data/peri-cata-89893-xyz"elif args.dataset == "peri":csv_path = "/home/tomerweiss/PBHs-design/data/peri-xtb-data-55821.csv"xyz_path = "/home/tomerweiss/PBHs-design/data/peri-cata-89893-xyz"elif args.dataset == "hetro":csv_path = "/home/tomerweiss/PBHs-design/data/db-474K-OPV-filtered.csv"xyz_path = "/home/tomerweiss/PBHs-design/data/db-474K-xyz"elif args.dataset == "hetro-dft":csv_path = "/home/tomerweiss/PBHs-design/data/db-15067-dft.csv"xyz_path = ""else:raise NotImplementedErrorreturn csv_path, xyz_path

改为:

def get_paths(args):if not hasattr(args, "dataset"):csv_path = args.csv_filexyz_path = args.xyz_rootelif args.dataset == "cata":csv_path = "./data/all_data/compas-main-COMPAS-1/COMPAS-1/COMPAS-1x.csv"xyz_path = "/data/all_data/compas-main-COMPAS-1/COMPAS-1/pahs-cata-34072-xyz"elif args.dataset == "hetro":csv_path = "./data/all_data/db-474K-OPV-filtered.csv"xyz_path = "./data/all_data/db-474K-xyz"else:raise NotImplementedErrorreturn csv_path, xyz_path

3.3 训练EDM 模型

由于作者没有提供预训练好的checkpoint, 所以需要我们自己训练。回到主目录,然后:

python train_edm.py

训练过程了会被记录,将保存在./summary路径下,默认是:cata-test文件夹。整个训练过程,3090显卡需要5h左右。

训练完成后,./summary/cata-test内得到如下目录:

.
├── args.txt
├── epoch_0
├── epoch_100
├── epoch_150
├── epoch_200
├── epoch_250
├── epoch_300
├── epoch_350
├── epoch_400
├── epoch_450
├── epoch_50
├── epoch_500
├── epoch_550
├── epoch_600
├── epoch_650
├── epoch_700
├── epoch_750
├── epoch_800
├── epoch_850
├── epoch_900
├── epoch_950
├── events.out.tfevents.1700200741.a01.3529424.0
├── events.out.tfevents.1700200774.a01.3532044.0
└── model.pt #模型文件

3.4 训练条件模型

同样的,作者没有给checkpoint,条件模型也需要训练。在主目录下,执行:

python cond_prediction/train_cond_predictor.py

训练过程将保存在prediction_summary目录中的cata-test文件夹中。训练过程大约也需要4h。训练完成后, prediction_summary的目录如下:

.
└── cata-test├── args.txt├── events.out.tfevents.1700211860.a01.63329.0└── model.pt

3.5 条件引导扩散的分子生成

3.5.1 使用generation_guidance.py

在完成EDM和条件模型的训练以后,现在可以进行条件引导分子扩散。

首先,需要修改generation_guidance.py文件中的EDM和条件模型路径。将如下内容:

args = get_edm_args("/home/tomerweiss/PBHs-design/summary/hetro_l9_c196_orientation2")
cond_predictor_args = get_cond_predictor_args(f"/home/tomerweiss/PBHs-design/prediction_summary/"f"cond_predictor/hetro_gap_homo_ea_ip_stability_polynomial_2_with_norm")

根据我们前面训练获得的模型,更改为:

args = get_edm_args("./gaudi/summary/cata-test")
cond_predictor_args = get_cond_predictor_args(f"./gaudi/prediction_summary/cata-test")

在189~193行可以修改,需要生成的分子数量和梯度引导强度。

##################### 设置引导梯度的强度,和想要的分子数量  ###################################
# Set controllable parameters
args.batch_size = 512   # number of molecules to generate
scale = 0.6             # gradient scale - the guidance strength
n_nodes = 10            # number of rings in the generated molecules
#########################################################################################

然后执行:

python generation_guidance.py

就可以生成分子。

但是,存在的问题是:

plot_graph_of_rings
plot_rdkit

这两个函数一直无法通过。同时发现,改模型输出的结果不是xyz文件,也不是sdf文件,似乎是图片。这是因为,作者在定义图的时候与我们平常的方法不同,平常的,我们会将一个原子作为一个节点,但是这里作者是将一个环作为一个节点。因此输出的结果比较奇怪。需要其他的转化函数(plot_rdkit),才能输出我们能查看的RDKIT对象。但是我们在运行generation_guidance.py文件时,plot_rdkit文件报错了。所以无法继续运行。

3.5.2 generation_guidance.py文件修正

在研究了其代码和输出结果以后,我们发现代码里面存在变量错误和文件名命名错误。

将以下代码进行修改:

plot_graph_of_rings(x_stable[idx].detach().cpu(),atom_type_stable[idx].detach().cpu(),filename=f"{dir_name}/{i}.pdf",title=f"{best_str}\n {value}",dataset=args.dataset,)plot_rdkit(x_stable[idx].detach().cpu(),atom_type_stable[idx].detach().cpu(),filename=f"{dir_name}/mol_{i}.pdf",title=f"{best_str}\n {value}",dataset=args.dataset,)

修改为:

try:plot_graph_of_rings(x_stable[idx].detach().cpu(),atom_type[idx].detach().cpu(),filename=f"{dir_name}/{i}.png",title=f"{best_str}\n {value}",dataset=args.dataset,)plot_rdkit(x_stable[idx].detach().cpu(),atom_type[idx].detach().cpu(),filename=f"{dir_name}/mol_{i}.png",title=f"{best_str}\n {value}",dataset=args.dataset,)except:pass

使用try语句的原因是,及时通过了有效检测,但是仍然有分子是画不出来的。

生成分子:

python generation_guidance.py

运行结束后,将产生./best文件夹目录,有一个以运行日期为名的文件夹,例如:1120_00:42:46_0.6,其中保存对于 Top 5 最优分子的结果,包括节点图以及分子结构。

生成目录示例:

./best
└── 1120_00:42:46_0.6├── 0.png├── 1.png├── 2.png├── 3.png├── 4.png├── all.png└── mol_0.png

生成节点图:

目标函数分子的gap最大,最优分子结构:

由于生成分子结构代码的问题,最终只生成了一个分子的结构图,如下图所示:

scale=0.8
stability_dict['mol_valid']=82.00% out of 50
Mean target function value: -4.7209
best value: -5.982420921325684, pred: tensor([ 0.2653, -6.9535, -0.1940,  0.3079, 53.0093])
Mean target function value (from valid): -4.7066

根据输出的结果,最优的分子的目标函数值,gap值为:5.98,但是由于画图的原因,导致无法输出分子结构。能输出分子结构的目标函数值是5.488。

因为在没有引导的时候,即scale参数为0时(在generation_guidance.py文件内调整scale参数的值),相当于直接使用EDM进行分子生成,运行代码输出:

scale=0
stability_dict['mol_valid']=100.00% out of 50
Mean target function value: 0.0738
best value: -1.7954111099243164, pred: tensor([ 1.1055, -8.5804, -0.2251,  0.3761, 55.9974])
Mean target function value (from valid): 0.0738

对应的gap的最大值只有1.79,远小于scale为0.8的结果,说明作者提出的梯度引导很符合target函数的要求,效果还不错。但是牺牲的代价是分子的有效率降低了。

3.6 scale梯度调节参数

刚才我们提到scale参数,scale参数是调节引导强度的超参数,当这个值越大时,则生成的分子越满足,越靠近我们的目标函数需求,但是分子的有效率会大大降低,例如,我们将scale设置为2时:只有6%的分子有效。

scale=2
stability_dict['mol_valid']=6.00% out of 50
Mean target function value: -5.2808
best value: -6.993871212005615, pred: tensor([ 0.2147, -6.5605, -0.1836,  0.2928, 52.0480])
Mean target function value (from valid): -5.1165
best value (from stable): tensor([ 0.2562, -7.1488, -0.2008,  0.3158, 52.8709]), score: -5.479823112487793
best value (from stable): tensor([ 0.3591, -7.2578, -0.1995,  0.3182, 53.5928]), score: -5.1993408203125
best value (from stable): tensor([ 0.1914, -7.4633, -0.2178,  0.3219, 54.1037]), score: -4.670310020446777

我们将scale设置为4时,报错了,生成了一些奇怪的分子无法计算其gap等分子属性结果,分子的有效率直接降为0:

scale=4
stability_dict['mol_valid']=0.00% out of 50
Mean target function value: -2.2682
best value: -6.642547130584717, pred: tensor([ 0.3690, -6.6970, -0.1769,  0.3109, 51.9043])
Mean target function value (from valid): nan
~/anaconda3/envs/GaUDI/lib/python3.8/site-packages/numpy/lib/histograms.py:883: RuntimeWarning: invalid value encountered in dividereturn n/db/n.sum(), bin_edges

3.7 条件引导扩散的分子生成(jupyter notebook版本)

作者也提供了一个jupyter notebook的版本,详见文件中的Case_Test.ipynb文件。

导入相关模块:

import shutil
import os
import matplotlib.pyplot as plt
import torch
import numpy as np
import gdown
from time import time
from types import SimpleNamespacefrom cond_prediction.train_cond_predictor import get_cond_predictor_model
from data.aromatic_dataloader import create_data_loaders
from models_edm import get_model
from utils.helpers import switch_grad_off, get_edm_args, get_cond_predictor_args

加载预训练模型:

edm_model - 扩散模型,一种在每次迭代时稍微清洁分子的降噪器。

cond_predictor - 条件预测器,预测生成过程中噪声分子的属性。 以时间为条件。

from cond_prediction.train_cond_predictor import get_cond_predictor_model
from data.aromatic_dataloader import create_data_loaders
from models_edm import get_model
from utils.helpers import switch_grad_off, get_edm_args, get_cond_predictor_args# 加载EDM 参数配置
args = get_edm_args("pre_trained/EDM")
# 加载条件控制模型参数配置
cond_predictor_args = get_cond_predictor_args("pre_trained/cond_pred")# 数据集的模拟,我们仅需要它来了解数据的形状及其统计数据。
dataset_mock = SimpleNamespace( num_node_features=12,num_targets=5,mean=torch.tensor([ 1.1734, -9.2780, -0.2356,  0.4042, 53.9615]),std=torch.tensor([0.5196, 0.3886, 0.0179, 0.0152, 1.6409]),
)
train_loader_mock = SimpleNamespace(dataset=dataset_mock)# 加载EDN模型
edm_model, nodes_dist, prop_dist = get_model(args, train_loader_mock, only_norm=True)
# 加载条件控制模型
cond_predictor = get_cond_predictor_model(cond_predictor_args, dataset_mock)
# 设置模型中的参数为不可训练
switch_grad_off([edm_model, cond_predictor])

定义生成的内容:

batch_size - 有多少分子 - 影响运行时间。

n_rings 每个分子中环的数量。

Guiding_scale - 对具有较低目标功能的分子的引导强度 - 梯度标量影响生成分子的有效性与其目标分数之间的权衡。

它越高,有效分子的百分比就会减少。 然而,生成的有效分子将更接近定义的目标属性。

目标函数 - 我们想要最小化的函数。 预测属性的任意组合。

### 定义分子限制和目标函数 ###
batch_size = 10
n_rings = 8
guidance_scale = 1def target_function(_input, _node_mask, _edge_mask, _t):pred = cond_predictor(_input, _node_mask, _edge_mask, _t)pred = prop_dist.unnormalize(pred)gap = pred[:, 0]homo = pred[:, 1]ea = pred[:, 2] * 27.2114  # hartree to eVip = pred[:, 3] * 27.2114  # hartree to eVreturn -gap# return ip + ea + 3 * gap

生成分子:

from sampling_edm import sample_guidance# 初始化生成分子,由于这里的模型是一个节点是一个环,所以节点比较奇怪
nodesxsample = torch.Tensor([n_rings] * batch_size).long()
# nodesxsample = nodes_dist.sample(args.batch_size)start_time = time()
x, one_hot, node_mask, edge_mask = sample_guidance(args,edm_model,target_function,nodesxsample,scale=guidance_scale,
)
print(f"Generated {x.shape[0]} molecules in {time() - start_time:.2f} seconds")

使用 RDKit 评估分子的有效性并过滤掉无效分子:

target_function_values = get_target_function_values(x, one_hot, target_function, node_mask, edge_mask, edm_model)
pred = prop_dist.unnormalize(predict(cond_predictor, x, one_hot, node_mask, edge_mask, edm_model))

绘制最佳分子(具有较低的目标函数值)。 生成的分子表示为环图 (GOR),并带有表示环方向的加法节点。

from utils.plotting import plot_grap_of_rings_inner, plot_rdkitbest_idxs = target_function_values.argsort()
n_plot = min(3, x.shape[0])
fig, axes = plt.subplots(1, n_plot, figsize=(5*n_plot, 7))
for i, idx in enumerate(best_idxs[:n_plot]):pred_i = pred[idx]title = f"HLG: {pred_i[0]:.2f}, HOMO: {pred_i[1]:.2f}, EA: {pred_i[2]:.2f}, IP: {pred_i[3]:.2f}"plot_grap_of_rings_inner(axes[i], x[idx], one_hot.argmax(2)[idx], title=title, dataset=args.dataset, )
plt.show()

输出:

转换成完整的分子结构:

fig, axes = plt.subplots(1, n_plot, figsize=(5*n_plot, 7))
for i, idx in enumerate(best_idxs[:n_plot]):pred_i = pred[idx]title = f"HLG: {pred_i[0]:.2f}, HOMO: {pred_i[1]:.2f}, EA: {pred_i[2]:.2f}, IP: {pred_i[3]:.2f}"plot_rdkit(x[idx], one_hot.argmax(2)[idx], axes[i], title=title, dataset=args.dataset)
plt.show()

四、总结

1. GaUDI是一个梯度引导的分子生成扩散模型,可以在不重新训练分子生成模型的基础上,通过目标函数的梯度引导分子生成,从而产生特定属性的分子。文中以Gap等分子属性作为目标,验证了其方法的可行性。

2. 对于药物设计,分子设计等而言,该方法不能直接使用。首先,该模型对分子的表示,以环为节点,不符合我们几何神经网络中关于分子的设定,导致分子还原存在困难。这也是为什么上述结果中,有着GOA图的原因,以及有大量分子无法输出结构的原因。数据集中的分子均为多环结构,不是药物设计中常用的分子结构,模型的偏差很严重。

结论是,该模型不推荐,难用不友好,但是该方法提供了非常好的概念验证,值得进一步研究学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/155826.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

详解Python Tornado框架写一个Web应用全过程

Tornado是什么 之前在看Jupyter组件的源码的时候,发现了tornado这个web框架。 不仅仅做一个web框架, 通过使用非阻塞网络I/O,Tornado可以扩展到数万个开放连接。 这样非常适合 long polling , WebSockets 以及其他需要与每个用户…

shell脚本判断语句

目录 一. 判断语句 1. 判断文件是否存在 test 2. 数值比较 3. 字符串比较 4. 逻辑运算 5. [ ] 与 [ [ ] ] 6. ( ) 与 { } 7. if 语句 二. 脚本应用 一. 判断语句 1. 判断文件是否存在 test 选项 -a 和 -e 都可以判断文件是否存在 只是 -a 选项在取反时有问题&#xf…

Linux | 安装openGauss数据库

Linux 安装openGauss数据库 今天我们来安装一下国产数据库openGauss~~ 下载openGauss 首先在官网下载对应的安装包,我们这里下载LInux 极简版来演示安装 下载后,使用root用户上传到Linux ,这边上传到/usr/local/目录下, 使用root 用户创建安装目录 mkdir /usr/l…

C++刷题 -- 二分查找

C刷题 – 二分查找 文章目录 C刷题 -- 二分查找一、原理二、例题1.二分查找2.使用二分查找确定target左右边界3.x的平方根 一、原理 条件:数组为有序数组,数组中无重复元素,因为一旦有重复元素,使用二分查找法返回的元素下标可能…

基于单片机预费电表控制系统(proteus仿真+源程序)

一、系统方案 1、本设计采用这51单片机作为主控器。 2、采集电量值送到液晶1602显示。 3、按键设置预设值,实际使用电量超过设置,蜂鸣器报警。 二、硬件设计 原理图如下: 三、单片机软件设计 1、首先是系统初始化 void LCD_init(void) { …

SMART PLC累计流量功能块(梯形积分法+浮点数累加精度控制)

S7-200SMART PLC数值积分器相关知识请参考下面文章链接: SMART PLC数值积分器功能块(矩形+梯形积分法完整源代码)-CSDN博客文章浏览阅读153次。PLC的数值积分器算法也可以参考下面文章链接:PLC算法系列之数值积分器(Integrator)-CSDN博客数值积分和微分在工程上的重要意义不…

前端CSS实现响应式TimeLine效果(附源码)

文章目录 纯CSS搭建,先上效果图(附有源码)视图层 index.htmlindex.css 公用样式文件Main.css 主要的样式文件 纯CSS搭建,先上效果图(附有源码) 本效果为纯CSS搭建,适配移动端和PC端&#xff01…

CMap数据库筛选化学药物

数据库clue.io 文献链接:连接图谱:使用基因表达特征连接小分子、基因和疾病 |科学 (science.org) 基本模式:利用CMap将差异基因列表与数据库参考数据集比对;根据差异表达基因在参考基因表达谱富集情况得到一个相关性分数&#…

Redis从入门到精通(二)- 入门篇

文章目录 0. 前言1. 入门篇[【入门篇】1.1 redis 基础数据类型详解和示例](https://icepip.blog.csdn.net/article/details/134438573)[【入门篇】1.2 Redis 客户端之 Jedis 详解和示例](https://icepip.blog.csdn.net/article/details/134440061)[【入门篇】1.3 redis客户端之…

(六)什么是Vite——热更新时vite、webpack做了什么

vite分享ppt,感兴趣的可以下载: ​​​​​​​Vite分享、原理介绍ppt 什么是vite系列目录: (一)什么是Vite——vite介绍与使用-CSDN博客 (二)什么是Vite——Vite 和 Webpack 区别&#xff0…

LR学习笔记——基本面板

文章目录 面板介绍色彩调整区域明暗调整区域纹理及质感色彩饱和 面板介绍 面板如上图所示 基本可分为几个板块:色彩、明暗、纹理及质感、色彩饱和 色彩调整区域 色温:由蓝色和黄色控制色调:由绿色和洋红控制 互补色:蓝色对黄色&…

模电 01

一.半导体基本知识 1.优点:体积小、重量轻、使用寿命长、输入功率小、功率转换效率高。 2.性能介于导体与绝缘体 3.常用半导体材料:硅(SI) 镉(Ge),化合物半导体:砷化镓(GaAs&…

RabbitMQ 基础操作

概念 从计算机术语层面来说,RabbitMQ 模型更像是一种交换机模型。 Queue 队列 Queue:队列,是RabbitMQ 的内部对象,用于存储消息。 RabbitMQ 中消息只能存储在队列中,这一点和Kafka相反。Kafka将消息存储在topic&am…

C语言进制转换(1112:进制转换(函数专题))

题目描述 输入一个十进制整数n,输出对应的二进制整数。常用的转换方法为“除2取余,倒序排列”。将一个十进制数除以2,得到余数和商,将得到的商再除以2,依次类推,直到商等于0为止,倒取除得的余数…

基于Vue+SpringBoot的考研专业课程管理系统

项目编号: S 035 ,文末获取源码。 \color{red}{项目编号:S035,文末获取源码。} 项目编号:S035,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 考研高校模块2.3 高…

断点检测学习

突然看到了一种反调试的手段&#xff0c;检测api函数的首字节是否为0xcc&#xff0c;即int 3类型的断点&#xff0c;来反调试&#xff0c;尝试一下 #include<stdio.h> #include<stdlib.h> void fun(int a) {a;a--;a 5;a - 5;return; } int main() {void (*ptr)(i…

【STM32】W25Q64 SPI(串行外设接口)

一、SPI通信 0.IIC与SPI的优缺点 https://blog.csdn.net/weixin_44575952/article/details/124182011 1.SPI介绍 同步&#xff08;有时钟线&#xff09;&#xff0c;高速&#xff0c;全双工&#xff08;数据发送和数据接收各占一条线&#xff09; 1&#xff09;SCK:时钟线--&…

Spring Boot要如何学习?【云驻共创】

Spring Boot 是由 Pivotal 团队提供的全新框架&#xff0c;其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置&#xff0c;从而使开发人员不再需要定义样板化的配置。我这里会分享一些学习Spring Boot的方法和干货&#xff0c;包括…

计算机毕业设计选题推荐-内蒙古旅游微信小程序/安卓APP-项目实战

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

Spring Cloud Alibaba Sentinel 简单使用

Sentinel Sentinel 主要功能Sentinel 作用常见的流量控制算法计数器算法漏桶算法 令牌桶算法Sentinel 流量控制Sentinel 熔断Sentinel 基本使用添加依赖定义资源定义限流规则定义熔断规则如何判断熔断还是限流自定义 Sentinel 异常局部自定义异常全局自定义异常系统自定义异常…