用Lisp的方言HY跑飞桨训练和推理

用Lisp的方言HY跑飞桨训练和推理

整个项目可以在AIStudio一键跑通:用Lisp的方言HY跑飞桨训练和推理 - 飞桨AI Studio星河社区

初见Lisp

估计很多人都看过《黑客与画家》这本书,百度百科中的条目:《黑客与画家:硅谷创业之父paul graham文集》是硅谷创业之父paul graham 的文集,主要介绍黑客即优秀程序员的爱好和动机,讨论黑客成长、黑客对世界的贡献以及编程语言和黑客工作方法等所有对计算机时代感兴趣的人的一些话题。

Paul在他的著作中极力推崇Lisp语言,将其誉为最佳的编程语言。据悉很多读者在阅读后都深受其影响。现在,我们有了在星河社区亲自实践Lisp的机会!尽管我们可能还无法与大牛们并肩,但是我们可以阅读他们的书籍,倾听他们的见解,并跟随他们的实践来磨练我们的Lisp技能。Lisp是人工智能的开发语言,上一次人工智能浪潮中它曾风靡一时。虽然它在这次的AI浪潮中无声无息并未占据主导地位,但谁能预测Lisp不会在下一次AI浪潮中大放异彩呢?

一、简单了解Lisp

Lisp(List Processing,列表处理)是一种具有悠久历史和独特魅力的编程语言,自上世纪50年代诞生以来,一直在计算机科学领域发挥着重要作用。Lisp以其简洁、优雅和强大的表达能力而著称,成为了函数式编程和人工智能领域的先锋。

Lisp的特点之一是其代码和数据结构的统一性,这使得Lisp具有极高的灵活性,可以轻松操作和处理复杂的数据结构。其独特的宏系统也为元编程提供了强大的工具,允许程序员创建自己的语言扩展和DSL(领域特定语言)。

1、Lisp的优缺点

它的优点和缺点都非常鲜明:

优点是使用前置运算符,语法非常简单

缺点是前置运算符是违反人类习惯的

另外因为Lisp语法非常简单,所以很多大牛都对Lisp进行了功能添加,新的语言被成为Lisp方言,这导致Lisp方言不计其数,这极大增加了初学者的学习成本。

比如我们学python、C语言,赋值语句都是x = 1这样的,而Lisp的方言中,common Lisp是(defvar x 1) scheme中是(define x 1) hy中是(setv x 1), 这些都完全不挨着,可以说Lisp方言,除了使用前置运算符是一样的,其它完全可以没有任何一点关系!

2、Lisp方言HY

Hy(或“Hylang”)是Lisp家族中的一种多范式通用编程语言,以膜翅目昆虫目命名,因为Paul Tagliamonte在创建该语言时正在研究群体行为。它被实现为Python的一种替代语法。与Python相比,Hy提供了各种额外的功能、概括和语法简化,正如Lisp所期望的那样。与其他Lisp相比,Hy提供了对Python内置库和第三方Python库的直接访问,同时允许您自由混合命令式、函数式和面向对象的编程风格。

Python程序员会注意到的关于Hy的第一件事是,它使用了Lisp的传统括号前缀语法来代替Python的类C中缀语法。例如,print("The answer is", 2 + object.method(arg)) 可以在Hy中书写(print "The answer is" (+ 2 (.method object arg)))

3、Lisp方言HY环境配置

pip安装HY库

!pip install hy -q

4、测试:使用HY初试Lisp语法

将x赋值1,然后再加上1,我们会看到输出结果为2

我们已经根据前面知道赋值语句是这样的(setv x 1) ,而对于前缀运算来说,常见的运算x= x+1是这样的(+ x 1),另外需要注意:Lisp里面如果不用赋值语句的话,那么执行完结果是不会修改原变量的。比如下面的语句,运算结束后输出结果为2,但是这个2并不会赋值给x 。如果需要赋值,可以这样写(setv x 1) (setv x (+ x 1)) ,因为需要显式赋值,所以Lisp代码相对其它编程语言会较少使用赋值(不需要的就不赋值了)。

 import hy
 hy.eval(hy.read_many("(setv x 1) (+ x 1)"))
2

将1赋值给x,然后返回x+1的值,果然是2,算对啦!

来个复杂的句子,导入飞桨库,创建一个随机的[2, 3]维度的矩阵,打印x的值,并打印x+1的值进行比较。
这段代码格式化为:

(import paddle) 
(setv x (paddle.randn [2,3] )) 
(print `x值:) 
(print x) 
(print `x+1值:) 
(print (+ x 1))
hy.eval(hy.read_many("(import paddle) (setv x (paddle.randn [2,3] )) (print `x值:) (print x) (print `x+1值:) (print (+ x 1))"))
x值:
Tensor(shape=[23], dtype=float32, place=Place(cpu), stop_gradient=True,
       [ 0.14839390, -0.73140484,  0.93431634, -1.44790399,  0.07094631,
         0.39240602, -0.46890527, -0.45317811,  0.07772370,  1.42541373,
         0.46317163,  0.77750325,  0.49435890,  0.63576186,  0.56791979,
         1.36508441, -0.26096687,  1.33353806, -0.21448247,  1.14773476,
         0.44072157,  1.07053936,  1.60521615])
x+1值:
Tensor(shape=[23], dtype=float32, place=Place(cpu), stop_gradient=True,
       [1.14839387, 0.26859516, 1.93431640, -0.44790399, 1.07094634, 1.39240599,
        0.53109473, 0.54682189, 1.07772374, 2.42541361, 1.46317160, 1.77750325,
        1.49435890, 1.63576186, 1.56791973, 2.36508441, 0.73903310, 2.33353806,
        0.78551751, 2.14773464, 1.44072151, 2.07053947, 2.60521603])

二、用HY跑飞桨训练模型

1、HY代码展示

因为HY中使用了类似hy.eval(hy.read_many(runpaddle))的语法,HY代码使用pyton字符串导入,因此没法语法高亮,我们先在Markdown里面看下加上语法高亮的HY代码:

(import paddle)  
(import paddle.vision.transforms [ToTensor])  
;(paddle.set_device "gpu")  
  
(pys "train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=ToTensor())")
(setv test-dataset (paddle.vision.datasets.MNIST :mode 'test :transform (ToTensor)))  
(setv lenet (paddle.vision.models.LeNet))  
  
; Mnist inherits from paddle.nn.Layer which is a Net, and model includes training functionality  
(setv model (paddle.Model lenet))  
  
; Set the optimizer, loss, and metric needed to train the model  
(model.prepare  
    (paddle.optimizer.Adam :learning_rate 0.001 :parameters (model.parameters))  
    (paddle.nn.CrossEntropyLoss)  
    (paddle.metric.Accuracy :topk [1 2])
    )  
  
; Start training  
(model.fit  train-dataset :epochs 2 :batch-size 64 :log-freq 400)  
  
; Start evaluation  
(model.evaluate  test-dataset :log-freq 100 :batch-size 64)

这部分代码由飞桨python代码转为HY的,可以看到还是比较容易看的懂的,跟python代码可以说是每行都有对应。

知识点:导入模块

导入飞桨直接用(import paddle) ,但是如果想导入子库,则from paddle.vision.transforms import ToTensor 要写成(import paddle.vision.transforms [ToTensor])

知识点:数据集读取

函数的传参,使用冒号+参数名+参数的格式,另外在Lisp中,单个引号可以理解为python中的一对引号。
HY(setv test-dataset (paddle.vision.datasets.MNIST :mode 'test :transform (ToTensor))) 对应python test_dataset = paddle.vision.datasets.MNIST(mode='test', transform=ToTensor())

训练集较大,HY报错:struct.error, 因此训练集赋值没有用上面的代码,而是在HY中调用了python代码来实现的:(pys "train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=ToTensor())")对应python train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=ToTensor())

知识点:HY注释用分号

比如这句话被注释掉了:;(paddle.set_device "gpu") 。归功于飞桨的自动识别cpu、GPU环境,我们HY代码也可以自如的在cpu和GPU环境下训练执行,而不用写set_device参数。

2、飞桨HY代码训练示例

第一次执行的时候需要下载数据集,因此会多花几秒,第二次之后速度就跟python下比较接近了。

import hy 
runpaddle = """
(import paddle)  
(import paddle.vision.transforms [ToTensor])  
;(paddle.set_device "gpu")  
  
(pys "train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=ToTensor())")
(setv test-dataset (paddle.vision.datasets.MNIST :mode 'test  :transform (ToTensor)))  
(setv lenet (paddle.vision.models.LeNet))  
  
; Mnist inherits from paddle.nn.Layer which is a Net, and model includes training functionality  
(setv model (paddle.Model lenet))  
  
; Set the optimizer, loss, and metric needed to train the model  
(model.prepare  
    (paddle.optimizer.Adam :learning_rate 0.001 :parameters (model.parameters))  
    (paddle.nn.CrossEntropyLoss)  
    (paddle.metric.Accuracy :topk [1 2])
    ;(paddle.metric.Accuracy :topk (1 2))
    )  
  
; Start training  
(model.fit  train-dataset :epochs 2 :batch-size 64 :log-freq 400)  
  
; Start evaluation  
(model.evaluate  test-dataset :log-freq 100 :batch-size 64)
"""
hy.eval(hy.read_many(runpaddle))
item  160/2421 [>.............................] - ETA: 1s - 651us/item

Cache file /home/aistudio/.cache/paddle/dataset/mnist/train-images-idx3-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/train-images-idx3-ubyte.gz 
Begin to download


item 8/8 [============================>.] - ETA: 0s - 4ms/item


Download finished
Cache file /home/aistudio/.cache/paddle/dataset/mnist/train-labels-idx1-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/train-labels-idx1-ubyte.gz 
Begin to download

Download finished


item 157/403 [==========>...................] - ETA: 0s - 880us/item

Cache file /home/aistudio/.cache/paddle/dataset/mnist/t10k-images-idx3-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/t10k-images-idx3-ubyte.gz 
Begin to download


item 2/2 [===========================>..] - ETA: 0s - 2ms/item


Download finished
Cache file /home/aistudio/.cache/paddle/dataset/mnist/t10k-labels-idx1-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/t10k-labels-idx1-ubyte.gz 
Begin to download

Download finished


The loss value printed in the log is the current step, and the metric is the average value of previous steps.
Epoch 1/2
step 400/938 - loss: 0.0354 - acc_top1: 0.9104 - acc_top2: 0.9607 - 28ms/step
step 800/938 - loss: 0.0288 - acc_top1: 0.9402 - acc_top2: 0.9761 - 28ms/step
step 938/938 - loss: 0.0354 - acc_top1: 0.9453 - acc_top2: 0.9786 - 28ms/step
Epoch 2/2
step 400/938 - loss: 0.0481 - acc_top1: 0.9788 - acc_top2: 0.9946 - 28ms/step
step 800/938 - loss: 0.0330 - acc_top1: 0.9798 - acc_top2: 0.9953 - 27ms/step
step 938/938 - loss: 0.0192 - acc_top1: 0.9801 - acc_top2: 0.9954 - 27ms/step
Eval begin...
step 100/157 - loss: 0.0029 - acc_top1: 0.9834 - acc_top2: 0.9972 - 14ms/step
step 157/157 - loss: 3.2777e-04 - acc_top1: 0.9867 - acc_top2: 0.9976 - 14ms/step
Eval samples: 10000





{'loss': [0.00032777030719444156], 'acc_top1': 0.9867, 'acc_top2': 0.9976}

也可以在控制台直接使用命令行来执行HY的代码,到work目录查看runpaddle.hy文件,可以看到它是纯的Lisp代码,运行输出如下:

!hy work/runpaddle.hy
The loss value printed in the log is the current step, and the metric is the average value of previous steps.
Epoch 1/2
step 400/938 - loss: 0.0469 - acc_top1: 0.9047 - acc_top2: 0.9558 - 28ms/step
step 800/938 - loss: 0.0396 - acc_top1: 0.9349 - acc_top2: 0.9727 - 27ms/step
step 938/938 - loss: 0.0681 - acc_top1: 0.9406 - acc_top2: 0.9755 - 27ms/step
Epoch 2/2
step 400/938 - loss: 0.0872 - acc_top1: 0.9743 - acc_top2: 0.9931 - 28ms/step
step 800/938 - loss: 0.0932 - acc_top1: 0.9757 - acc_top2: 0.9938 - 27ms/step
step 938/938 - loss: 0.0316 - acc_top1: 0.9761 - acc_top2: 0.9940 - 27ms/step
Eval begin...
step 100/157 - loss: 0.0091 - acc_top1: 0.9761 - acc_top2: 0.9942 - 12ms/step
step 157/157 - loss: 0.0022 - acc_top1: 0.9812 - acc_top2: 0.9955 - 12ms/step
Eval samples: 10000

使用hy.eval(hy.read_many(runpaddle)) 比HY控制台执行多了一行输出:{'loss': [0.00032777030719444156], 'acc_top1': 0.9867, 'acc_top2': 0.9976},这行输出就是hy.eval函数的返回值,是可以赋值给python变量的。

3、飞桨python代码训练对比

本身Lisp的速度是很快的,跟c语言接近,但是HY是编译成Pyhon伪代码进行执行的,所以没法比python快。

下面使用飞桨python代码训练,可以看到训练输出是一样的,训练时间也差不多,大约比Lisp快1秒。

import paddle 
from paddle.vision.transforms import ToTensor
# paddle.set_device("gpu")
train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=ToTensor())
test_dataset = paddle.vision.datasets.MNIST(mode='test', transform=ToTensor())
lenet = paddle.vision.models.LeNet()

# Mnist继承paddle.nn.Layer属于Net,model包含了训练功能
model = paddle.Model(lenet)

# 设置训练模型所需的optimizer, loss, metric
model.prepare(
    paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters()),
    paddle.nn.CrossEntropyLoss(),
    paddle.metric.Accuracy(topk=(1, 2))
    )

# 启动训练
model.fit(train_dataset, epochs=2, batch_size=64, log_freq=400)

# 启动评估
model.evaluate(test_dataset, log_freq=100, batch_size=64)
The loss value printed in the log is the current step, and the metric is the average value of previous steps.
Epoch 1/2
step 400/938 - loss: 0.0500 - acc_top1: 0.9109 - acc_top2: 0.9607 - 30ms/step
step 800/938 - loss: 0.0430 - acc_top1: 0.9389 - acc_top2: 0.9756 - 29ms/step
step 938/938 - loss: 0.0221 - acc_top1: 0.9442 - acc_top2: 0.9781 - 28ms/step
Epoch 2/2
step 400/938 - loss: 0.0440 - acc_top1: 0.9757 - acc_top2: 0.9936 - 27ms/step
step 800/938 - loss: 0.0332 - acc_top1: 0.9772 - acc_top2: 0.9947 - 28ms/step
step 938/938 - loss: 0.0349 - acc_top1: 0.9777 - acc_top2: 0.9949 - 28ms/step
Eval begin...
step 100/157 - loss: 0.0011 - acc_top1: 0.9812 - acc_top2: 0.9948 - 13ms/step
step 157/157 - loss: 0.0060 - acc_top1: 0.9858 - acc_top2: 0.9960 - 13ms/step
Eval samples: 10000





{'loss': [0.006007179617881775], 'acc_top1': 0.9858, 'acc_top2': 0.996}

通过上面的例子,我们对HY跑飞桨有了初步的了解,下面开始进阶到使用飞桨套件。

三、用HY调用PaddleClas图像识别示例

首先在PaddleClas repo官网找到python代码的示例:

import paddleclas
model = paddleclas.PaddleClas(model_name="person_exists")
result = model.predict(input_data="pulc_demo_imgs/person_exists/objects365_01780782.jpg")
print(next(result))

我们的任务就是将这段代码转为Lisp语法并使用HY来执行。首先需要:

1、 安装PaddleClas库

因为HY底层还是调用了PaddleClas库,所以首先要进行库的安装。

当前版本的PaddleClas(大约截止到2023年的年底)通过PIP安装可能不太顺利,因此要用源码编译安装,同时要把requirements.txt文件中faiss-cpu去掉,否则会导致编译失败。

# 若不成功,这里可以多运行几次,也可以按照下面的提示,点击“快捷下载”来下载该套件。
# !git clone https://www.github.com/PaddlePaddle/PaddleClas.git
!git clone https://www.gitee.com/PaddlePaddle/PaddleClas.git  

安装相关的库,faiss-cpu手工安装,并且pip使用work/requirements.txt文件进行安装。

!pip install pip -U
!pip install faiss-cpu
!pip install -r work/requirements.txt

编译安装,还是使用了work/requirements.txt文件,以便编译通过。

# !tar -xzvf work/paddleclas.tar.gz 
!cp work/requirements.txt PaddleClas/
!cd PaddleClas && python setup.py install

测试padddleclas库是否安装好,如果前面已经编译安装好,而这里导入的时候报错No module named 'paddleclas', 那么只需要重启内核即可。

import paddleclas

2、 开始paddleclas识别任务

下面开始执行paddleclas模型任务,这是一个识别图片中有没有人的任务,代码量跟python一样多。当然有大神说Lisp代码量可以比Python 和C更精简,但是一味追求低代码量可读性就比较差了。

可以看到即使用cpu也可以在一秒内跑出结果,飞桨真棒!

import hy
runpaddleclas = """
(import paddleclas)
(setv model (paddleclas.PaddleClas :model_name "person_exists"))
;(setv result (model.predict :input_data "work/pulc_demo_imgs/person_exists/objects365_01780782.jpg"))
(setv result (.predict model :input_data "work/pulc_demo_imgs/person_exists/objects365_01780782.jpg"))  
 
(next result)
"""
hy.eval(hy.read_many(runpaddleclas))
[2023/12/14 10:51:57] ppcls INFO: download https://paddleclas.bj.bcebos.com/models/PULC/inference/person_exists_infer.tar to /home/aistudio/.paddleclas/inference_model/PULC/person_exists/person_exists_infer.tar


100%|██████████| 7.29M/7.29M [00:00<00:00, 22.9MiB/s]

[2023/12/14 10:51:57] ppcls WARNING: The current running environment does not support the use of GPU. CPU has been used instead.








[{'class_ids': [0],
  'scores': [0.9955421285703778],
  'label_names': ['nobody'],
  'filename': 'work/pulc_demo_imgs/person_exists/objects365_01780782.jpg'}]

‘label_names’: [‘nobody’],看来没有人。再来看个有人的:

import hy
runpaddleclas = """
(import paddleclas)
(setv model (paddleclas.PaddleClas :model_name "person_exists"))
(setv result (model.predict :input_data "work/pulc_demo_imgs/person_exists/objects365_02035329.jpg"))
;(setv result (.predict model :input_data "work/pulc_demo_imgs/person_exists/objects365_01780782.jpg"))  
 
(next result)
"""
result = hy.eval(hy.read_many(runpaddleclas))
print(result)
[2023/12/14 11:32:28] ppcls WARNING: The current running environment does not support the use of GPU. CPU has been used instead.
[{'class_ids': [1], 'scores': [0.9999976], 'label_names': ['someone'], 'filename': 'work/pulc_demo_imgs/person_exists/objects365_02035329.jpg'}]

‘label_names’: [‘someone’],可见判断出里面有人了。

在python中使用hy.eval执行的代码,输出可以赋值到一个python变量中,方便以后在python里面继续处理。比如上面就将输出赋值给变量result。可以看到result是一个list表。

print(type(result), result)
<class 'list'> [{'class_ids': [1], 'scores': [0.9999976], 'label_names': ['someone'], 'filename': 'work/pulc_demo_imgs/person_exists/objects365_02035329.jpg'}]

‘filename’: ‘work/pulc_demo_imgs/person_exists/objects365_02035329.jpg’}]

Lisp确实非常有趣,强烈推荐大家尝试一下!

本项目仅仅完成了将飞桨Python代码转换为HY Lisp代码的工作,尚未涉及Lisp的一些强大功能,例如宏和编写“能够自我编写代码”的代码。如果有对此感兴趣的朋友,非常欢迎大家一起深入挖掘Lisp的潜力,我们可以共同交流学习,并不断提升自己的技能水平!

四、调试记录

遇到了报错:hy Lisp 报错:struct.error

是train数据集解包报错,后来用调用python代码的方法解决,也就是不用上面那句,而是用下面那句:

;(setv train-dataset (paddle.vision.datasets.MNIST :mode 'test :transform (ToTensor))) 
(pys "train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=ToTensor())")

PaddleClas安装问题

不管是pip安装还是编译安装,都会失败。
解决方案是去掉requirements.txt文件中faiss-cpu,这样就能成功编译了。最后再手工pip install faiss-cpu即可。

结束语

让我们荡起双桨,在AI的海洋乘风破浪!

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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

NUS CS1101S:SICP JavaScript 描述:一、使用函数构建抽象

原文&#xff1a;1 Building Abstractions with Functions 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 心灵的行为&#xff0c;其中它对简单的想法施加其力量&#xff0c;主要有以下三种&#xff1a;1.将几个简单的想法组合成一个复合的想法&#xff0c;从而形成所…

阿里状态机引擎实现

状态机的技术选型看这篇就够了&#xff0c;最后一个直叫好&#xff01; - 掘金 实现一个状态机引擎&#xff0c;教你看清DSL的本质_cola状态机-CSDN博客 一、引入jar包 <!--阿里状态机jar--> <dependency><groupId>com.alibaba.cola</groupId><a…

Python | 三、函数

函数的形参和实参&#xff08;对应卡码网11题句子缩写&#xff09; 除非实参是可变对象&#xff0c;如列表、字典和集合&#xff0c;则此时形参会复制实参的地址&#xff0c;即此时二者指向同一个地址&#xff0c;因此在函数内对形参的操作会影响到实参除这种情况外&#xff0…

Spring自带分布式锁你用过吗?

环境&#xff1a;SpringBoot2.7.12 本篇文章将会为大家介绍有关spring integration提供的分布式锁功能。 1. 简介 Spring Integration 是一个框架&#xff0c;用于构建事件驱动的应用程序。在 Spring Integration 中&#xff0c;LockRegistry 是一个接口&#xff0c;用于管理…

推荐两款好用的卫星地图。

问题描述&#xff1a;推荐两款好用的卫星地图。 问题解决&#xff1a;谷歌地球、高德卫星地图。个人感觉谷歌地球好用一些。

ST工具Flash Loader烧写STM32

简介 使用ST公司自家的Flash Loader烧写程序&#xff0c; 如下图, F103直接接USART1到PC端就好, 使用普通的USB转TTL线&#xff0c; 就是你之前使用串口打印的方式连接到电脑就好。 软件下载 ST Flash Loader 我放到CSDN里面了Flash_Loader_demo_v2.8.0 开发板设置 Boot0-&g…

序章 熟悉战场篇—了解vue的基本操作

了解vue 的基本目录&#xff1a; dist 是打包后存放的目录(后续可以改)node_modules 是依赖包public 是静态index页面src 是存放文件的目录assets 是存放静态资源的目录components 是存放组件的目录views 是存放页面文件的目录&#xff08;没有views 自己新建一个&#xff09;A…

动态规划篇-03:打家劫舍

198、打家劫舍 状态转移方程 base case 边界问题就是&#xff1a;走到最后一间房子门口也没抢&#xff0c;那么最终抢到的金额为0 明确状态 “原问题和子问题中会变化的变量” 抢到的金额数就是状态&#xff0c;因为随着在每一件房子门口做选择&#xff0c;抢到的金额数会随…

Unity中的异步编程【7】——在一个异步方法里播放了animation动画,取消任务时,如何停止动画播放

用一个异步方法来播放一个动画&#xff0c;正常情况是&#xff1a;动画播放结束时&#xff0c;异步方法宣告结束。那如果我提前取消这个异步任务&#xff0c;那在这个异步方法里面&#xff0c;我要怎么停止播放呢&#xff1f;&#xff01; 一、播放animation动画的异步实现 1…

RIP【新华三与华为区别】

【介绍】 rip分为rip 1 与 rip 2 &#xff0c;rip 2 是对 rip 1 的一种升级&#xff0c;rip 2 可以进行认证等功能 【命令】 新华三&#xff1a; [HC3-R1] rip #启用rip [HC3-R1-rip] version 2 #告知rip 版本号 [HC3-R1-rip] network 192.168.1.0 #宣告其网段 [HC3-R1-rip] …

【AIGC】电影风格的一组绝美高清图提示词解析

实际示例 女人主角&#xff0c;以时尚电影风格为灵感&#xff0c;追求照片般的逼真度&#xff0c;运用伦勃朗式光线&#xff0c;创造奇幻且细节丰富的场景&#xff0c;充满象征意义&#xff0c;使用3D渲染技术达到8K超高清晰度。 分类相关信息主角女人风格时尚电影风格逼真度…

银行储蓄系统的顶层数据流图及细化数据流图

绘制出银行储蓄系统的顶层数据流图及细化数据流图&#xff1b; 银行储蓄系统存、取款流程如下&#xff1a; 1&#xff09;业务员事先录入利率信息&#xff1b; 2&#xff09;如果是存款&#xff0c;储户填写存款单&#xff0c;业务员将存款单键入系统&#xff0c;系统更新储户存…

力扣周赛第二题,下午更新后两道

本题中其实看着条件很多&#xff0c;但是仔细读一下会发现&#xff0c;前四个条件都是固定条件。然后我们再看题。 我们的暴力做法是遍历a数组的字符串a的下标起始下标&#xff0c;然后遍历b数组的字符串b的下标起始下标&#xff0c;进行判断&#xff0c;但是这样会超时&#x…

[软件工具]通用OCR识别文字识别中文识别服务程序可局域网访问

【软件界面】 【算法介绍】 采用业界最先进算法之一paddlocr&#xff0c;PaddleOCR&#xff0c;全称PaddlePaddle OCR&#xff0c;是一种基于深度学习的光学字符识别&#xff08;OCR&#xff09;技术。相较于传统的OCR技术&#xff0c;PaddleOCR具有许多优点。 首先&#xff0…

如何创建一个pytorch的训练数据加载器(train_loader)用于批量加载训练数据

Talk is cheap,show me the code! 哈哈&#xff0c;先上几段常用的代码&#xff0c;以语义分割的DRIVE数据集加载为例&#xff1a; DRIVE数据集的目录结构如下&#xff0c;下载链接DRIVE,如果官网下不了&#xff0c;到Kaggle官网可以下到&#xff1a; 1. 定义DriveDataset类&…

Kibana:使用反向地理编码绘制自定义区域地图

Elastic 地图&#xff08;Maps&#xff09;附带预定义区域&#xff0c;可让你通过指标快速可视化区域。 地图还提供了绘制你自己的区域地图的功能。 你可以使用任何您想要的区域数据&#xff0c;只要你的源数据包含相应区域的标识符即可。 但是&#xff0c;当源数据不包含区域…

Spring集成

目录 概述1 声朋一个简单的集成流1.1 使用XML定义集成流1.2 使用Java配置集成流1.3 使用Spring lntegration 的 DSL 配置 2 Spring integration 功能概览2.1 消息通道2.2 过滤器2.3 转换器2.4 路由器2.5 切分器2.6 服务激活器2.7 网关2.8 通道适配器2.9 端点模块 概述 就像我们…

RibbonGroup 添加QLineEdit

RibbonGroup添加QLineEdit&#xff1a; QLineEdit* controlEdit new QLineEdit(); controlEdit->setToolTip(tr("Edit")); controlEdit->setText(tr("Edit")); controlEdit->setMinimumWidth(150); …

vue知识-04

计算属性computed 注意&#xff1a; 1、计算属性是基于它们的依赖进行缓存的 2、计算属性只有在它的相关依赖发生改变时才会重新求值 3、计算属性就像Python中的property&#xff0c;可以把方法/函数伪装成属性 4、computed: { ... } 5、计算属性必须要有…

Windows python下载

1、下载 进入到地址&#xff1a;https://www.python.org/dowmloads 可以直接下载最新的版本 或者点击Windows&#xff0c;查看下方更多的版本 点击文档就下载下来啦 2、安装 双击下载的文件&#xff0c;勾选Add python.exe to PATH添加到环境变量中&#xff0c;选择Coutomi…