当前位置: 首页 > news >正文

paddle——站在巨人肩膀上及背刺二三事

 飞桨AI Studio - 人工智能学习与实训社区     

飞桨PaddlePaddle-源于产业实践的开源深度学习平台

        先抛结论,对于想要快速了解某一领域有哪些比较适合落地的算法的从业人员来说,是一个很好的参考系统。从中可以知道从哪些模型里选型、如何轻量化、如何加速、一些非常细节的FAQ。但是,这个框架维护上还是存在欠缺,比如很多人反馈的教程调不通,盘子铺得较大但维护没跟上;遇到一些报错的时候,相比pytorch这种大量使用的框架,能查到的解决方案较少。                 我遇到的三个坑是:

1、P100开发环境效果验证OK——UWSGI+NGINX搭好项目后——多进程报错,勉强单进程跑跑,网上的说法是paddle有多进程的问题,需要把import放到多进程里,但是试了一番没成功。

2、同一个镜像,相同的代码,换个服务器上测试环境V100直接卡死,没有报错提示,就是卡住了,后来倒腾了几天试版本,又是降低paddle版本,又是换显卡类型,终于搞定。这一点网上很多人也提到了,报错信息不完善。所以,如果是新手,并需要在短期内上线服务的场景,慎重。

3、cpu推理正常,即加参数use_gpu=False,但gpu推理乱码,这里需要基于box输出判断是识别乱码还是整个流程乱码了,如果box数量正常和cpu一致,那就是识别乱码,大概率是词典的问题。如果确定是gpu乱码,会比较麻烦,和显卡型号、驱动版本、cuda、paddle-paddle-gpu版本有关,可以搜索关键词(paddle gpu 乱码),遇到该问题的人也挺多,解决方法一般是各种升级降级,只能试出来,个人认为这属于paddle框架的兼容性问题。

        上面吐槽了一番,但值得肯定的是,paddle在轻量化及速度上还是不错的。

        如果后面的读者成功解决了UWSGI+NGINX多进程部署的问题,请分享一下你的经验。报错信息如下:

[Hint: 'cudaErrorInitializationError'. The API call failed because the CUDA driver and runtime could not be initialized. ] (at /paddle/paddle/phi/backends/gpu/cuda/cuda_info.cc:172)

一、paddleocr

1.1 简介

GitHub - PaddlePaddle/PaddleOCR: Awesome multilingual OCR toolkits based on PaddlePaddle (practical ultra lightweight OCR system, support 80+ languages recognition, provide data annotation and synthesis tools, support training and deployment among server, mobile, embedded and IoT devices)在README_ch.md里可以看到ppocr最新加入的一些算法 

FAQ(doc/doc_ch/FAQ.md)里可以看到一些常见的问题

1.2 ppocr支持的算法

查看tools/program.py。

注:pp会不断更新,最新最全的还是要看源码,这里只是示例说明

ssert alg in ['EAST', 'DB', 'SAST', 'Rosetta', 'CRNN', 'STARNet', 'RARE', 'SRN','CLS', 'PGNet', 'Distillation', 'NRTR', 'TableAttn', 'SAR', 'PSE','SEED', 'SDMGR', 'LayoutXLM', 'LayoutLM', 'LayoutLMv2', 'PREN', 'FCE','SVTR', 'ViTSTR', 'ABINet', 'DB++', 'TableMaster', 'SPIN', 'VisionLAN','Gestalt', 'SLANet', 'RobustScanner', 'CT', 'RFL', 'DRRG', 'CAN','Telescope']

检测:sast、psenet、db

识别:百度自研结合语义基于Transformer的srn、基于ctc的CRNN、StarNet和Rosetta,基于attention的RARE。80种语言

端到端识别:PGnet

Kie:sdmgr

sdmgr利用双模态信息(文本及坐标+视觉)进行图节点分类。图像特征通过UNet提取特征图,并通过ROI Pooling获取切片的图像特征。对每个字符进行one-hot编码,投影到低维空间,并输入Bi-LSTM获取文本特征。

特征融合尝试了三种方法(CONCAT、线性求和、克罗内克积),克罗内克积最优

sdmgr属于mmocr工作

GitHub - open-mmlab/mmocr at 4882c8a317cc0f59c96624ce14c8c10d05fa6dbc

原理:

带你读AI论文:SDMG-R结构化提取—无限版式小票场景应用 - 华为云开发者联盟 - 博客园

sdmgr_cc_moe的博客-CSDN博客

DocVQALayoutLM、LayoutLMv2,LayoutXLM, ser和re由LayoutXLM实现

语义实体识别SER

关系抽取RE:

Style-Text

    基于论文《Editing Text in the Wild》中的SRNet

PaddleOCR/data_synthesis.md at release/2.4 · PaddlePaddle/PaddleOCR · GitHub

其他数据合成工具

SynthText_Chinese_version,TextRecognitionDataGenerator、text_renderer

SynthText3D、UnrealText、StyleText

PP-Structure之版面分析: 文字、标题、图片、列表和表格5类,基于yolov2

PP-Structure之表格解析:基于RARE算法,后面又出了个SLANet

轻量化移动端部署:EasyEdge、Paddle-Lite

1.3一张图的OCR

    过程分为:文本检测——切子图,并根据长宽比旋转90度,主要是为了处理竖排文字(0、90度)——文本方向分类(0、180度)——文本识别。

检测:DBNet 

分类:每个切片的方向分类,在pp中将切片方向分类放在检测后面,而不是方向分类——检测——识别。这样做的好处有:1)可以处理竖排文字 2)支持对同一张图中多个不同文档图像的处理。缺陷1)实测经常会发生在第一步旋转90度就转错了 2)耗时比对整张图像进行方向分类慢一点。

        在paddleocr的方向分类模块中,不仅仅依赖模型的分类输出,还会参考softmax的值,当方向分类为180且置信度大于0.9时才会将图片进行旋转180度操作。如果定位时有上下行都切出来的现象,就容易造成置信度0.5左右的分类错误。猜想是因为模型不太确定这个几个字是上下结构或左右结构。

        而且我不理解,为什么模型判断方向这一步只做二分类,不做四分类。很多单字的定位最后因为方向搞错了,无法识别正确。

识别:CRNN

        pp做了很多速度和显存上的优化,其中动态宽度对速度的提升非常有效果,实测自己训练的大训练模型(基于Restnet,200M左右)修改动态宽度和其他一些点后和pp的速度也很接近了,考虑到字数和时间比,甚至更快一点。关于pp的轻量化,知乎有一篇很好的介绍:PaddleOCR为何这么轻?

        普通的图片走完ocr流程的时间在0.3s左右,如果文字较多,时间会相对增加。可以下载开源模型,然后根据场景更改一下调用流程、阈值、前处理后处理。

1.4 半自动标注工具PPOCRLabel

        要解析一些证件,自研和百度的都不能定位得特别好,想试一下半自动标注能不能偷懒一点。

        安装:过程参考PPOCRLable下的README即可,不再赘述,一种不行就换一种,我最后是通过python脚本运行成功的,报需要啥安装包就装啥,有安装包冲突就搜索一下,安装别人推荐的版本,包括什么“Class RunLoopModeTracker is implemented in both”报错闪退。内网环境下不了模型就手动操作,改改代码的download部分,加个if os.path.exists。

        平时都是labelme标,这个界面用起来有点别扭,为啥要这么搞呢?堪比单个脚踏板的汽车。包括:

1、图片后缀要是正常的图片后缀,不能没后缀

2、不接受指定文件夹下的循环嵌套文件夹,只能是对应文件夹下的图片

3、不能设置标签路径,和图片放一起了

4、多个文件的标签放到了一个标注文件中,如果我想把数据放在几个文件夹中标,就很难受

5、进入标注状态后不能esc,必须让我标注

6、自动标注后的标签是矩形,进行矩形标注会显示4个点,我想改成4点的标注都不知道从哪改,Label.txt里没有显式形状的说明。

7、有旋转90方向,但太隐蔽,要用3个jia4组成快捷键,不好用。

        这个工具目前最大价值在于半自动标注了,其他真的不咋好用。

1.5训练

        用自己的数据更新定位识别模型

1.5.1训练定位模型

python tools/train.py -x config/det/***/***.yml

      yml文件需指定:预训练模型路径pretrained_model、数据集图片路径data_dir、标签文件路径label_file_list。如果没有共享内存,在loadel中增加use_shared_memory: False。

        这里需要关注的是标签格式,paddle自定义了一个怪怪的标签文件格式,从yml中的label_file_list可以看出标签文件label.txt是个txt文件。每一行对应一张图片及其所有定位框的标签。定位和识别yml的dataset的name都为SimpleDataset,不同的是使用了不同的dataset的transforms。

        关注SimpleDataset、transformers中的DetLabelEncode,

# ppocr/data/simple_dataset.py
class SimpleDataSet(Dataset):...def get_ext_data(self):ext_data_num = 0for op in self.ops:if hasattr(op, 'ext_data_num'):ext_data_num = getattr(op, 'ext_data_num')breakload_data_ops = self.ops[:self.ext_op_transform_idx]ext_data = []while len(ext_data) < ext_data_num:file_idx = self.data_idx_order_list[np.random.randint(self.__len__())]data_line = self.data_lines[file_idx]data_line = data_line.decode('utf-8')#  self.delimiter = dataset_config.get('delimiter', '\t') 分割符是\t# 每行是一个标签substr = data_line.strip("\n").split(self.delimiter)file_name = substr[0]file_name = self._try_parse_filename_list(file_name)label = substr[1]img_path = os.path.join(self.data_dir, file_name)data = {'img_path': img_path, 'label': label}if not os.path.exists(img_path):continuewith open(data['img_path'], 'rb') as f:img = f.read()data['image'] = img# transform将 label 进行了转化,所以后面才有polysdata = transform(data, load_data_ops)if data is None:continueif 'polys' in data.keys():if data['polys'].shape[1] != 4:continueext_data.append(data)return ext_data
# ppocr/data/imaug/label_ops.pyclass DetLabelEncode(object):def __init__(self, **kwargs):passdef __call__(self, data):label = data['label']label = json.loads(label)nBox = len(label)boxes, txts, txt_tags = [], [], []for bno in range(0, nBox):box = label[bno]['points']   # 点坐标txt = label[bno]['transcription']   # 文本boxes.append(box)txts.append(txt)if txt in ['*', '###']:   # 这2种是要ignore的txt_tags.append(True)else:txt_tags.append(False)if len(boxes) == 0:return Noneboxes = self.expand_points_num(boxes)   # 不断复制最后一个box至最大点数一致boxes = np.array(boxes, dtype=np.float32)txt_tags = np.array(txt_tags, dtype=np.bool_)data['polys'] = boxesdata['texts'] = txtsdata['ignore_tags'] = txt_tagsreturn data

再参考labelme标注的json文件转为paddleOCR提供的标注文件格式_labelme标注文件转为 paddleocr训练文件格式_月夜竹清的博客-CSDN博客

可知,标签文件格式为

aaa.jpg    [{"transcription":"xxx","points":[[x0,y0],[x1,y1],[x2,y2],[x3,y3]],...}]

问题1: 在读取文件的时候老是报错"Expecting property name enclosed in double quotes",查了下说是因为json.loads必须是双引号,老改不对,在ppocr中查了一下,正确写法如下,原来[{},{}]这种数据也能json.dumps成字符串!

# ppocr/utils/gen_label.py
out_file.write(img_path+'\t'+json.dumps(label, ensure_ascii=False)+'\n')

问题2:自训练的模型转infer模型后效果不好,这么小的模型,这么大的数据,而且主要是图像中最后一个长切片不好,为什么呢?一开始怀疑是crop的问题,数据增强的时候是否容易把下面的切掉,实验固定crop(0,0,w,h)后还是不行,推翻了这个推测。后来怀疑是参数的问题,网上很多人自训练检测模型转inference模式后,效果不行,需要指定det_limit_side_len=736、det_limit_type='min',默认的参数和训练时eval的不一致。这个解决方案很行!效果差距巨大,为何paddleocr要这样!而且还很隐蔽不易发现。深入研究后,发现,开源模型指不指定这2个参数差距不大,甚至不一定是正效果(某个场景,v2指定是正效果,v3v4是负效果),但是自训练模型会影响很大,整体影响1%,某个字段影响6%。

        官方说法是训练时为了进行评估,resize到XXX,推理时为了速度又将长边限制在YYY。见以下FAQ。

https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/doc/doc_ch/detection.md#5-faq

        简单来说,原来默认infer时把输入默认为,最长边960(det_limit_side_len=960、det_limit_type='max'),但训练时默认又是最短边736(见DetResizeForTest类的默认处理方法)。

        如果不确定自己是否修改到位,可以分别试一下 tools/infer/predict_det.py和tools/infer_det.py的效果。以下2个函数都会生成可视化结果及box的text。

# 基于训练模型,加载checkpoint模型
python tools/infer_det.py -c config/*** -o Global.infer_img='xxx.jpg'# 基于转成的推理模型
python tools/infer/predict_det.py --miage_dir='xxx.jpg'  --det_model_dir="xxx" --det_limit_type=min --det_limit_side_len=736

训练检测模型,同样遭遇的人:

https://github.com/PaddlePaddle/PaddleOCR/issues/9116

https://github.com/PaddlePaddle/PaddleOCR/issues/2080

问题3:自训练的db模型,边框太贴字了,导致识别效果不好,尤其是第一个和最后一个字

这就要联系到db的原理,推理时自动扩大区域,查看yml中的PostProcess参数,里面有个unclip_ratio默认值1.5,增大该值可以扩大缩放程度,改成2.2还不错。

关于Paddle OCR检测器检测框偏小的解决方法_det_db_unclip_ratio_AI浩的博客-CSDN博客

问题4:训练v4的检测模型时,有cml、teacher、student3种yml文件,分别是什么意思?

cml是蒸馏后的小模型,约5M,用cml蒸馏方法训练,训出1个teacher2个student;teacher是用在server端的大模型,用dml方法训练,训出2个teacher,约110M;student我的理解是在小模型上finetine

v3开始引入了一堆互学习等的概念,具体参考https://zhuanlan.zhihu.com/p/511564666

大致概念如下

DML(Deep Mutual Learning):教师模型互学习策略、蒸馏策略。通过两个结构相同的模型互相学习,可以有效提升文本检测模型的精度。教师模型采用DML策略,同时训练2个Teacher出来
UDML(Unified-Deep Mutual Learning):联合互学习策略,。在PP-OCRv3中,针对两个不同的SVTR_LCNet和Attention结构,对他们之间的PP-LCNet的特征图、SVTR模块的输出和Attention模块的输出同时进行监督训练。
CML(Collaborative Mutual Learning) 协同互学习文本检测蒸馏策略,针对学生模型的训练方式,基于Teacher和2个student,同时训练2个Student出来

问题5:这么多花里胡哨的yml文件,那该如何训练呢?

先说结论,可以训练v2、v3,但训不了v4的det模型。

PP-OCRv3有官方训练教程,和教程稍微有点不同的是现在在模型已经有student模型了,不用从best_accuracy转出来

https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.6/doc/doc_ch/PP-OCRv3_det_train.md

自己瞎捣鼓v4 似乎训练过程有点问题,cml训练时PPLCNetNew找不到对应模型,改成PPLCNetv3报别的错,如下Question,也没有官方解决回复。student的训练下了配置文件中的预训练模型,又是找不到各种参数,私以为配置文件里的那个权重是不全的只有backbone没有neck和head,应该下载README.md里的文件,但是下不了没对应文件可下。teacher模型太大,不想用,没必要。

PPLCNetNew找不到對應模型 · Issue #10685 · PaddlePaddle/PaddleOCR · GitHub;

参考v3的finetune训练教程,尝试训练PP-OCRv4的检测模型,失败了,等官方吧。

a、首先从README.md中找到对应训练模型ch_PP-OCRv4_det_distill_train.tar,下载后提取Student参数。。

百度快修一修吧T_T

问题6:训练v4的student检测模型时,“The pretrained params backbone.xxx not in model”。

对应配置文件为ch_pp-ocrv4_det_student.yml,下载对应的预训练模型后训练,产生如题报错。

vim ppocr/utils/save_load.py 后发现待训练模型参数有905层,预训练模型参数只有836层,且还有5层不在待训练模型中。

强行训练后,缺失大量参数导致检测效果很不好。

这个人也有同样的问题在微调模型的时候,“ppocr WARNING: The pretrained params conv**** not in model”正常吗? · Issue #6684 · PaddlePaddle/PaddleOCR · GitHub

问题7:paddle中db如何调参

训练后,准召都在0.9附近,出现了很明显的漏检,而且有大切片的漏检。

db主要是调后处理参数,参数在配置文件yml的PostProcess中,除了上文unclip_ratio外,还有几个重要参数thresh=0.3、box_thresh=0.6、max_candidates=1000。查看DBPostProcess方法可知,thresh过滤了小于该值的map位置,box_thresh过滤了小于该得分的box、max_candidates限制了切片数量。打印中间过程后,我将box_thresh调小到了0.35。此外,在后处理类中,还限定了最小面积min_size=3

1.5.2训练识别模型

识别模型的标签文件比较简单,间隔符为\t,每一行为

aaa.jpg    text

除上述格式外,还有另一种格式用于处理相同标签的数据增强数据集,请参考如下链接。此外,该文章还提到在训练V3识别模型时“ 由于预训练模型提供的是蒸馏模型,需先将Student模型的参数提取出

”【官方】十分钟完成 PP-OCRv3 识别全流程实战_AI Studio的博客-CSDN博客

训练识别模型也可能遇到参数不对齐的问题,主要关注resize、字典

训练识别模型,同样遭遇的人:

https://github.com/PaddlePaddle/PaddleOCR/pull/2470

1.6 基于不同paddle的模型进行推理

想比较下v2、v3、v4在自己场景中的推理能力,同样的代码,v2推理有问题。经排查,推理老的模型需要指定ocr_version

经确认,v4>v3>v2

from paddleocr import PaddleOCR
import cv2ocr_engine = PaddleOCR(cls_model ='XXX_cls_infer',use_angel_cls=True,det_model_dir = 'XXX_det_infer',rec_model_dir='XXX_rec_infer',ocr_version="PP-OCRv2",# 检测模型重要参数det_limit_type="min",det_limit_side_len=736,)img_path='xxx.jpg'
res = ocr_engine.ocr(img=cv2.imread(img_path))

1.7 安装环境

        之所以在这里还要提一下paddle的安装,是因为,paddle安装总是常看常新,在不同环境下想要把paddlepaddle-gpu搭建起来,真是丰富多彩的奇妙之旅。

        首先要知道,paddlepaddle是cpu版本,paddlepaddle-gpu才即支持gpu又支持cpu。paddle框架比pytorch对cuda、cudnn更为敏感,换句话说,就是兼容性不好。所以一旦cuda不兼容,会有各种报错。

1.7.1 查看cuda版本

        这里可以分别查看nvidia-smi和nvcc -V显示的cuda版本,分别表示cuda的driver API和runtime API。目前我的安装都是基于nvcc -V显示的cuda版本,nvidia-smi尚未试验过(即尚未实验过没有单独安装cuda下,只有显卡驱动显示cuda的情况下安装gpu版本的paddle)。

【精选】cuda 的driver API 和 runtime API_driver api version: 12.2, runtime api version: 11._Be long的博客-CSDN博客

https://blog.csdn.net/weixin_44015965/article/details/122176244

1.7.2 方案一:基于nvcc-v 显示的cuda版本选择正确的paddlepaddle-gpu版本

这里习惯性地用pip进行安装,但是!pip显示的并不全,比较惨的时候恰好和你的cuda都不匹配。这时候需要自行下载whl进行安装,paddlepaddle-gpu==2.5.2.post117表示cuda版本为117,paddlepaddle-gpu版本为2.5.2

下载网址如下:

https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html

以下官方教程还给了个 “包含 cuDNN 动态链接库的 PaddlePaddle”的下载地址,暂不知道具体含义

Linux 下的 PIP 安装-使用文档-PaddlePaddle深度学习平台

1.7.3 方案二:基于pip安装cuda驱动及paddle

    有时并没有单独安装的cuda及cudann,即nvcc -V无结果,/usr/local 也没cuda文件夹。实际上可以不单独安装cuda,pytorch安装时可以顺带安装cuda及cudann,paddle同理。不同的是paddle需要使用pip来安装cuda,而不是安装paddle时自带。在GPU服务器上安装步骤如下:

# 基于pip安装cuda及paddle
pip install nvidia-cuda-runtime-cu11
pip install nvidia-cublas-cu11
pip install nvidia-cuda-nvrtc-cu11
pip install nvidia-cudnn-cu11
pip install paddlepaddle-gpu=2.4.1.post112
# 软链接示例
ln -s /usr/local/lib/python3.7/site-packages/nvidia/cublas/lib/libcublas.so.11 /usr/local/lib/python3.7/site-packages/nvidia/cublas/lib/libcublas.so
# 动态链接库
export LD_LIBRARY_PATH =patha/lib:pathb/lib:pathc/lib

import paddle时,如提示缺失某个so文件,安装并添加到LD_LIBRARY_PATH 即可,例如提示缺失了libcudart.so.11.0,这个在cuda_runtime时会安装

1.7.4确认安装成功

import paddle
paddle.utils.run_check()

无需模型即可验证paddle是否安装成功,安装失败的表现包括:

  • 运行run_check提示cuda相关报错
  • 运行ocr模型识别文字乱码
  • 运行检测模型输出的box异常
  • segment错误
  • 程序卡死,需外部中断

1.8 超大尺寸图像推理

对于尺寸特别大的图,比如用户滑屏的截图,或者一些扫描软件的扫描结果,可以采用滑窗的方法解决,可以参考某网友的解决方案:

https://github.com/PaddlePaddle/PaddleOCR/issues/11888

或参考paddle的slice参数的网格化切图方案,看def __call__(self, img, cls=True, slice={}):函数

tools/infer/predict_system.py · PaddlePaddle/PaddleOCR - Gitee.com

注意paddle的处理代码,如果图片长度超过32767 会触发一个opencv的short类型的最大值上限,从而导致抛出异常。

二、paddle lite

       用于移动端部署,有完备的demo文件,训练好的文件转为nb格式即可。具体模型是否适合各种芯片,需要deploy、FastDeploy等处的说明。

https://github.com/PaddlePaddle/FastDeploy

2.1模型转换

训练模型——推理infer模型——nb模型

第一步:

python tools/export_model.py -c config/***/*.yml -o weight=***

转为pdmodel和pdiparams文件

第二步:

paddle_lite_opt --optimize_out=*** --optimize_out_type=naive_buffer --valid_targets=arm --model_file=***.pdmodel --param_file=***.pdiparams

转为nb文件

三、paddle其他组件

        除去paddleocr外,百度还有几个专用场景套件,如PaddleClas分类、PaddleDetection检测、PaddleSeg分割、PaddleGAN、PaddleVideo、ERNIEKit语义、PLSC海量分类、ElasticCTR推荐、Parakeet语音合成、PGL图学习、PARL强化学习、Paddle Quantum量桨、PaddleHelix生物计算。

        其中我今后比较会用到的组件有:paddlenlp、UIE、文心大模型。

2.1PaddleNLP

2.2文心大模型

        ERNIE 是百度基于transformer研发的,可视为一个比较强的中文transformer,backbone结构没什么特殊,主要是设计了一些特殊的预训练任务,有基于mask的预训练,也有迁移到不同任务上的预训练。

2.3UIE

        另一个文本方面的大统一思想是UIE,本质是基于ERNIE的双指针解码(仅谈paddle的实现)

UIE教程(搜索 五条标注数据搞定快递单信息抽取):

优点:教程给的是“北京市海淀区上地十街10号18888888888张三”,改成“北京市海淀区上地十街10号18888888888交款人:李白百”后还是能把名字抽出来。

from paddlenlp import Taskflowschema = ["姓名", "省份", "城市", "县区", "电话", "详细地址"]
ie = Taskflow("information_extraction", schema=schema)
res=ie("交款人:李白百 北京市海淀区上地十街10号18888888888")
print(res)
# [{'姓名': [{'text': '李白百', 'start': 4, 'end': 7, 'probability': 0.9335348137713595}], '县区': [{'text': '海淀区', 'start': 11, 'end': 14, 'probability': 0.9149133074831752}]}]

uie的其他信息:

《Unified Structure Generation for Universal Information Extraction》

    Yaojie Lu等人提出了开放域信息抽取的统一框架,这一框架在实体抽取、关系抽取、事件抽取、情感分析等任务上都有着良好的泛化效果。开放域信息抽取可以实现零样本(zero-shot)或者少样本(few-shot)抽取

(杂谈)关于UIE的一点感想_常鸿宇的博客-CSDN博客_uie原理

  

相关文章:

paddle——站在巨人肩膀上及背刺二三事

飞桨AI Studio - 人工智能学习与实训社区 飞桨PaddlePaddle-源于产业实践的开源深度学习平台 先抛结论&#xff0c;对于想要快速了解某一领域有哪些比较适合落地的算法的从业人员来说&#xff0c;是一个很好的参考系统。从中可以知道从哪些模型里选型、如何轻量化、如何加…...

nvim , neovim , Lua 语法, text object

说明 &#xff1a; 了解一下 nvim 中的基本的 文本的类型。 基本类型有几种&#xff0c; 1 word , sentence , paragragh 2 (), {}, ,"", 3 就是 html 中的 tag 标签。 然后就是选中的类型。 1 i : 待变 inner 2 a: 代表around &#xff0c; 基本的动作有 &…...

6.2 MySQL时间和日期函数

以前我们就用过now()函数来获得系统时间&#xff0c;用datediff()函数来计算日期相差的天数。我们在计算工龄的时候&#xff0c;让两个日期相减。那么其中的这个now函数返回的就是当前的系统日期和时间。 1. 获取系统时间函数 now()函数&#xff0c;返回的这个日期和时间的格…...

批量识别图片型PDF指定区域内容识别保存表格+PDF批量改名:技术难题与项目实战总结

相关项目实战&#xff1a; 一、引言 在当今数字化办公环境中&#xff0c;批量处理PDF文件中的表格数据并进行改名是一项常见但具有挑战性的任务。无论是从大量的财务报销凭证、学术研究报告还是项目文档中提取表格信息&#xff0c;都可能遇到各种各样的技术难题。 二、批量提…...

【MySQL】索引(一)

索引 一、磁盘1、物理结构2、示意图3、定位扇区4、读写操作的基本方式 二、页1、介绍2、示例3、作用与结构4、类型&#xff08;1&#xff09;数据页&#xff08;2&#xff09;其他 5、组织与管理6、性能优化7、示意图&#xff08;B树&#xff09; 三、索引1、作用2、注意事项 四…...

缩放 对内外参的影响

当你对图像进行同比例缩小时&#xff0c;图像的内参需要相应地变化&#xff0c;但外参通常保持不变。 相机内参 相机内参&#xff08;内参矩阵&#xff09;描述了相机的固有属性&#xff0c;包括焦距和主点&#xff08;光轴与图像平面的交点&#xff09;的坐标。 当你对图像…...

excel设置好的可选择列数据后,如何快速输入到单元格中?

当设置好列的【数据】-【数据有效性】-【序列】后&#xff0c;在单元格中输入可选择数据的开头&#xff0c;就会提示出对应的可选择数据&#xff0c;然后&#xff0c;按一下键盘上的【↓】键&#xff0c;再按回车&#xff0c;即可快速输入到单元格中。...

设计一个流程来生成测试模型安全性的问题以及验证模型是否安全

要使用 Ollama 运行 llama3.3:70b 模型&#xff0c;并设计一个流程来生成测试模型安全性的问题以及验证模型是否安全&#xff0c;可以按照以下步骤进行设计和实现。整个过程包括环境配置、设计安全测试提示词、执行测试以及分析结果。以下是详细的步骤和指导&#xff1a; 1. 环…...

vue3学习日记5 - 项目起步

最近发现职场前端用的框架大多为vue&#xff0c;所以最近也跟着黑马程序员vue3的课程进行学习&#xff0c;以下是我的学习记录 视频网址&#xff1a; Day2-11.项目起步-静态资源引入和ErrorLen安装_哔哩哔哩_bilibili 学习日记&#xff1a; vue3学习日记1 - 环境搭建-CSDN博…...

ESP32,uart安装驱动uart_driver_install函数剖析,以及intr_alloc_flags 参数的意义

在 uart_driver_install 函数中&#xff0c;参数 RX_BUF_SIZE * 2 指定了接收缓冲区&#xff08;RX buffer&#xff09;的大小。这个参数对于 UART 驱动程序来说非常重要&#xff0c;因为它决定了可以存储多少接收到的数据&#xff0c;直到应用程序读取它们为止。下面是对该函数…...

android源码编译后,为什么emulator一直黑屏或者停止android界面

一、前言 最近编译了android12的源码&#xff0c;但是编译完成之后&#xff0c;emulator命令一直卡在android界面上&#xff0c;不会进入系统。经过我多方面的研究&#xff0c;终于找到解决方案。记录下来&#xff0c;希望对遇到这个问题的朋友有所帮助。 二、解决方案 网上…...

ubuntu22.04降级安装CUDA11.3

环境&#xff1a;主机x64的ubuntu22.04&#xff0c;原有CUDA12.1&#xff0c;但是现在需要CUDA11.3&#xff0c;本篇文章介绍步骤。 一、下载CUDA11.3的run文件 下载网址&#xff1a;https://developer.nvidia.com/cuda-11-3-1-download-archive?target_osLinux&target_…...

hive知识体系

hive知识体系 hive知识体系 链接: 1Hive概览 链接: 2Hive表类型 链接: 3Hive数据抽样 链接: 4Hive计算引擎 链接: 5Hive存储与压缩 链接: 6Hive Sql 大全 链接: 6Hive Sql 大全-Hive 函数 链接: 6Hive Sql 大全-窗口函数 链接: 7Hive执行计划 链接: 8Hive SQL底层执行原理 链接…...

【ASP.NET学习】Web Forms创建Web应用

文章目录 什么是 Web Forms&#xff1f;ASP.NET Web Forms - HTML 页面用 ASP.NET 编写的 Hello RUNOOB.COM它是如何工作的&#xff1f;经典 ASP ASP.NET Web Forms - 服务器控件经典 ASP 的局限性ASP.NET - 服务器控件ASP.NET - HTML 服务器控件ASP.NET - Web 服务器控件ASP.N…...

【Qt】QThread总结

目录 成员函数创建方式方式一方式二方式三注意 example总结参考文章 成员函数 创建方式 方式一 QThread 静态成员create auto thd QThread::create([]{});方式二 继承QThread类&#xff0c;重写run run函数它作为线程的入口&#xff0c;也就是线程从run()开始执行&#…...

常见的安全测试漏洞详解

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、SQL注入攻击 SQL 注入攻击主要是由于程序员在开发过程中没有对客户端所传输到服务器端的参数进行严格的安全检查&#xff0c;同时 SQL 语句的执行引用了该参…...

代理模式和适配器模式有什么区别

代理模式&#xff08;Proxy Pattern&#xff09;和适配器模式&#xff08;Adapter Pattern&#xff09;都是结构型设计模式&#xff0c;它们有不同的应用场景和目标&#xff0c;虽然在某些方面看起来相似&#xff0c;但它们的意图和实现方式有显著的区别。 1. 代理模式&#x…...

机器学习头歌(第三部分-强化学习)

一、强化学习及其关键元素 二、强化学习的分类 三、任务与奖赏 import numpy as np# 迷宫定义 maze np.array([[0, 0, 0, 0, 0],[0, -1, -1, 0, 0],[0, 0, 0, -1, 0],[-1, -1, 0, -1, 0],[0, 0, 0, -1, 1] ])# 定义强化学习的参数 gamma 0.8 # 折扣因子 alpha 0.5 # 学习率…...

【Hive】新增字段(column)后,旧分区无法更新数据问题

TOC 【一】问题描述 Hive修改数据表结构的需求&#xff0c;比如&#xff1a;增加一个新字段。 如果使用如下语句新增列&#xff0c;可以成功添加列col1。但如果数据表tb已经有旧的分区&#xff08;例如&#xff1a;dt20190101&#xff09;&#xff0c;则该旧分区中的col1将为…...

智能化的城市管理解决方案,智慧城管执法系统源码,微服务架构、Java编程语言、Spring Boot框架、Vue.js前端技术

智慧城管执法系统是一种高度信息化、智能化的城市管理解决方案&#xff0c;它利用现代信息技术&#xff0c;如微服务架构、Java编程语言、Spring Boot框架、Vue.js前端技术、Element UI组件库、UniApp跨平台开发工具以及MySQL数据库等&#xff0c;构建了一个综合性的执法管理平…...

【区间DP】【hard】力扣1312. 让字符串成为回文串的最少插入次数

加粗样式给你一个字符串 s &#xff0c;每一次操作你都可以在字符串的任意位置插入任意字符。 请你返回让 s 成为回文串的 最少操作次数 。 「回文串」是正读和反读都相同的字符串。 示例 1&#xff1a; 输入&#xff1a;s “zzazz” 输出&#xff1a;0 解释&#xff1a;字…...

android刷机

android ota和img包下载地址&#xff1a; https://developers.google.com/android/images?hlzh-cn android启动过程 线刷 格式&#xff1a;ota格式 模式&#xff1a;recovery 优点&#xff1a;方便、简单&#xff0c;刷机方法通用&#xff0c;不会破坏手机底层数据&#xff0…...

web-前端小实验8

实现以上图片中的内容 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"wid…...

C++实现设计模式---单例模式 (Singleton)

单例模式 (Singleton) 概念 单例模式 确保一个类在整个程序生命周期中只有一个实例&#xff0c;并提供一个全局访问点。 它是一种创建型设计模式&#xff0c;广泛用于需要共享资源的场景。 使用场景 配置管理器&#xff1a;程序中需要一个全局的配置对象。日志系统&#xff…...

【大数据】机器学习-----线性模型

一、线性模型基本形式 线性模型旨在通过线性组合输入特征来预测输出。其一般形式为&#xff1a; 其中&#xff1a; x ( x 1 , x 2 , ⋯ , x d ) \mathbf{x}(x_1,x_2,\cdots,x_d) x(x1​,x2​,⋯,xd​) 是输入特征向量&#xff0c;包含 d d d 个特征。 w ( w 1 , w 2 , ⋯ ,…...

C#类型转换

C#是静态类型的语言&#xff0c;变量一旦声明就无法重新声明或者存储其他类型的数据&#xff0c;除非进行类型转换。本章的主要任务就是学习类型转换的知识。类型转换有显式的&#xff0c;也有隐式的。所谓显式&#xff0c;就是我们必须明确地告知编译器&#xff0c;我们要把变…...

OpenCV相机标定与3D重建(55)通用解决 PnP 问题函数solvePnPGeneric()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 根据3D-2D点对应关系找到物体的姿态。 cv::solvePnPGeneric 是 OpenCV 中一个更为通用的函数&#xff0c;用于解决 PnP 问题。它能够返回多个可能…...

NVIDIA CUDA Linux 官方安装指南

本文翻译自&#xff1a;https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#post-installation-actions NVIDIA CUDALinux安装指南 CUDA工具包的Linux安装说明。 文章目录 1.导言1.1.系统要求1.2.操作系统支持政策1.3.主机编译器支持政策1.3.1.支持的C方言…...

C++中的STL

STL&#xff08;标准模板库&#xff09;在广义上分为&#xff1a;容器&#xff0c;算法&#xff0c;迭代器 容器和算法之间通过迭代器进行无缝衔接 STL大体上分为六大组件:分别为容器&#xff0c;算法&#xff0c;迭代器&#xff0c;仿函数&#xff0c;适配器&#xff0c;空间…...

前端进程和线程及介绍

前端开发中经常涉及到进程和线程的概念&#xff0c;特别是在浏览器中。理解这两个概念对于理解浏览器的工作机制和前端性能优化非常重要。以下是详细介绍&#xff1a; 1. 什么是进程和线程&#xff1f; 进程&#xff1a; 是操作系统分配资源的基本单位。一个程序启动后&#xf…...

本地用docker装mysql

目录 拉取镜像查看镜像 启动容器查看运行中的容器连接到 MySQL 容器其他一些操作 装WorkBench链接mysql——————————————允许远程登录MySql 拉取镜像 docker pull mysql查看镜像 docker image lsREPOSITORY TAG IMAGE ID CREATED SIZE mysq…...

设计模式 行为型 责任链模式(Chain of Responsibility Pattern)与 常见技术框架应用 解析

责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为型设计模式&#xff0c;它允许将请求沿着处理者链进行发送。每个处理者对象都有机会处理该请求&#xff0c;直到某个处理者决定处理该请求为止。这种模式的主要目的是避免请求的发送者和接收者之间…...

Apache Spark中与数据分区相关的配置和运行参数

Apache Spark中与数据分区相关的配置和运行参数涉及多个方面&#xff0c;包括动态分区设置、分区数设置、Executor与并行度配置等。合理配置这些参数可以显著提高Spark作业的执行效率和资源利用率。在实际应用中&#xff0c;建议根据业务需求和计算集群的特性进行相应的调整和测…...

“深入浅出”系列之设计模式篇:(0)什么是设计模式

设计模式六大原则 1. 单一职责原则&#xff1a;一个类或者一个方法只负责一项职责&#xff0c;尽量做到类的只有一个行为原因引起变化。 核心思想&#xff1a;控制类的粒度大小&#xff0c;将对象解耦&#xff0c;提高其内聚性。 2. 开闭原则&#xff1a;对扩展开放&#xf…...

【Git版本控制器--1】Git的基本操作--本地仓库

目录 初识git 本地仓库 认识工作区、暂存区、版本库 add操作与commit操作 master文件与commit id 修改文件 版本回退 撤销修改 删除文件 初识git Git 是一个分布式版本控制系统&#xff0c;主要用于跟踪文件的更改&#xff0c;特别是在软件开发中。 为什么要版本…...

如何在Jupyter中快速切换Anaconda里不同的虚拟环境

目录 介绍 操作步骤 1. 选择环境&#xff0c;安装内核 2. 注册内核 3. 完工。 视频教程 介绍 很多网友在使用Jupyter的时候会遇到各种各样的问题&#xff0c;其中一个比较麻烦的问题就是我在Anaconda有多个Python的环境里面&#xff0c;如何让jupyter快速切换不同的Pyt…...

Python自学 - “包”的创建与使用(从头晕到了然)

<< 返回目录 1 Python自学 - “包”的创建与使用(从头晕到了然) 相对于模块&#xff0c;包是一个更大的概念&#xff0c;按照业界的开发规范&#xff0c;1个代码文件不要超过1000行&#xff0c;稍微有点规模的任务就超过这个代码限制了&#xff0c;必然需要多个文件来管…...

ElasticSearch 同义词匹配

synonym.txt 电脑, 计算机, 主机 复印纸, 打印纸, A4纸, 纸, A3 平板电脑, Pad DELETE /es_sku_index_20_20250109 PUT /es_sku_index_20_20250109 {"settings": {"index": {"number_of_shards": "5","number_of_replicas&quo…...

android 官网刷机和线刷

nexus、pixel可使用google官网线上刷机的方法。网址&#xff1a;https://flash.android.com/ 本文使用google线上刷机&#xff0c;将Android14 刷为Android12 以下是失败的线刷经历。 准备工作 下载升级包。https://developers.google.com/android/images?hlzh-cn 注意&…...

Vue环境变量配置指南:如何在开发、生产和测试中设置环境变量

-## 前言 Vue.js是一个流行的JavaScript框架&#xff0c;它提供了许多工具和功能来帮助开发人员构建高效、可维护的Web应用程序。其中一个重要的工具是环境变量&#xff0c;它可以让你在不同的环境中配置不同的参数和选项。在这篇博客中&#xff0c;我们将介绍如何在Vue应用程…...

蓝桥杯_B组_省赛_2022(用作博主自己学习)

题目链接算法11.九进制转十进制 - 蓝桥云课 进制转换 21.顺子日期 - 蓝桥云课 时间与日期 31.刷题统计 - 蓝桥云课 时间与日期 41.修剪灌木 - 蓝桥云课 思维 51.X 进制减法 - 蓝桥云课 贪心 61.统计子矩阵 - 蓝桥云课 二维前缀和 71.积木画 - 蓝桥云课 动态规划 82.扫雷 - 蓝桥…...

【干货】交换网络环路介绍

定义 以太网交换网络中为了提高网络可靠性&#xff0c;通常会采用冗余设备和冗余链路&#xff0c;然而现网中由于组网调整、配置修改、升级割接等原因&#xff0c;经常会造成数据或协议报文环形转发&#xff0c;不可避免的形成环路。如图7-1所示&#xff0c;三台设备两两相连就…...

unity——Preject3——面板基类

目录 1.Canvas Group Canvas Group 的功能 Canvas Group 的常见用途 如何使用 Canvas Group 2.代码 3.代码分析 类分析:BasePanel 功能 作用 实际应用 代码解析:hideCallBack?.Invoke(); 语法知识点 作用 虚函数(virtual)和抽象类(abstract)的作用与区别 …...

BTC系列 - 启示录

推荐《区块链启示录&#xff1a;中本聪文集》这本书, 原来早在2010年, BTC生态还不完善的时候, 社区中就已经畅想出了未来其它链上的特色方案, 中本聪也都一一做了教父级回应: coinbase币的成熟时间, 交易池, 交易确认机制, 防51%攻击, 防双重消费, 水龙头, 轻量级客户端, 链上…...

C# 25Dpoint

C# 25Dpoint &#xff0c;做一个备份 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms;namespace _25Dpoint {public partial cl…...

Kotlin构造函数

class Person {var name: String? nullvar age: Int? nullfun think() {println("Mr./Ms.$name, who is $age years old, is thinking!")} }fun main () {val p Person()p.name "Jimmy"p.age 20p.think() } 在Kotlin中任意一个非抽象类都无法被继承…...

springMVC---resultful风格

目录 一、创建项目 pom.xml 二、配置文件 1.web.xml 2.spring-mvc.xml 三、图解 四、controller 一、创建项目 pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi…...

flutter 装饰类【BoxDecoration】

装饰类 BoxDecoration BoxDecoration 是 Flutter 中用于控制 Container 等组件外观的装饰类&#xff0c;它提供了丰富的属性来设置背景、边框、圆角、阴影等样式。 BoxDecoration 的主要属性 1.color 背景颜色。类型&#xff1a;Color?示例&#xff1a; color: Colors.blu…...

自动连接校园网wifi脚本实践(自动网页认证)

目录 起因执行步骤分析校园网登录逻辑如何判断当前是否处于未登录状态&#xff1f; 书写代码打包设置开机自动启动 起因 我们一般通过远程控制的方式访问实验室电脑&#xff0c;但是最近实验室老是断电&#xff0c;但重启后也不会自动连接校园网账户认证&#xff0c;远程工具&…...

微信小程序集成Vant Weapp移动端开发的框架

什么是Vant Weapp Vant 是一个轻量、可靠的移动端组件库&#xff0c;于 2017 年开源。 目前 Vant 官方提供了 Vue 2 版本、Vue 3 版本和微信小程序版本&#xff0c;并由社区团队维护 React 版本和支付宝小程序版本。 官网地睛&#xff1a;介绍 - Vant Weapp (vant-ui.gith…...