飞桨分子动力学模拟-论文复现第六期:复现TorchMD

飞桨分子动力学模拟-论文复现第六期:复现TorchMD

Paddle for MD 飞桨分子动力学模拟科学计算

复现论文-TorchMD: A deep learning framework for molecular simulations
本项目可在AIStudio一键运行:飞桨分子动力学模拟PaddleMD-复现TorchMD
在这里插入图片描述

【论文复现第六期】相关信息

飞桨第六期论文复现赛128 https://aistudio.baidu.com/aistudio/competition/detail/205/0/task-definition

issue报名地址:https://github.com/PaddlePaddle/Paddle/issues/41482

验收标准:Di-alanine 688 8 min 44 s, Trypsin 3,248 13 min 2 s。(后改为去掉速度要求)

成功后会合入 https://github.com/X4Science

飞桨顶会论文挑战赛第9号 https://www.educoder.net/competitions/index/paddlepaddle-02

torchMD代码学习:https://github.com/torchmd/torchmd

论文地址
论文中文版地址

复现工作

复现工作第一步PaddleMD
第一步完成后运行Tutorial指导手册 复现第二步2PaddleMD提速 复现第三步集成测试

复现相关几个手写API速度测试 经测试,代码中有for循环的,一般速度比没有for循环都要慢30倍左右。

当前复现代码github地址PaddleMd https://github.com/skywalk163/INFINITY/tree/main/examples/PaddleMD

准备论文复现工作

下载论文原作源码

首先git clone下载论文原作的源码,使用命令git clone https://github.com/torchmd/torchmd

相关库安装。

在AIStudio下有些库使用pip无法安装,或者安装好之后不起作用,需要conda或者源码安装。
在AIStudio下如果pip无法安装,基本上我们就只剩下一个选择,就是源码安装。

pip安装moleculukit

使用这条命令pip install "moleculekit<=0.9.14"
如果安装不成功,使用源码安装。

源码安装ParmEd

源码安装ase

ase需要高版本的matplotlib,但是我用pip升级不成功(显示成功,但是版本就是没变)。
后来通过右侧工具条“包管理”,将matplotlib升级到最新版本3.5.1
因为,若安装中报错matplotlib,升级到最新版本,然后再源码安装ase。

pip安装openmm

这个是集成测试的时候使用,若不集成测试,可以不装这个库!
使用命令为:pip install openmm-systems

如果分子结构文件读取的时候报pandas出错,则需要相应降低pandas版本试试。

安装完成后,可以使用import xx的方式,验证是否安装成功。就作者本人的经验来说,运气好的时候,一路顺!运气不好的时候,有些包可能会有反复。

!pip install molkitten pyyaml tqdm pandas networkx scipy parmed ase  # Only needed for minimizers
!pip install pyyaml tqdm pandas networkx scipy parmed ase  # Only needed for minimizers
pip install "moleculekit<=0.9.14"
!cd work && wget https://files.pythonhosted.org/packages/56/75/422fa404b42999d6346545b63542d8c1e30f1cc31e5fc884bb7c9a3995c8/ParmEd-3.4.3.tar.gz 
!cd work && tar -xzvf ParmEd-3.4.3.tar.gz 
!cd work/ParmEd-3.4.3/ && python setup.py install 
# import matplotlib
# matplotlib.__version__
!cd work && wget https://files.pythonhosted.org/packages/69/64/096410b2e0b58aee082b40a37cdd61e708ed722a7471d7cf0e2dcb01cade/ase-3.22.1.tar.gz
!cd work && tar -xzvf ase-3.22.1.tar.gz
!cd work/ase-3.22.1 && python setup.py install 
# 安装之后需要重启内核
!pip install openmm-systems 
import moleculekit
# import ParmEd
import parmed
import ase
import openmm

若不成功,则按照下面安装openmm等,学习于这个项目:h
ttps://aistudio.baidu.com/aistudio/projectdetail/2694076

! mkdir 1
!wget https://repo.anaconda.com/miniconda/Miniconda3-py37_4.8.2-Linux-x86_64.sh
! chmod +x Miniconda3-py37_4.8.2-Linux-x86_64.sh
! bash ./Miniconda3-py37_4.8.2-Linux-x86_64.sh -b -f -p /home/aistudio/1
#! conda install -c rdkit rdkit -y
!yes| /home/aistudio/1/bin/conda install -c conda-forge openmm
!yes |/home/aistudio/1/bin/conda install -c conda-forge pdbfixer
import sys
sys.path.append('/home/aistudio/1/bin/')import sys
sys.path.append('/home/aistudio/1/lib/python3.7/site-packages/') 

跑通原论文torchmd

先跑通原作代码,对整个流程有个基本了解

开始复现

第一阶段 手工开始单个文件转换

将项目所有核心.py文件,使用%%writefile xx.py的格式,放到notebook cell中,这样可以通过查找替换,快速修改所有的代码。

  • 优点是:代码修改效率高。发现一个问题,解决问题,并可以全部查找、替换,将同类问题全部解决。
  • 缺点是:调试效率较低。需要另开一个notebook文件进行测试,且修改代码后,需要重新执行,甚至要重启测试项目的内核。

代码复现第二阶段

像常规notebook下的调试流程

1、对疑点文件拆分,将函数放到Cell进行测试

测试中可以加入测试代码,验证函数是否正确。最终保证所有函数测试通过

2、测试通过后,将修改写回文件

3、在tutorial.ipynb文件中总测试

优点是,基本不修改tutorial.ipynb文件代码。

代码复现第三阶段

调试精度和速度
速度提高工具
https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/performance_improving/profiling_model.html#profiler
当然最终这个项目里没有使用。

1、速度提高

有些手工写的算子使用了for循环,需要找到并提速。

提升paddleindex_add

5.12日确认了paddleindex_add对速度的影响非常大,这个算子要处理!

其次,在屏蔽掉paddleindex_add后,程序运行速度较快提高,非常利于调试!
目前的思路,是找到黑客马拉松项目里面的index_add代码,然后自己动手写成单独的算子。

6.1日,官方提供put_along_axis算子,可以实现index_add功能!

6.2日,好像put_along算子只支持1D index,以后不能用,后来发现可以使用。

6.4日 使用put_alone_axis函数重写了paddleindex_add,速度提升非常多!基本上跟以前测试的时候使用透传的的速度相当!

质疑numpy()函数

使用了太多的numpy()转换函数,这会大大降低速度。要看看这些转换的原因是什么,能否去掉。

提高paddleindexjia

修改paddleindexjia函数,将其修改成由numpy实现:

#             pos[:, self.nongrouped] -= offset.unsqueeze(1)
#             pos = paddleindexjia(pos, -offset, self.nongrouped)pos = pos.numpy()offset = offset.unsqueeze(1).numpy()pos[:, group] -= offset # 尝试使用numpy来处理 相关语句共4句pos = paddle.to_tensor(pos)

最终这一大段应该还有提升空间

        if len(self.nongrouped):offset = paddle.floor(pos[:, self.nongrouped] / box) * box
#             pos[:, self.nongrouped] -= offset.unsqueeze(1)
#             pos = paddleindexjia(pos, -offset, self.nongrouped)pos = pos.numpy()offset = offset.unsqueeze(1).numpy()pos[:, group] -= offset # 尝试使用numpy来处理 相关语句共4句pos = paddle.to_tensor(pos)
性能分析cProfile

import cProfile
import re
cProfile.run(‘re.compile(“foo|bar”)’)

def my_on_trace_ready(prof): # 定义回调函数,性能分析器结束采集数据时会被调用callback = profiler.export_chrome_tracing('./profiler_demo') # 创建导出性能数据到profiler_demo文件夹的回调函数callback(prof)  # 执行该导出函数prof.summary(sorted_by=profiler.SortedKeys.GPUTotal) # 打印表单,按GPUTotal排序表单项p = profiler.Profiler(scheduler = [3,14], on_trace_ready=my_on_trace_ready, timer_only=True) # 初始化Profiler对象p.start() # 性能分析器进入第0个step
测试paddle.profiler

paddle.profiler是飞桨自带的性能分析套件。
但是我在启智平台使用的时候,内核直接重启。
后来发现是最后使用了exit()指令的缘故。

但是分析套件需要数据集部分,没有就报错。曾设想加上一个空的数据集指令来骗过去,但最终没有动手做。

2、精度测试

每个文件分别写调试命令,验证精度。

这个并没有做

对tutorial.ipynb文件中的变量输出,跟torchmd的比对。
print(Epot)
print(system.forces)

在使用同一随机种子的情况,paddlemd和torchmd精度对齐。

集成测试

跟openmm的力场能量进行比较,差别不大,在可接受范围

Running test: test-data/benzamidine/angle Energy diff: 1.599e-06 Force diff: 6.954e-05bond Energy diff: -2.731e-06 Force diff: 1.177e-04dihedral Energy diff: -1.608e-06 Force diff: 7.054e-06lennardjones Energy diff: 6.798e-06 Force diff: 1.794e-05electrostatic Energy diff: -6.766e-07 Force diff: 1.272e-07
All forces. Total energy: 20.914 Energy diff: 3.382e-06 Force diff 1.458e-04

成功复现

复现成功后,即可进行飞桨分子动力学模拟

使用PaddleMD进行分子动力学模拟

参考PaddleMD指引手册,以前丙氨酸二肽为例,进行分子动力学模拟。1000step大约需要4分钟。

首先编译安装PaddleMD

若有报错缺库,缺啥装啥。

编译安装后,需要重启一下环境。

!cd ~/INFINITY/examples/PaddleMD/ && python setup.py develop 

参考指引手册,进行前丙氨酸二肽分子模拟

INFINITY/examples/PaddleMD/test-data/目录中有各种分子结构文件,比如二面角、水分子、苯甲脒、凝血酶配体等。这里以前丙氨酸二肽为例。

读取前丙氨酸二肽分子结构文件

使用“moleculekit”库读取输入拓扑和起始坐标

from moleculekit.molecule import Molecule
import os
import paddletestdir = "INFINITY/examples/PaddleMD/test-data/prod_alanine_dipeptide_amber/"
mol = Molecule(os.path.join(testdir, "structure.prmtop"))  # Reading the system topology
mol.read(os.path.join(testdir, "input.coor"))  # Reading the initial simulation coordinates
mol.read(os.path.join(testdir, "input.xsc"))  # Reading the box dimensionsfrom paddlemd.forcefields.forcefield import ForceField
from paddlemd.parameters import Parametersprecision = paddle.float32
# 加载forcefield力场文件,并使用上述拓扑提取将用于模拟的相关参数
ff = ForceField.create(mol, os.path.join(testdir, "structure.prmtop"))
parameters = Parameters(ff, mol, precision=precision)

创建系统

我们可以创建一个“System”系统对象,该对象将包含模拟期间系统的状态,包括:
1、当前原子坐标
1.当前的盒子大小
1、当前原子速度
1、当前原子力场

from paddlemd.integrator import maxwell_boltzmann
from paddlemd.systems import Systemsystem = System(mol.numAtoms, nreplicas=1, precision=precision)
system.set_positions(mol.coords)
system.set_box(mol.box)
system.set_velocities(maxwell_boltzmann(parameters.masses, T=300, replicas=1))
from paddlemd.forces import Forces
bonded = ["bonds", "angles", "dihedrals", "impropers", "1-4"]
# bonded = ["dihedrals"]
# forces = Forces(parameters, cutoff=9, rfa=True, switch_dist=7.5)
forces = Forces(parameters, cutoff=9, rfa=True, switch_dist=7.5, terms=bonded)
# Evaluate current energy and forces. Forces are modified in-place
Epot = forces.compute(system.pos, system.box, system.forces, returnDetails=True)print(Epot)
print(system.forces)

动力学积分器

为了执行动力学,我们将创建一个“积分器”对象,用于集成模拟的时间步,以及一个“包装器”对象,用于包装周期单元内的系统坐标

from paddlemd.integrator import Integrator
from paddlemd.wrapper import Wrapperlangevin_temperature = 300  # K
langevin_gamma = 0.1
timestep = 1  # fsintegrator = Integrator(system, forces, timestep, gamma=langevin_gamma, T=langevin_temperature)
wrapper = Wrapper(mol.numAtoms, mol.bonds if len(mol.bonds) else None)

from paddlemd.minimizers import minimize_bfgsminimize_bfgs(system, forces, steps=500)  # Minimize the system steps=500
from paddlemd.utils import LogWriterlogger = LogWriter(path="logs/", keys=('iter','ns','epot','ekin','etot','T'), name='monitor.csv')

开始集成模拟

from tqdm import tqdm 
import numpy as npFS2NS = 1E-6 # Femtosecond to nanosecond conversionsteps = 1000 # 1000 
output_period = 10
save_period = 100
traj = []trajectoryout = "mytrajectory.npy"iterator = tqdm(range(1, int(steps / output_period) + 1))
# print(f"iterator={iterator}")
Epot = forces.compute(system.pos, system.box, system.forces)
for i in iterator:Ekin, Epot, T = integrator.step(niter=output_period)wrapper.wrap(system.pos, system.box)
#     currpos = system.pos.detach().cpu().numpy().copy()
#     currpos = system.pos.detach()currpos = system.pos
#     print(currpos.shape)traj.append(currpos)
#     print(len(traj) )
#     print(f"iterator={iterator}")if (i*output_period) % save_period  == 0:np.save(trajectoryout, np.stack(traj, axis=2))logger.write_row({'iter':i*output_period,'ns':FS2NS*i*output_period*timestep,'epot':Epot,'ekin':Ekin,'etot':Epot+Ekin,'T':T})

集成测试

INFINITY/examples/PaddleMD/3集成测试.ipynb/集成测试.ipynb 为集成测试文件,在AIStudio中,到相应位置点开该文件即可。也可以在终端使用命令执行。

集成测试的步骤:

首先使用python setup.py develop安装paddlemd开发模式。

在实际使用中,可以使用普通模式,命令为:python setup.py install

执行测试命令

可以使用python tests/test_paddlemd.py进行集成测试,使用./bin/paddlemd --conf tests/water/water_conf.yaml测试水分子,使用./bin/paddlemd --conf tests/prod_alanine_dipeptide_amber/conf.yaml测试prod alanine dipeptide前丙氨酸二肽,使用./bin/paddlemd --conf tests/trypsin/conf.yaml测试Trypsin胰蛋白酶。

3集成测试.ipynb文件中,上述命令已经放入,直接运行即可。也可以到相应目录,在控制台直接使用相应命令执行。

目前这三个单项测试都可以正常运行不报错。速度大约是torchmd的十六分之一。还有较大提升空间。

集成测试,可以测试一部分,可看到势能和力场等数值跟openmm的较接近。但是后面还是会报错,大约是训练求导那块还有问题。

复现过程中的一些工作留档

手动适配的飞桨API

有些API飞桨没有适配,先手写顶上。

def paddlerandn_like(x) : # 添加飞桨的randn_like函数return paddle.randn(x.shape)# 后来发现飞桨2.3版本已经有了atan2函数,直接用即可
def paddleatan2(input, other): # 飞桨的atan2函数atan = paddle.atan(input/other)atan[1] = atan[1] + piatan[2] = atan[2] + pireturn atandef paddlescatter(x, dim, index, src): # scatter支持1D版本updates = srcif len(index.shape) == 1 :
#         for i in index:
#             x[i] += updates[i]for i in range(index.shape[0]):x[index[i]] += updates[i]return xi, j = index.shapegrid_x , grid_y = paddle.meshgrid(paddle.arange(i), paddle.arange(j))if dim == 0 :index = paddle.stack([index.flatten(), grid_y.flatten()], axis=1)elif dim == 1:index = paddle.stack([grid_x.flatten(), index.flatten()], axis=1)# PaddlePaddle updates 的 shape 大小必须与 index 对应updates_index = paddle.stack([grid_x.flatten(), grid_y.flatten()], axis=1)updates = paddle.gather_nd(updates, index=updates_index)return paddle.scatter_nd_add(x, index, updates)# 这个要使用飞桨黑客松的代码,对速度影响非常大
def paddleindex_add(x, dim, index, source): # 飞桨的index_addfor i in range(len(index)):x[index[i]] += source[i]return x# 最终没有等到黑客松的index_add算子,自己用put_alone_axis写了一个
# 飞桨的put_alone_axis不支持shape不一致的情况,即indices和value比arr长或者短的情况。
# 需要做的,就是要把短的补齐,长的分段传入。
def paddleput_alone_axis(arr, indices, value, axis, reduce="add"):#     print(f"==arr.shape:{arr.shape} indices.shape:{indices.shape} value.shape:{value.shape}")lenarr = arr.shape[0]lenindices = indices.shape[0]while lenarr < lenindices:arr = paddle.put_along_axis(arr, indices[:lenarr].reshape([-1, 1]), value[:lenarr], axis, reduce=reduce)indices = indices[lenarr:]value = value[lenarr:]lenarr = arr.shape[0]lenindices = indices.shape[0]xs = lenarr - lenindicesif xs >= 1:newindices = paddle.concat([indices, paddle.zeros([xs], dtype=paddle.int64)]).reshape([-1, 1])newvalue = paddle.concat([value, paddle.zeros([xs, value.shape[-1]])])else:newindices = indices.reshape([-1, 1])newvalue = valueout = paddle.put_along_axis(arr, newindices, newvalue, axis, reduce=reduce)return out# 为了跟程序里的参数序列对齐,尽量不修改代码,写paddleindex_add
def paddleindex_add(x, dim, index, source):return paddleput_alone_axis(x, index, source, dim)# paddleeye这个不用了,全部用变量乘以paddle.eye(3)实现,解决shape首位>1的情况。
#         box = paddleeye(box, 3)box = box*paddle.eye(3) # 可以很好的处理box[2, 3, 3]类型数据box = box.sum(1)def paddleeye(x, n): # 针对[1, 3, 3]输入的特供eye函数tmp =x[0][paddle.eye(n).astype(paddle.bool)]return tmp.unsqueeze_(0)# paddleindexjia,使用专为numpy计算的方式,速度比paddleindexjia提高30%以上
#             pos[:, self.nongrouped] -= offset.unsqueeze(1)
#             pos = paddleindexjia(pos, -offset, self.nongrouped)pos = pos.numpy()offset = offset.unsqueeze(1).numpy()pos[:, group] -= offset # 尝试使用numpy来处理 相关语句共4句pos = paddle.to_tensor(pos)def paddleindexjia (x, y, xindex): # 索引/切片/赋值特供版本'''切片+索引,使用循环来解决切片问题,然后使用中间变量,来实现按照索引赋值支持类似的语句pos[:, group] -= offset.unsqueeze(1)'''xlen = len(x)assert len(x.shape) == 3 , "维度不一致,必须为3D数据"
#     if len(y.shape) == 3 and y.shape[0] ==1 :
#         y = paddle.squeeze(y)assert len(y.shape) ==2 , "维度不一致,必须为2D数据"for i in range(xlen):tmp = x[i]tmp[xindex] += yx[i] = tmpreturn x# 写飞桨版本的笛卡尔直积函数cartesian_prod
from itertools import product
def paddlecartesian_prod(x,y): # 飞桨版本的笛卡尔直积函数z = list(product(x,y))z = paddle.to_tensor(z)return z.squeeze(axis=-1)# 最终版本笛卡尔直积函数支持变长变量输入
from itertools import product
def paddlecartesian_prod(*x): # 飞桨版本的笛卡尔直积函数z = list(product(*x))z = paddle.to_tensor(z)return z.squeeze(axis=-1)

学习paddlemd里面的几句话

# 这句什么意思        self.require_distances = any(f in self.nonbonded for f in self.energies)
# 也就是力场里面有任何一个nobonded值,则self.require_distances为True,也就是有”长距力“ ?
bonded = ["bonds", "angles", "dihedrals", "impropers", "1-4"]
nonbonded = ["electrostatics", "lj", "repulsion", "repulsioncg"]
terms = bonded + nonbondedclass TestClass():bonded = ["bonds", "angles", "dihedrals", "impropers", "1-4"]nonbonded = ["electrostatics", "lj", "repulsion", "repulsioncg"]terms = bonded + nonbondeddef __init__(self, terms=None):self.energies = [ene.lower() for ene in terms]self.require_distances = any(f in self.nonbonded for f in self.energies)print(f"self.require_distances:{self.require_distances}")
tmp = TestClass(terms=terms)

提速思考

像类似这样,应该都可以用张量直接操作

for i in range(nsystems):if explicit_forces:forces[i] = paddleindex_add(forces[i], 0, self.par.angles[:, 0], angle_forces[0])forces[i] = paddleindex_add(forces[i], 0, self.par.angles[:, 1], angle_forces[1])forces[i] = paddleindex_add(forces[i], 0, self.par.angles[:, 2], angle_forces[2])

调试与总结

复现心得

刚开始选这个复现题目的时候,我承认我大意了,分子动力学模拟这个跟平时接触的机器学习和神经网络有较大的不同,而且有几个算子不支持,导致复现工作几度陷入困境。

在低谷期,只好自己鼓励自己:如果我碰到坎,别人也会碰到;如果我想放弃,那别人也会想放弃。坚持,才能胜利!最终跌跌撞撞,在自己写了几个算子(只求功能,不求速度)之后,程序终于能跑通了!

除了自我鼓励之外,问题拆分也是一个非常有效的解决问题的法宝。几乎所有问题,都可以拆分为小问题,进而拆分为更小更易于解决的问题,最终完成开始看起来几乎不可能完成的任务!

一些技术问题存档

大部分碰到的技术问题,都存档了。比如一些分子库pip无法安装的问题,一些算子的问题等。可以在复现三步走对应的文档下部,看到问题存档。

当前遗留的一些问题

1 集成测试无法完全通过。

2 AI自动求导优化那块可能还有问题。

3 运行速度大约是torchmd的十六分之一,还有很大提升空间。

其中有几个算子需要飞桨官方开发出来。另外整个项目的计算(代码表达式)可能还有较大的改进空间。

引用Citation

Please cite:

@misc{doerr2020torchmd,title={TorchMD: A deep learning framework for molecular simulations}, author={Stefan Doerr and Maciej Majewsk and Adrià Pérez and Andreas Krämer and Cecilia Clementi and Frank Noe and Toni Giorgino and Gianni De Fabritiis},year={2020},eprint={2012.12106},archivePrefix={arXiv},primaryClass={physics.chem-ph}
}

To reproduce the paper go to the tutorial notebook https://github.com/torchmd/torchmd-cg/blob/master/tutorial/Chignolin_Coarse-Grained_Tutorial.ipynb

结束语

用飞桨,划时代!让我们荡起双桨,在AI的海洋乘风破浪!

飞桨官网:https://www.paddlepaddle.org.cn

因为水平有限,难免有不足之处,还请大家多多帮助。

作者: 网名skywalk 或 天马行空,济宁市极快软件科技有限公司的AI架构师,百度飞桨PPDE。

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

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

相关文章

分布式系统的前世

文章目录 前言分布式系统解决了什么问题分布式系统存在什么问题总结 前言 大家好&#xff0c;我是醉墨居士&#xff0c;我准备和大家浅聊一下分布式系统&#xff0c;分享我一下我的心得体会&#x1fae0; 分布式系统解决了什么问题 如果用户的请求压力过于庞大&#xff0c;使…

原生Ajax的使用,四种请求方法示例(前后端代码)

目录 原生Ajax是什么 原生Ajax的优点 Ajax应用环境 Ajax的使用 基本使用步骤 AJAX请求状态和HTTP状态码 AJAX 请求状态 HTTP 状态码 XHR对象的方法 各种请求方式和数据获取 post请求 post 请求完整代码 get 请求 服务端 put 请求 服务端 delete 请求 服务端代…

TypeScript基础知识:类型守卫和类型推断

在 TypeScript 中&#xff0c;类型守卫和类型推断是两个重要的概念&#xff0c;它们可以帮助我们更好地理解和利用类型系统的优势。本文将详细介绍这两个概念&#xff0c;并提供示例代码来说明它们的用法和优势。 一、类型守卫 类型守卫是一种在 TypeScript 中用于缩小变量类型…

U盘安装XP纯净版系统教程软件安装教程(附软件下载地址)

软件简介&#xff1a; 软件【下载地址】获取方式见文末。注&#xff1a;推荐使用&#xff0c;更贴合此安装方法&#xff01; U盘安装XP纯净版系统是一种便捷且快速的方式&#xff0c;以实现系统重装或升级的需求。这篇教程将为您详细介绍如何使用U盘来安装XP纯净版系统。XP纯…

代码随想录Day 17 | 110 平衡二叉树 257 二叉树的所有路径 404 左叶子之和

代码随想录Day 17 | 110 平衡二叉树 257 二叉树的所有路径 404 左叶子之和 平衡二叉树二叉树的所有路径左叶子之和 平衡二叉树 文档讲解&#xff1a;代码随想录 视频讲解&#xff1a; 后序遍历求高度&#xff0c;高度判断是否平衡 | LeetCode&#xff1a;110.平衡二叉树 状态 …

DEJA_VU3D - Cesium功能集 之 117-雷达扫描(圆环效果)

前言 编写这个专栏主要目的是对工作之中基于Cesium实现过的功能进行整合,有自己琢磨实现的,也有参考其他大神后整理实现的,初步算了算现在有差不多实现小140个左右的功能,后续也会不断的追加,所以暂时打算一周2-3更的样子来更新本专栏(每篇博文都会奉上完整demo的源代码…

C++知识点总结(13):函数

一、定义 函数&#xff0c;指可以实现某个功能&#xff0c;可以重复使用的一段代码。不同的函数之间相互独立&#xff0c;即函数之间的功能互不影响&#xff08;互相的代码&#xff09;。 二、结构 1. 定义 返回值类型 函数名(形参1, 形参2, 形参3...形参n) {...return 值; }2…

Java初学习

Java代码示例&#xff1a; public class helloworld {public static void main(String[] args){System.out.println("hello world");} } Java程序的名字需要和文件名字一致&#xff0c;就是那个helloworld Java程序需要对类有深度的认识&#xff1a; 对象是类的…

2023年全国职业院校技能大赛软件测试赛题—单元测试卷②

单元测试 一、任务要求 题目1&#xff1a;任意输入2个正整数值分别存入x、y中&#xff0c;据此完成下述分析&#xff1a;若x≤0或y≤0&#xff0c;则提示&#xff1a;“输入不符合要求。”&#xff1b;若2值相同&#xff0c;则提示“可以构建圆形或正方形”&#xff1b;若2<…

ipad协议逆向分析实战篇-1

请使用dnspy环境进行学习研究&#xff0c;切勿用于非法操作 1.首先拿到得到的部署包进行逆向分析 2.解压部署包并找到bin这个文件夹 3.找到Wechat.Api.dll这个文件 4.这两个是协议的核心文件&#xff0c;破解了这个核心文件就可以得出逻辑源码 5.首先把Wechat.Api.dll这个…

Pandas实战100例 | 案例 23: 处理空值

案例 23: 处理空值 知识点讲解 处理空值是数据清洗过程中的一个关键步骤。Pandas 提供了多种方法来检测、填充和删除空值。 检测空值: 使用 isnull 方法可以检测 DataFrame 中的空值。填充空值: 使用 fillna 方法可以填充空值。删除包含空值的行或列: 使用 dropna 方法可以删…

C++ (MFC) 单程序运行(防止多开程序)

C (MFC) 单程序运行&#xff08;防止多开程序) 项目文件名:MFCAppTest 在 C*****App.cpp 文件中 CMFCAppTestApp::InitInstance 函数中 添加以下代码 //避免程序的多开 xxxx为信号量的名字 可随意CreateMutex(NULL, TRUE, TEXT("MFCAppTest")); if (GetLastError…

oracle—IMU机制

正常的情况下&#xff0c;当事务需要回滚块的时候&#xff0c;是去undo表空间找 现在是在sharepool中分一个IMUbuffer&#xff0c;将所有的回滚信息写入。直接就可以从中取。减少了物理IO 同时这个过程也产生redo&#xff0c;直接就是图中红色的&#xff0c;不防止崩溃 优点 1…

开机自启动android app

Android App开机自启动_android 开机自启动-CSDN博客 注意权限问题&#xff1a; 第二种实现方式&#xff1a;系统桌面应用 问&#xff1a;android的系统桌面应用启动是什么&#xff1a; 答&#xff1a; Android 系统桌面应用是指用户在设备主屏幕上看到的默认启动界面&…

代码随想录算法训练营第四天| 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点面试题 02.07. 链表相交、142.环形链表II

文档讲解&#xff1a;虚拟头节点&#xff0c;三指针&#xff0c;快慢指针&#xff0c;链表相交&#xff0c;环形链表&#xff0c; 技巧&#xff1a; 1、对于指针的操作要画图&#xff0c;明确步骤后好做了 2、使用虚拟头节点可以避免对头节点单独讨论&#xff0c;且方便对头节点…

C++ Primer 6.1 函数基础

函数的形参列表 int func(int v,int v2) {int v,v2;//&#xff01;错误 } 函数返回类型 不能是数组和函数&#xff08;两者都不接受对拷&#xff09;&#xff0c;但可以是指针 局部对象 形参和函数体内部的变量称为局部变量&#xff0c;仅在函数内部可见&#xff0c;隐藏外部…

c++的map的内存布局

以下均基于x86平台64位CentOS或Ubuntu&#xff0c;g8。 有一个指针偶尔会置成0xffffffff&#xff0c;大佬查了几天发现是由于对map的end迭代器进行了错误操作导致的。简化代码如下&#xff1a; struct s_t {std::map<long, int> m;void *p; }; int main() {s_t s;auto …

Python 安卓开发:Kivy、BeeWare、Flet、Flutter

kivy&#xff1a;https://github.com/kivy python-for-android &#xff1a;https://python-for-android.readthedocs.io/en/latest/ BeeWare&#xff1a;https://docs.beeware.org/en/latest/ Flet&#xff1a;https://github.com/flet-dev/flet 把 PySide6 移植到安卓上去&a…

权值初始化

一、梯度消失与爆炸 在神经网络中&#xff0c;梯度消失和梯度爆炸是训练过程中常见的问题。 梯度消失指的是在反向传播过程中&#xff0c;梯度逐渐变小&#xff0c;导致较远处的层对参数的更新影响较小甚至无法更新。这通常发生在深层网络中&#xff0c;特别是使用某些激活函…

Pandas实战100例 | 案例 18: 列操作 - 重命名、删除和重新排序列

案例 18: 列操作 - 重命名、删除和重新排序列 知识点讲解 在处理 DataFrame 时&#xff0c;经常需要对列进行各种操作&#xff0c;如重命名列、删除列或重新排序列。Pandas 提供了简洁的方法来执行这些任务。 重命名列: 使用 rename 方法可以改变 DataFrame 中一个或多个列的…