Pytorch实现多层lstm

P y t o r c h 实现多层 l s t m Pytorch实现多层lstm Pytorch实现多层lstm 推荐一下:深度学习AI-计算机视觉(CV)-整体解决方案课件(Yolo+Flask+Vue+Waitress+Nginx) 视频教程:https://www.bilibili.com/video/BV19h4y1874T/?spm_id_from=333.999.0.0 # 10:输入数据维度大小 20 :隐状态的特征维度 2:层数,表示用来两层lstm lstm = nn.LSTM(10, 20, 2) # 5:序列长度 3:单个训练数据长度 10:单个序列维度 举个例子:每次运行时取3个含有5个字的句子(且句子中每个字的维度为10) input = Variable(torch.randn(5, 3, 10)) # 2个LSTM层,batch_size=3, 隐藏层的特征维度20 h0 = Variable(torch.randn(2, 3, 20)) # 2个LSTM层,batch_size=3, 隐藏层的特征维度20 # 这里有2层lstm,output是最后一层lstm的每个词向量对应隐藏层的输出,其与层数无关,只与序列长度相关 c0 = Variable(torch.randn(2, 3, 20)) # output, hn = lstm(input, (h0, c0)) class RNN(nn.Module): def __init__(self, input_size, hidden_size, num_layers, num_classes): super(RNN, self).

python编写小游戏详细教程,用python做简单的小游戏

本篇文章给大家谈谈如何用python编写一个简单的小游戏,以及如何用Python做小游戏让别人玩,希望对各位有所帮助,不要忘了收藏本站喔。 本篇文章给大家谈谈如何用python编写一个简单的小游戏,以及如何用Python做小游戏让别人玩,希望对各位有所帮助,不要忘了收藏本站喔。 1、小恐龙 玩法:上下控制起跳躲避 import cfg import sys import random import pygame from modules import * '''main''' def main(highest_score): # 游戏初始化 pygame.init() screen = pygame.display.set_mode(cfg.SCREENSIZE) pygame.display.set_caption('九歌') # 导入所有声音文件 sounds = {} for key, value in cfg.AUDIO_PATHS.items(): sounds[key] = pygame.mixer.Sound(value) # 游戏开始界面 GameStartInterface(screen, sounds, cfg) # 定义一些游戏中必要的元素和变量 score = 0 score_board = Scoreboard(cfg.IMAGE_PATHS['numbers'], position=(534, 15), bg_color=cfg.BACKGROUND_COLOR) highest_score = highest_score highest_score_board = Scoreboard(cfg.IMAGE_PATHS['numbers'], position=(435, 15), bg_color=cfg.BACKGROUND_COLOR, is_highest=True) dino = Dinosaur(cfg.IMAGE_PATHS['dino']) ground = Ground(cfg.

unity使用UniStorm 5.1.0.unitypackage增加天气

添加天天气组件unistorm 然后添加一个player 导入包会报错,需要修改代码 using UnityEngine; using UnityEngine.PostProcessing; namespace UnityEditor.PostProcessing { [CustomPropertyDrawer(typeof(UnityEngine.PostProcessing.MinAttribute))] sealed class MinDrawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { UnityEngine.PostProcessing.MinAttribute attribute = (UnityEngine.PostProcessing.MinAttribute)base.attribute; if (property.propertyType == SerializedPropertyType.Integer) { int v = EditorGUI.IntField(position, label, property.intValue); property.intValue = (int)Mathf.Max(v, attribute.min); } else if (property.propertyType == SerializedPropertyType.Float) { float v = EditorGUI.FloatField(position, label, property.floatValue); property.floatValue = Mathf.Max(v, attribute.min); } else { EditorGUI.LabelField(position, label.text, "Use Min with float or int.

串联滞后校正的MATLAB实现

本题例题的为: 直接进行MATLAB实现: % 用MATLAB实现串联滞后校正 % 系统的型别 v=1; % 题目给的指标为 % 静态速度误差Kv_star = 30,那么计算增益 K = 30; % 其余的指标: r_star = 40; wc_star = 2.3; % 绘制出原有的系统传函 num_0 = 30; den_0 = conv([1,0],[conv([1/5,1],[1/10,1])]); sys_0 = tf(num_0,den_0); [Gm0,Pm0,Wcg0,Wcp0] = margin(sys_0); figure margin(sys_0);hold on % 得到其矫正完增益的截止频率Wcp0 = 9.7714 满足截止频率指标,但是相位裕度Pm不满足,所以采用滞后校正 % 绘制相位裕度Pm和w的关系图, syms w w = (0.01:0.01:100); Pm = 180+(-90)^v-atand(w/5)-atand(w/10); % figure % plot(Pm); Pm_star = r_star + 6; % 找出相位裕度指标+6dec的对应w wc = spline(Pm,w,Pm_star); % 得到wc新系统的截止频率最大为2.

linux 虚拟机扩容--直接扩容到根目录

pvcreate 创建pv -> vgcreate 创建卷组 -> lvcreate 创建逻辑卷 首先得了解几个概念: PV:PV(Physical Volume)- 物理卷 ,物理卷在逻辑卷管理中处于最底层,它可以是实际物理硬盘上的分区**,也可以是整个物理硬盘,也可以是raid设备。 **VG:**VG(Volumne Group)- 卷组 ,卷组建立在物理卷之上,一个卷组中至少要包括一个物理卷,在卷组建立之后可动态添加物理卷到卷组中。一个逻辑卷管理系统工程中可以只有一个卷组,也可以拥有多个卷组。 **LV:**LV(Logical Volume)- 逻辑卷 ,逻辑卷建立在卷组之上,卷组中的未分配空间可以用于建立新的逻辑卷,逻辑卷建立后可以动态地扩展和缩小空间。系统中的多个逻辑卷可以属于同一个卷组,也可以属于不同的多个卷组 fdisk -l ##查看新增的磁盘,需要使用root权限 fdisk /dev/name ##对磁盘进行分区 pvcreate /dev/vdb1 ##在分区上创建pv pvdisplay vgcreate vg名字 /dev/vdb1 ##在物理卷上创建vg卷组 lvcreate -l 逻辑卷空间大小 -n lv名字 vg名字 ##创建并划分lv空间 mkfs.ext4 /dev/lvm_data/ lv名字 ##格式化lv逻辑卷 /etc/fstab #挂载文件 1.在虚拟机关机的状态下操作,我这又给了20G 2.开启虚拟机查看 fdisk -l 可以看到 8e linux lvm的 这个是新加的 3.将刚才分区的磁盘改能lvm类型,并保存分区 fdisk /dev/sda2 4.重启系统或partprobe使新分区表生效 5.查看可以用作物理卷的设备 lvmdiskscan 6.创建物理卷并查看物理卷 pvcreate /dev/sdb pvdisplay 查看 7.将新创建的物理卷加载到VG,vgextend 并查看VG可用空间 vgextend centos /dev/sdb 注意:如果不是centos df -h 看一下根目录是什么 替换掉就行

C/C++:absl:status

absl/status目录下包含两个Status库 absl::Statusabsl::StatusOr< T> absl::Status 在 Google 内部,absl::Status 是跨 API 边界(尤其是跨 RPC 边界)优雅地处理错误的主要机制。其中一些错误可能可以恢复,但其他错误则可能无法恢复。大多数可能产生可恢复错误的函数应设计为返回一个absl::Status 或类似的absl::StatusOr< T>,它保存类型T 的对象或错误。 absl::Status MyFunction(absl::string_view filename, ...) { ... // encounter error if (error condition) { return absl::InvalidArgumentError("bad mode"); } // else, return OK return absl::OkStatus(); } 必须被处理的返回值可以标记为ABSL_MUST_USE_RESULT absl::Status Open(absl::string_view filename, absl::string_view mode, ...) { if (...) return absl::OkStatus(); // Signal success if (...) return absl::InvalidArgumentError("bad mode"); absl::Status result; // Default constructor creates an OK value as well.

ToBeWritten之车联网安全中常见的TOP 10漏洞

也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 转移发布平台通知:将不再在CSDN博客发布新文章,敬请移步知识星球 感谢大家一直以来对我CSDN博客的关注和支持,但是我决定不再在这里发布新文章了。为了给大家提供更好的服务和更深入的交流,我开设了一个知识星球,内部将会提供更深入、更实用的技术文章,这些文章将更有价值,并且能够帮助你更好地解决实际问题。期待你加入我的知识星球,让我们一起成长和进步 汽车威胁狩猎专栏长期更新,本篇最新内容请前往: [车联网安全自学篇] 汽车威胁狩猎之关于威胁狩猎该如何入门?你必须知道的那些事「7万字详解」 本文内容请忽略… … 0x01 威胁狩猎技巧 1:了解你的环境中什么是正常情况,那么你将能够更容易地发现异常情况 太多的企业试图在不了解他们的环境的情况下,跳入威胁狩猎的深渊(这是一个追逐松鼠和兔子,而且收效甚微的方法)。 威胁狩猎最终是在一个环境中寻找未知因素的做法,因此,了解什么是 “正常业务” 与 “可疑”、甚至 “恶意” 相比是至关重要的 为了理解环境,请确保你能获得尽可能多的信息,包括网络图、以前的事件报告,以及能得到的任何其他文件,并确保你拥有网络和终端层面的日志,以支持你的狩猎 0x02 威胁狩猎技巧 2:当建立狩猎活动时,根据你的假设,从一般的情况开始,再到具体的情况。通过这样做,可以创建上下文,并了解你在环境中寻找的是什么 当建立狩猎活动时,根据你的假设,从一般的情况开始,再到具体的情况。通过这样做,可以创建上下文,并了解你在环境中寻找的是什么 当威胁猎手第一次在结构化的威胁狩猎中崭露头角时,他们中的许多人都在努力建立他们的第一个假设。许多人发现这个过程,具有挑战性的原因往往是他们试图有点过于具体了。与其直接跳到细节上,不如先尝试在你的假设中更多地体现出一般的情况。通过这样做,你将更好地塑造你的狩猎,并在此过程中增加额外的上下文信息 0x03 威胁狩猎技巧 3:有时,最好狩猎你了解和知道的事物然后进行可视化,而不是狩猎你专业知识之外的事物,并尝试进行可视化到你知道的事物上 有时,在你了解和知道的事情上狩猎,然后再进行可视化,与在你的专业知识之外的事情上狩猎,并试图可视化到你知道的事情上,效果更好。 新的猎手遇到的最常见的挑战之一是,很容易很快摆脱困境。并不是每个信息安全专业人员,都是所有领域的专家,在威胁狩猎方面也是如此 无论你,是刚开始,还是已经狩猎了一些时间,同样的建议是正确的:狩猎你理解的东西,然后通过可视化来挖掘这些数据。这可以确保你理解你正在查看的东西,并让你对数据进行理解,以及理解你是如何到达那里的 如果,试图在你不了解的数据上狩猎,你更有可能倾向于你了解的数据,并对其进行可视化,这可能或不可能真正导致有意义和有价值的狩猎 0x04 威胁狩猎技巧 4:并非所有假设都会成功,有时可能会失败。但是不要气馁,回去再测试一下 与威胁保护和威胁检测等事情不同,威胁狩猎远不是一件肯定的事情。事实上,威胁狩猎的本质意味着你正在寻找未知的事物。正因为如此,所以并不是你狩猎的每一个假设都会成功。事实上,大多数猎手都知道,虽然他们可能会花几个小时,去挖掘他们发现的兔子洞,但这个洞更有可能导致一个使用 PowerShell 的高级用户来节省一些时间,而不是一个想要加密你的域控制器的高级攻击者 不要让这些时刻,让你灰心丧气!记录你的发现,不要让它成为你的负担。记录你的发现,不要气馁,并继续狩猎。从长远来看,它将会得到回报 0x05 威胁狩猎技巧 5:了解你的工具集及其数据功能,与执行你的狩猎同样重要。如果你没有验证工具中是否存在预期的数据,则误报就会潜伏在每个角落 虽然,在 IT 领域几乎每个人都明白,每个工具和技术都是不同的,并且都有特定的局限性。但有时安全人员(尤其是威胁猎手),可能会认为这是理所当然的 关于 “了解你的技术”,最重要的概念之一是了解它的能力,以及它的局限性是什么。如果你在不了解的情况下贸然前进,很可能会产生误报的结果,给安全团队一种错误的安全感 在建立你的狩猎系统之前,必须测试和验证你的搜索查询,以确保它们返回你所期望的结果,这是至关重要的 参考链接: https://blog.csdn.net/Ananas_Orangey/article/details/129491146 你以为你有很多路可以选择,其实你只有一条路可以走

Nessus部署及简单使用

01 Nessus 简介 Nessus 是目前全世界最多人使用的系统漏洞扫描与分析软件。总共有超过75,000个机构使用 Nessus 作为扫描该机构电脑系统的软件。Nessus号称是世界上最流行的漏洞扫描程序,通常包括成千上万的最新的漏洞,各种各样的扫描选项,及易于使用的图形界面和有效的报告。 02 Nessus 下载 进入官网下载地址,根据自己的操作操作系统选择下载的版本。本文以windows系统为例。 官网下载地址:https://www.tenable.com/downloads/nessusnessus-8.15.9安装包下载地址:https://download.csdn.net/download/qq_23435961/88372251 Nessus 安装 下载好安装包Nessus-10.1.1-x64.msi后,windows系统直接双击安装即可。 安装完成后进行系统设置,打开访问网址 https://127.0.0.1:8834,初始化扫描器。 根据提示步骤,选择 Managed Scanner 再选择 Tenable.sc 最后,点击继续,创建账号密码即可登录。 04 更新漏洞库 首先注册Nessus账号 注册地址:https://zh-cn.tenable.com/products/nessus/nessus-essentials 之后会收到一封邮箱邮件,复制邮件里的 Activation Code 值 再打开 Nessus 本地安装目录,执行cmd命令获取 Challenge Code 值 访问更新包链地址,填写 Challenge Code 和 Activation Code 获取 all-2.0.tar.gz 文件。 更新包地址:https://plugins.nessus.org/v2/offline.php 将下载好的 all-2.0.tar.gz 文件放到 Nessus 的安装目录下,然后执行如下更新命令: 注意:更新完漏洞库后,记住version版本号,如上述中的version版本号为 202003232053,之后破解时会用到这个。 05 Nessus 破解 (1)管理员身份打开cmd输入如下命令{停止Tenable Nessus服务} net stop "Tenable Nessus" (2)输入以下两个命令(更改文件属性) attrib -s -r -h "C:\ProgramData\Tenable\Nessus\nessus\plugins\*.*" attrib -s -r -h "

SQL SEVER2008附加数据库拒绝访问提示5120错误的处理方法

报错信息: 刚开始我以为自己服务没开,于是就取开服务,半天可是我服务是开的,最后是这样解决的, 右键需要附加的数据库文件,弹出属性对话框,选择安全标签页。 找到Authenticated Users用户名。 如未找到,进行Authenticated Users用户名的添加。 添加Authenticated Users用户名。 1.点击安全标签页的编辑按钮,而后点击添加显示选择用户或组对话框。 2.点击高级按钮而后点击该界面的立即查找,在搜索结果中显示了所有的用户和组。 3.选择Authenticated Users用户后点击确定,在 选择用户或组对话框 中便显示了Authenticated Users用户名。 4.点击确定 在安全标签页的用户组里面便显示了Authenticated Users用户。为Authenticated Users用户分配 完全控制 权限。

Ubuntu搭建dhcpv6服务器(Kea DHCP Server V2.3.7)

1 PD相关 1.1 修改PD的valid-lifetime 修改valid-lifetime时,必须确保renew-timer比valid-lifetime小,否则LAN侧RA在valid-lifetime到期之后就不再下发。 "renew-timer": 100, "rebind-timer": 200, "preferred-lifetime": 300, "valid-lifetime": 400,

mmap底层驱动实现(remap_pfn_range函数)

mmap底层驱动实现 myfb.c(申请了128K空间) #include <linux/init.h> #include <linux/tty.h> #include <linux/device.h> #include <linux/export.h> #include <linux/types.h> #include <linux/module.h> #include <linux/export.h> #include <linux/mm_types.h> #include <linux/mm.h> #include <linux/slab.h> #define BUFF_SIZE (32 * 4 * 1024) static char *buff; static int major; static struct class * myfb_class; static int myfb_mmap (struct file *fp, struct vm_area_struct *vm) { int res; //表示该vma在虚拟地址空间中的偏移地址,单位是页(4K) //unsigned long offset = vm->vm_pgoff << PAGE_SHIFT; //计算被映射的物理内存的物理页帧号(物理地址+偏移),以页为单位, virt_to_phys将虚拟地址转成物理地址 //vm->pgoff表示的是用户空间映射时在VMA中的偏移(即mmap最后一个参数,单位是字节,但vm->pgoff自动转成页单位) unsigned long pfn_start = (virt_to_phys(buff) >> PAGE_SHIFT); res = remap_pfn_range(vm, vm->vm_start, pfn_start + vm->vm_pgoff, //在物理页帧号上加上偏移 vm->vm_end - vm->vm_start, vm->vm_page_prot); if(res){ printk("

ToBeWritten之让响应团队参与并做好沟通

也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 转移发布平台通知:将不再在CSDN博客发布新文章,敬请移步知识星球 感谢大家一直以来对我CSDN博客的关注和支持,但是我决定不再在这里发布新文章了。为了给大家提供更好的服务和更深入的交流,我开设了一个知识星球,内部将会提供更深入、更实用的技术文章,这些文章将更有价值,并且能够帮助你更好地解决实际问题。期待你加入我的知识星球,让我们一起成长和进步 汽车威胁狩猎专栏长期更新,本篇最新内容请前往: [车联网安全自学篇] 汽车威胁狩猎之关于威胁狩猎该如何入门?你必须知道的那些事「7万字详解」 本文内容请忽略… … 0x01 威胁狩猎技巧 1:了解你的环境中什么是正常情况,那么你将能够更容易地发现异常情况 太多的企业试图在不了解他们的环境的情况下,跳入威胁狩猎的深渊(这是一个追逐松鼠和兔子,而且收效甚微的方法)。 威胁狩猎最终是在一个环境中寻找未知因素的做法,因此,了解什么是 “正常业务” 与 “可疑”、甚至 “恶意” 相比是至关重要的 为了理解环境,请确保你能获得尽可能多的信息,包括网络图、以前的事件报告,以及能得到的任何其他文件,并确保你拥有网络和终端层面的日志,以支持你的狩猎 0x02 威胁狩猎技巧 2:当建立狩猎活动时,根据你的假设,从一般的情况开始,再到具体的情况。通过这样做,可以创建上下文,并了解你在环境中寻找的是什么 当建立狩猎活动时,根据你的假设,从一般的情况开始,再到具体的情况。通过这样做,可以创建上下文,并了解你在环境中寻找的是什么 当威胁猎手第一次在结构化的威胁狩猎中崭露头角时,他们中的许多人都在努力建立他们的第一个假设。许多人发现这个过程,具有挑战性的原因往往是他们试图有点过于具体了。与其直接跳到细节上,不如先尝试在你的假设中更多地体现出一般的情况。通过这样做,你将更好地塑造你的狩猎,并在此过程中增加额外的上下文信息 0x03 威胁狩猎技巧 3:有时,最好狩猎你了解和知道的事物然后进行可视化,而不是狩猎你专业知识之外的事物,并尝试进行可视化到你知道的事物上 有时,在你了解和知道的事情上狩猎,然后再进行可视化,与在你的专业知识之外的事情上狩猎,并试图可视化到你知道的事情上,效果更好。 新的猎手遇到的最常见的挑战之一是,很容易很快摆脱困境。并不是每个信息安全专业人员,都是所有领域的专家,在威胁狩猎方面也是如此 无论你,是刚开始,还是已经狩猎了一些时间,同样的建议是正确的:狩猎你理解的东西,然后通过可视化来挖掘这些数据。这可以确保你理解你正在查看的东西,并让你对数据进行理解,以及理解你是如何到达那里的 如果,试图在你不了解的数据上狩猎,你更有可能倾向于你了解的数据,并对其进行可视化,这可能或不可能真正导致有意义和有价值的狩猎 0x04 威胁狩猎技巧 4:并非所有假设都会成功,有时可能会失败。但是不要气馁,回去再测试一下 与威胁保护和威胁检测等事情不同,威胁狩猎远不是一件肯定的事情。事实上,威胁狩猎的本质意味着你正在寻找未知的事物。正因为如此,所以并不是你狩猎的每一个假设都会成功。事实上,大多数猎手都知道,虽然他们可能会花几个小时,去挖掘他们发现的兔子洞,但这个洞更有可能导致一个使用 PowerShell 的高级用户来节省一些时间,而不是一个想要加密你的域控制器的高级攻击者 不要让这些时刻,让你灰心丧气!记录你的发现,不要让它成为你的负担。记录你的发现,不要气馁,并继续狩猎。从长远来看,它将会得到回报 0x05 威胁狩猎技巧 5:了解你的工具集及其数据功能,与执行你的狩猎同样重要。如果你没有验证工具中是否存在预期的数据,则误报就会潜伏在每个角落 虽然,在 IT 领域几乎每个人都明白,每个工具和技术都是不同的,并且都有特定的局限性。但有时安全人员(尤其是威胁猎手),可能会认为这是理所当然的 关于 “了解你的技术”,最重要的概念之一是了解它的能力,以及它的局限性是什么。如果你在不了解的情况下贸然前进,很可能会产生误报的结果,给安全团队一种错误的安全感 在建立你的狩猎系统之前,必须测试和验证你的搜索查询,以确保它们返回你所期望的结果,这是至关重要的 参考链接: https://blog.csdn.net/Ananas_Orangey/article/details/129491146 你以为你有很多路可以选择,其实你只有一条路可以走

Unity微信小游戏常用API总结

获取用户信息 游戏初始化,想要获取玩家的信息还需要在mp中进行隐私设置。 WX.InitSDK((code) => { // 打印屏幕信息 var systemInfo = WX.GetSystemInfoSync(); Debug.Log($"{systemInfo.screenWidth}:{systemInfo.screenHeight}, {systemInfo.windowWidth}:{systemInfo.windowHeight}, {systemInfo.pixelRatio}"); // 创建用户信息获取按钮,在底部区域创建一个300高度的透明区域 // 首次获取会弹出用户授权窗口, 可通过右上角-设置-权限管理用户的授权记录 var canvasWith = (int)(systemInfo.screenWidth * systemInfo.pixelRatio); var canvasHeight = (int)(systemInfo.screenHeight * systemInfo.pixelRatio); var buttonHeight = (int)(canvasWith / 1080f * 300f); infoButton = WX.CreateUserInfoButton(0, canvasHeight - buttonHeight, canvasWith, buttonHeight, "zh_CN", false); infoButton.OnTap((userInfoButonRet) => { Debug.Log(JsonUtility.ToJson(userInfoButonRet.userInfo)); txtUserInfo.text = $"nickName:{userInfoButonRet.userInfo.nickName}, avartar:{userInfoButonRet.userInfo.avatarUrl}"; //userInfoButonRet.userInfo.nickName 获取用户昵称 //userInfoButonRet.userInfo.avatarUrl 获取用户图片 }); Debug.Log("infoButton Created"); }); 游戏分享 public void OnShareClick() { WX.

ToBeWritten之利用MaGMA进行威胁狩猎

也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 转移发布平台通知:将不再在CSDN博客发布新文章,敬请移步知识星球 感谢大家一直以来对我CSDN博客的关注和支持,但是我决定不再在这里发布新文章了。为了给大家提供更好的服务和更深入的交流,我开设了一个知识星球,内部将会提供更深入、更实用的技术文章,这些文章将更有价值,并且能够帮助你更好地解决实际问题。期待你加入我的知识星球,让我们一起成长和进步 汽车威胁狩猎专栏长期更新,本篇最新内容请前往: [车联网安全自学篇] 汽车威胁狩猎之关于威胁狩猎该如何入门?你必须知道的那些事「7万字详解」 本文内容请忽略… … 0x01 威胁狩猎技巧 1:了解你的环境中什么是正常情况,那么你将能够更容易地发现异常情况 太多的企业试图在不了解他们的环境的情况下,跳入威胁狩猎的深渊(这是一个追逐松鼠和兔子,而且收效甚微的方法)。 威胁狩猎最终是在一个环境中寻找未知因素的做法,因此,了解什么是 “正常业务” 与 “可疑”、甚至 “恶意” 相比是至关重要的 为了理解环境,请确保你能获得尽可能多的信息,包括网络图、以前的事件报告,以及能得到的任何其他文件,并确保你拥有网络和终端层面的日志,以支持你的狩猎 0x02 威胁狩猎技巧 2:当建立狩猎活动时,根据你的假设,从一般的情况开始,再到具体的情况。通过这样做,可以创建上下文,并了解你在环境中寻找的是什么 当建立狩猎活动时,根据你的假设,从一般的情况开始,再到具体的情况。通过这样做,可以创建上下文,并了解你在环境中寻找的是什么 当威胁猎手第一次在结构化的威胁狩猎中崭露头角时,他们中的许多人都在努力建立他们的第一个假设。许多人发现这个过程,具有挑战性的原因往往是他们试图有点过于具体了。与其直接跳到细节上,不如先尝试在你的假设中更多地体现出一般的情况。通过这样做,你将更好地塑造你的狩猎,并在此过程中增加额外的上下文信息 0x03 威胁狩猎技巧 3:有时,最好狩猎你了解和知道的事物然后进行可视化,而不是狩猎你专业知识之外的事物,并尝试进行可视化到你知道的事物上 有时,在你了解和知道的事情上狩猎,然后再进行可视化,与在你的专业知识之外的事情上狩猎,并试图可视化到你知道的事情上,效果更好。 新的猎手遇到的最常见的挑战之一是,很容易很快摆脱困境。并不是每个信息安全专业人员,都是所有领域的专家,在威胁狩猎方面也是如此 无论你,是刚开始,还是已经狩猎了一些时间,同样的建议是正确的:狩猎你理解的东西,然后通过可视化来挖掘这些数据。这可以确保你理解你正在查看的东西,并让你对数据进行理解,以及理解你是如何到达那里的 如果,试图在你不了解的数据上狩猎,你更有可能倾向于你了解的数据,并对其进行可视化,这可能或不可能真正导致有意义和有价值的狩猎 0x04 威胁狩猎技巧 4:并非所有假设都会成功,有时可能会失败。但是不要气馁,回去再测试一下 与威胁保护和威胁检测等事情不同,威胁狩猎远不是一件肯定的事情。事实上,威胁狩猎的本质意味着你正在寻找未知的事物。正因为如此,所以并不是你狩猎的每一个假设都会成功。事实上,大多数猎手都知道,虽然他们可能会花几个小时,去挖掘他们发现的兔子洞,但这个洞更有可能导致一个使用 PowerShell 的高级用户来节省一些时间,而不是一个想要加密你的域控制器的高级攻击者 不要让这些时刻,让你灰心丧气!记录你的发现,不要让它成为你的负担。记录你的发现,不要气馁,并继续狩猎。从长远来看,它将会得到回报 0x05 威胁狩猎技巧 5:了解你的工具集及其数据功能,与执行你的狩猎同样重要。如果你没有验证工具中是否存在预期的数据,则误报就会潜伏在每个角落 虽然,在 IT 领域几乎每个人都明白,每个工具和技术都是不同的,并且都有特定的局限性。但有时安全人员(尤其是威胁猎手),可能会认为这是理所当然的 关于 “了解你的技术”,最重要的概念之一是了解它的能力,以及它的局限性是什么。如果你在不了解的情况下贸然前进,很可能会产生误报的结果,给安全团队一种错误的安全感 在建立你的狩猎系统之前,必须测试和验证你的搜索查询,以确保它们返回你所期望的结果,这是至关重要的 参考链接: https://blog.csdn.net/Ananas_Orangey/article/details/129491146 你以为你有很多路可以选择,其实你只有一条路可以走

ToBeWritten之定义跟踪指标

也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 转移发布平台通知:将不再在CSDN博客发布新文章,敬请移步知识星球 感谢大家一直以来对我CSDN博客的关注和支持,但是我决定不再在这里发布新文章了。为了给大家提供更好的服务和更深入的交流,我开设了一个知识星球,内部将会提供更深入、更实用的技术文章,这些文章将更有价值,并且能够帮助你更好地解决实际问题。期待你加入我的知识星球,让我们一起成长和进步 汽车威胁狩猎专栏长期更新,本篇最新内容请前往: [车联网安全自学篇] 汽车威胁狩猎之关于威胁狩猎该如何入门?你必须知道的那些事「7万字详解」 本文内容请忽略… … 0x01 威胁狩猎技巧 1:了解你的环境中什么是正常情况,那么你将能够更容易地发现异常情况 太多的企业试图在不了解他们的环境的情况下,跳入威胁狩猎的深渊(这是一个追逐松鼠和兔子,而且收效甚微的方法)。 威胁狩猎最终是在一个环境中寻找未知因素的做法,因此,了解什么是 “正常业务” 与 “可疑”、甚至 “恶意” 相比是至关重要的 为了理解环境,请确保你能获得尽可能多的信息,包括网络图、以前的事件报告,以及能得到的任何其他文件,并确保你拥有网络和终端层面的日志,以支持你的狩猎 0x02 威胁狩猎技巧 2:当建立狩猎活动时,根据你的假设,从一般的情况开始,再到具体的情况。通过这样做,可以创建上下文,并了解你在环境中寻找的是什么 当建立狩猎活动时,根据你的假设,从一般的情况开始,再到具体的情况。通过这样做,可以创建上下文,并了解你在环境中寻找的是什么 当威胁猎手第一次在结构化的威胁狩猎中崭露头角时,他们中的许多人都在努力建立他们的第一个假设。许多人发现这个过程,具有挑战性的原因往往是他们试图有点过于具体了。与其直接跳到细节上,不如先尝试在你的假设中更多地体现出一般的情况。通过这样做,你将更好地塑造你的狩猎,并在此过程中增加额外的上下文信息 0x03 威胁狩猎技巧 3:有时,最好狩猎你了解和知道的事物然后进行可视化,而不是狩猎你专业知识之外的事物,并尝试进行可视化到你知道的事物上 有时,在你了解和知道的事情上狩猎,然后再进行可视化,与在你的专业知识之外的事情上狩猎,并试图可视化到你知道的事情上,效果更好。 新的猎手遇到的最常见的挑战之一是,很容易很快摆脱困境。并不是每个信息安全专业人员,都是所有领域的专家,在威胁狩猎方面也是如此 无论你,是刚开始,还是已经狩猎了一些时间,同样的建议是正确的:狩猎你理解的东西,然后通过可视化来挖掘这些数据。这可以确保你理解你正在查看的东西,并让你对数据进行理解,以及理解你是如何到达那里的 如果,试图在你不了解的数据上狩猎,你更有可能倾向于你了解的数据,并对其进行可视化,这可能或不可能真正导致有意义和有价值的狩猎 0x04 威胁狩猎技巧 4:并非所有假设都会成功,有时可能会失败。但是不要气馁,回去再测试一下 与威胁保护和威胁检测等事情不同,威胁狩猎远不是一件肯定的事情。事实上,威胁狩猎的本质意味着你正在寻找未知的事物。正因为如此,所以并不是你狩猎的每一个假设都会成功。事实上,大多数猎手都知道,虽然他们可能会花几个小时,去挖掘他们发现的兔子洞,但这个洞更有可能导致一个使用 PowerShell 的高级用户来节省一些时间,而不是一个想要加密你的域控制器的高级攻击者 不要让这些时刻,让你灰心丧气!记录你的发现,不要让它成为你的负担。记录你的发现,不要气馁,并继续狩猎。从长远来看,它将会得到回报 0x05 威胁狩猎技巧 5:了解你的工具集及其数据功能,与执行你的狩猎同样重要。如果你没有验证工具中是否存在预期的数据,则误报就会潜伏在每个角落 虽然,在 IT 领域几乎每个人都明白,每个工具和技术都是不同的,并且都有特定的局限性。但有时安全人员(尤其是威胁猎手),可能会认为这是理所当然的 关于 “了解你的技术”,最重要的概念之一是了解它的能力,以及它的局限性是什么。如果你在不了解的情况下贸然前进,很可能会产生误报的结果,给安全团队一种错误的安全感 在建立你的狩猎系统之前,必须测试和验证你的搜索查询,以确保它们返回你所期望的结果,这是至关重要的 参考链接: https://blog.csdn.net/Ananas_Orangey/article/details/129491146 你以为你有很多路可以选择,其实你只有一条路可以走

ERROR 2002 (HY000): Can‘t connect to local MySQL server through socket ‘/tmp/mysql.sock‘ (2)

本文仅仅提供一个查错思路,跟目前网络上的诸多情况不一样!!! 这是一个很有意思的错误,一个星期前安装mysql没成功,所以前几重装了系统并且先安的mysql8.0后配置ubuntu里面的其他相关需要配件(如anaconda等。。。)在当时按照其他博主安装mysql8.0的时候,我也不知道为什么就是会出现先装自动mysql5.7的情况,鄙人才疏学浅也没有去深究 今天重新连mysql的时候使用 mysql -uroot -p密码 发现报错ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) 但是使用 mysql -uroot -h127.0.0.1 -p密码 却可以进去 找了一堆教程没有解决问题,期间修改配置文件,需要重启mysql服务的过程中使用 service mysqld status 会报错Unit mysqld.service could not be found(后来发现不影响,所以不管) 后来发现原因如下: 因为 我装了 Anaconda 所以打开终端默认进入的是虚拟环境(base) 在这样的情况下(激活了虚拟环境的情况) 使用: mysql --version 显示的是mysql5.7版本!!!! 但是取消激活环境 conda deactivate 再次使用 mysql --version 终于是mysql8.0版本 此时使用 mysql -uroot -p密码 就可以正常进入mysql了 然后我去将虚拟环境中那个莫名其妙的mysql5.7卸载之后,在虚拟环境里使用的mysql版本就默认是系统本地的mysql版本了,暴哭ing 然后解释一下为什么之前用-h127.0.0.1进入和使用sql-workbench都能进呢,因为他们连接到的是mysql8.0

【SLAM】IMU预积分的理解、手把手推导(4/4)

由于篇幅设置,IMU预积分分为4篇完成: 【SLAM】IMU预积分的理解、手把手推导(1/4):概要介绍【SLAM】IMU预积分的理解、手把手推导(2/4):噪声分离、分布形式、递推形式【SLAM】IMU预积分的理解、手把手推导(3/4):零偏更新后的速算【SLAM】IMU预积分的理解、手把手推导(4/4):残差的雅可比、总结 在优化过程中,残差计算和残差对状态量的雅可比矩阵是迭代的核心内容。本文对IMU预积分优化过程中,残差和对应的雅可比矩阵的计算进行推导。同时对整个IMU预积分过程进行总结。 IMU预积分推导 优化与残差 在实际应用中,通常以 R i \mathbf{R}_{i} Ri​、 p i \mathbf{p}_{i} pi​、 v i \mathbf{v}_{i} vi​、 R j \mathbf{R}_{j} Rj​、 p j \mathbf{p}_{j} pj​、 v j \mathbf{v}_{j} vj​ 等为导航求解的目标,同时由于IMU的零偏也是不可忽视的,因此,全部的导航状态是 R i \mathbf{R}_{i} Ri​、 p i \mathbf{p}_{i} pi​、 v i \mathbf{v}_{i} vi​、 R j \mathbf{R}_{j} Rj​、 p j \mathbf{p}_{j} pj​、 v j \mathbf{v}_{j} vj​、 δ b i g \delta \mathbf{b}_{i}^{g} δbig​、 δ b i a \delta \mathbf{b}_{i}^{a} δbia​ 。

【SLAM】IMU预积分的理解、手把手推导(3/4)

由于篇幅设置,IMU预积分分为4篇完成: 【SLAM】IMU预积分的理解、手把手推导(1/4):概要介绍【SLAM】IMU预积分的理解、手把手推导(2/4):噪声分离、分布形式、递推形式【SLAM】IMU预积分的理解、手把手推导(3/4):零偏更新后的速算【SLAM】IMU预积分的理解、手把手推导(4/4):残差的雅可比、总结 上一篇文章对IMU预积分噪声进行分离,并对其递推形式进行推导,最终引出了其信息矩阵的递推形式。而本文将会对零偏改变时IMU预积分的速算进行推导。这是IMU预积分节省计算量的关键。 IMU预积分推导 零偏更新时的PVQ增量测量值更新 前面的计算和推导,都是在假设积分区间内陀螺和加计的零偏恒定的基础上推导的。当零偏发生变化时,若仍按照前述公式,PVQ增量测量值需要整个重新计算一遍,这将非常的耗费算力。为了解决这个问题,提出了利用线性化来进行零偏变化时的一阶近似更新方法。 具体来说,我们把PVQ增量观测值看成 b i g \mathbf{b}_{i}^{g} big​、 b i a \mathbf{b}_{i}^{a} bia​ 的函数,那么,当 b i g \mathbf{b}_{i}^{g} big​、 b i a \mathbf{b}_{i}^{a} bia​ 更新了 δ b i g \delta\mathbf{b}_{i}^{g} δbig​、 δ b i a \delta\mathbf{b}_{i}^{a} δbia​ 之后,PVQ增量观测值应作如下的修正: Δ R ~ i j ( b i g + δ b i g ) ≈ Δ R ~ i j ( b i g ) E x p ( ∂ Δ R ~ i j ∂ b i g δ b i g ) Δ v ~ i j ( b i g + δ b i g , b i a + δ b i a ) ≈ Δ v ~ i j ( b i g , b i a ) + ∂ Δ v ~ i j ∂ b i g δ b i g + ∂ Δ v ~ i j ∂ b i a δ b i a Δ p ~ i j ( b i g + δ b i g , b i a + δ b i a ) ≈ Δ p ~ i j ( b i g , b i a ) + ∂ Δ p ~ i j ∂ b i g δ b i g + ∂ Δ p ~ i j ∂ b i a δ b i a \begin{aligned} &\Delta \tilde{\mathbf{R}}_{ij}\left( \mathbf{b}_{i}^{g} + \delta \mathbf{b}_{i}^{g} \right) \approx \Delta \tilde{\mathbf{R}}_{ij}(\mathbf{b}_{i}^{g}) \mathrm{Exp} \left(\frac{\partial \Delta \tilde{\mathbf{R}}_{ij}}{\partial \mathbf{b}_i^g} \delta \mathbf{b}_{i}^{g}\right) \\ & \Delta \tilde{\mathbf{v}}_{ij} (\mathbf{b}_{i}^{g} + \delta \mathbf{b}_{i}^{g}, \mathbf{b}_{i}^{a} + \delta \mathbf{b}_{i}^{a}) \approx \Delta \tilde{\mathbf{v}}_{ij}(\mathbf{b}_{i}^{g}, \mathbf{b}_{i}^{a}) + \frac{\partial \Delta \tilde{\mathbf{v}}_{ij}}{\partial \mathbf{b}_{i}^{g}} \delta \mathbf{b}_{i}^{g} + \frac{\partial \Delta \tilde{\mathbf{v}}_{ij}}{\partial \mathbf{b}_{i}^{a}} \delta \mathbf{b}_{i}^{a} \\ & \Delta \tilde{\mathbf{p}}_{ij} (\mathbf{b}_{i}^{g} + \delta \mathbf{b}_{i}^{g}, \mathbf{b}_{i}^{a} + \delta \mathbf{b}_{i}^{a}) \approx \Delta \tilde{\mathbf{p}}_{ij}(\mathbf{b}_{i}^{g}, \mathbf{b}_{i}^{a}) + \frac{\partial \Delta \tilde{\mathbf{p}}_{ij}}{\partial \mathbf{b}_{i}^{g}} \delta \mathbf{b}_{i}^{g} + \frac{\partial \Delta \tilde{\mathbf{p}}_{ij}}{\partial \mathbf{b}_{i}^{a}} \delta \mathbf{b}_{i}^{a} \end{aligned} ​ΔR~ij​(big​+δbig​)≈ΔR~ij​(big​)Exp(∂big​∂ΔR~ij​​δbig​)Δv~ij​(big​+δbig​,bia​+δbia​)≈Δv~ij​(big​,bia​)+∂big​∂Δv~ij​​δbig​+∂bia​∂Δv~ij​​δbia​Δp~​ij​(big​+δbig​,bia​+δbia​)≈Δp~​ij​(big​,bia​)+∂big​∂Δp~​ij​​δbig​+∂bia​∂Δp~​ij​​δbia​​

【SLAM】IMU预积分的理解、手把手推导(2/4)

由于篇幅设置,IMU预积分分为4篇完成: 【SLAM】IMU预积分的理解、手把手推导(1/4):概要介绍【SLAM】IMU预积分的理解、手把手推导(2/4):噪声分离、分布形式、递推形式【SLAM】IMU预积分的理解、手把手推导(3/4):零偏更新后的速算【SLAM】IMU预积分的理解、手把手推导(4/4):残差的雅可比、总结 本章开始将会开始对IMU预积分进行详细的推导。本次的推导采用李群李代数的形式来表示旋转,对应的是ORB-SLAM3的方案。比如VINS,采用的四元数方案,可能从推导过程上看有一些不同。 本文主要通过PVQ增量真值=PVQ增量测量值-PVQ增量噪声,将增量噪声进行分离操作,并探究其分布形式和递推形式。 IMU预积分推导 先说一下李群李代数的定义吧: R ˙ = ϕ ∧ R \dot{\mathbf{R}}=\phi^{\wedge}\mathbf{R} R˙=ϕ∧R R = Exp ⁡ ( ϕ ) = exp ⁡ ( ϕ ∧ ) \mathbf{R}=\operatorname{Exp}(\phi)=\operatorname{exp}(\phi^{\wedge }) R=Exp(ϕ)=exp(ϕ∧) 其中, R \mathbf{R} R为李群SO(3), ϕ \phi ϕ为对应的李代数so(3),两者之间相差一个指数对数的关系。如果是 Exp ⁡ \operatorname{Exp} Exp,括号里面是李代数向量,如果是 exp ⁡ \operatorname{exp} exp,括号里面是李代数向量对应的反对称矩阵。 有时候,会有用 ϕ ⃗ \vec{\phi} ϕ ​的表示,其实与 ϕ \phi ϕ的含义是一致的。 PVQ增量真值 假设 i i i帧的Q、V、P分别是 R i R_i Ri​、 v i v_i vi​、 p i p_i pi​,则可以利用从 k = i k=i k=i到 k = j − 1 k=j-1 k=j−1帧的所有IMU测量值,直接更新得到 j j j帧的 R j R_j Rj​、 v j v_j vj​、 p j p_j pj​,详细如下:

Vscode使用Git详解

前言 简介:本文将带你完成 git 安装、远程代码仓库创建、链接远程仓库、代码推送等 说明:本文演示所用远程仓库为 gitee(码云),你用 github或者其他的远程仓库也是可以的的 最后:欢迎评论区讨论,我尽力解答你们的疑惑 文章目录 前言一、安装 git1.1 打开 git 官网1.2 如图操作 二、node.js安装三、创建代码仓库3.1 来到首页3.2 新建3.3 仓库配置3.4 完成创建 四、链接远程仓库4.1 打开vscode4.2 点击代码管理4.3 复制地址4.4 链接仓库4.5 推送代码4.6 查看结果 五、日常代码推送和拉取5.1.编辑代码前,最好先拉取一下代码5.2 话不多说,先拉代码5.3 推送代码5.4 检查无误,推送代码5.5 查看推送情况 六、其他如果你有其他的问题,也可以评论区留言,包括但不限于,vscode主题设置,背景图片设置等..... 一、安装 git git官网地址:https://git-scm.com/ 1.1 打开 git 官网 1.2 如图操作 鼠标在桌面右键,出现这个 git bash here 就表示 git 已经安装成功 二、node.js安装 node.js请自行安装好,若没安装好,百度搜node.js安装,教程很多 三、创建代码仓库 注:我这里仅用 gitee 做演示,如果你更愿意使用其他代码仓库,如 github也是可以的。 3.1 来到首页 来到 gitee 首页,点击 右上角的加号 3.2 新建 选择新建仓库 3.3 仓库配置 来到新建仓库页面,自定义仓库名称并创建仓库 3.4 完成创建 如图所示,仓库就算创建成功了。(gitee 网页暂时放这儿不动,咱们接着往后看)

Excel操作

1、筛选后求和 109表示求和的意思 =SUBTOTAL(109,AQ2:AQ26)

qt 对数据库sqlite的操作(超详细)包含增删改查

目录 一、表格数据类型示例 在pro里面 QT += core gui sql 二、头文件包含 三、增删改查操作 3.1 查询 select 3.2 多表联合查询 join on 图片格式jpg,png 3.3 插入 insert 3.4 更新修改 update 3.5 删除 delete 一、表格数据类型示例 主要有三个表格,其中images存的是照片,关键字都是user,可以通过user来多表联合查询 建立的DataBase文件为c++类型,继承自QObject 在pro里面 QT += core gui sql 二、头文件包含 #include <QObject> #include <QMap> #include <QMessageBox> #include <QSettings> #include <QSqlError> #include <QSqlDatabase> #include <QSqlQuery> #include <QDebug> #include <QBuffer> 注意:在构造函数里面调用create_database(),必须先连接数据库才能对数据进行操作。 // 创建数据库,连接数据库 void Database::create_database() { QSqlDatabase db; // 避免重复连接数据库 if(QSqlDatabase::contains("qt_sql_default_connection")) { db = QSqlDatabase::database("

Camunda适配达梦数据库

Camunda适配达梦数据库 ​ 只需要指定数据库类型为oracle即可,具体application.yml配置如下: camunda: bpm: webapp: index-redirect-enabled: false admin-user: id: demo password: camunda history-level: full auto-deployment-enabled: true authorization: enabled: true database: type: oracle

大数据项目分享 - 深度学习 大数据 股票预测系统 - python lstm

文章目录 0 前言1 课题意义1.1 股票预测主流方法 2 什么是LSTM2.1 循环神经网络2.1 LSTM诞生 2 如何用LSTM做股票预测2.1 算法构建流程2.2 部分代码 3 实现效果3.1 数据3.2 预测结果项目运行展示开发环境数据获取 0 前言 🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是 🚩 深度学习 大数据 股票预测系统 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分工作量:3分创新点:4分 🧿 选题指导, 项目分享: https://gitee.com/yaa-dc/warehouse-1/blob/master/python/README.md 1 课题意义 利用神经网络模型如果能够提高对股票价格的预测精度,更好地掌握股票价格发展趋势,这对于投资者来说可以及时制定相应的发展策略,更好地应对未来发生的不确定性事件,对于个人来说可以降低投资风险,减少财产损失,实现高效投资,具有一定的实践价值。 1.1 股票预测主流方法 股票市场复杂、非线性的特点使我们难以捉摸其变化规律,目前有很多预测股票走势的论文和算法。 定量分析从精确的数据资料中获得股票发展的价值规律,通过建立模型利用数学语言对股市的发展情况做出解释与预测。 目前常用的定量分析方法有: 传统时间序列预测模型马尔可夫链预测灰色系统理论预测遗传算法机器学习预测等方法 2 什么是LSTM LSTM是长短期记忆网络(LSTM,Long Short-Term Memory),想要理解什么是LSTM,首先要了解什么是循环神经网络。 2.1 循环神经网络 对于传统的BP神经网络如深度前馈网络、卷积神经网络来说,同层及跨层之间的神经元是独立的,但实际应用中对于一些有上下联系的序列来说,如果能够学习到它们之间的相互关系,使网络能够对不同时刻的输入序列产生一定的联系,像生物的大脑一样有“记忆功能”,这样的话我们的模型也就会有更低的训练出错频率及更好的泛化能力。 JordanMI提出序列理论,描述了一种体现“并行分布式处理”的网络动态系统,适用于语音生成中的协同发音问题,并进行了相关仿真实验,ElmanJL认为连接主义模型中对时间如何表示是至关重要的,1990年他提出使用循环连接为网络提供动态内存,从相对简单的异或问题到探寻单词的语义特征,网络均学习到了有趣的内部表示,网络还将任务需求和内存需求结合在一起,由此形成了简单循环网络的基础框架。 循环神经网络(RNN)之间的神经元是相互连接的,不仅在层与层之间的神经元建立连接,而且每一层之间的神经元也建立了连接,隐藏层神经元的输入由当前输入和上一时刻隐藏层神经元的输出共同决定,每一时刻的隐藏层神经元记住了上一时刻隐藏层神经元的输出,相当于对网络增添了“记忆”功能。我们都知道在输入序列中不可避免会出现重复或相似的某些序列信息,我们希望RNN能够保留这些记忆信息便于再次调用,且RNN结构中不同时刻参数是共享的,这一优点便于网络在不同位置依旧能将该重复信息识别出来,这样一来模型的泛化能力自然有所上升。 RNN结构如下: 2.1 LSTM诞生 RNN在解决长序列问题时未能有良好的建模效果,存在长期依赖的弊端,对此HochreiterS等人对神经单元做出了改进,引入自循环使梯度信息得以长时间持续流动,即模型可以拥有长期记忆信息,且自循环权重可以根据前后信息进行调整并不是固定的。作为RNN的一种特殊结构,它可以根据前后输入情况决定历史信息的去留,增进的门控机制可以动态改变累积的时间尺度进而控制神经单元的信息流,这样神经网络便能够自己根据情况决定清除或保留旧的信息,不至于状态信息过长造成网络崩溃,这便是长短期记忆(LSTM)网络。随着信息不断流入,该模型每个神经元内部的遗忘门、输入门、输出门三个门控机制会对每一时刻的信息做出判断并及时进行调整更新,LSTM模型现已广泛应用于无约束手写识别、语音识别、机器翻译等领域。 2 如何用LSTM做股票预测 2.1 算法构建流程 2.2 部分代码 import numpy as np import matplotlib.pyplot as plt import tensorflow as tf import pandas as pd import math def LSTMtest(data): n1 = len(data[0]) - 1 #因为最后一位为label n2 = len(data) print(n1, n2) # 设置常量 input_size = n1 # 输入神经元个数 rnn_unit = 10 # LSTM单元(一层神经网络)中的中神经元的个数 lstm_layers = 7 # LSTM单元个数 output_size = 1 # 输出神经元个数(预测值) lr = 0.

SpringBoot 如何配置 SSL

Spring Boot SSL配置指南 在现代Web开发中,保护用户数据和通信的安全性至关重要。为了实现这一目标,许多网站都采用了SSL(安全套接层)协议来加密数据传输。Spring Boot使得为你的应用程序配置SSL变得非常容易,本文将详细介绍如何在Spring Boot应用程序中配置SSL。 什么是SSL? SSL(安全套接层)是一种用于加密通信的协议。它通过将数据加密传输来保护通信的机密性和完整性。SSL协议通常用于Web浏览器和Web服务器之间的安全通信,以确保用户的敏感数据(如密码、信用卡号等)在传输过程中不被窃取或篡改。 为什么需要配置SSL? 配置SSL对于Web应用程序至关重要,因为它确保了用户与应用程序之间的数据传输的安全性。如果您的应用程序处理用户的敏感信息,如登录凭据或支付信息,那么使用SSL来保护这些数据至关重要。此外,现代浏览器通常要求Web应用程序使用SSL以确保安全性。 Spring Boot SSL配置步骤 要在Spring Boot应用程序中配置SSL,您需要执行以下步骤: 步骤1:获取SSL证书 首先,您需要获取有效的SSL证书。您可以从受信任的证书颁发机构(如Let’s Encrypt、DigiCert等)购买SSL证书,也可以自行创建自签名证书。对于测试和开发目的,自签名证书通常足够。以下是如何创建自签名证书的示例: keytool -genkey -alias myapp -keyalg RSA -keystore keystore.jks -validity 3650 上述命令将生成一个名为keystore.jks的Java密钥存储文件,并为其创建一个自签名证书,有效期为3650天。 步骤2:将SSL证书添加到Spring Boot项目 将生成的SSL证书添加到Spring Boot项目中。您可以将证书文件(通常是.jks文件)放在项目的资源文件夹中。 步骤3:配置Spring Boot应用程序以使用SSL 要配置Spring Boot应用程序以使用SSL,您需要在application.properties或application.yml文件中添加以下属性: 使用application.properties配置文件: server.port=8443 server.ssl.key-store=classpath:keystore.jks server.ssl.key-store-password=your_password server.ssl.key-password=your_password server.ssl.keyAlias=myapp 使用application.yml配置文件: server: port: 8443 ssl: key-store: classpath:keystore.jks key-store-password: your_password key-password: your_password key-alias: myapp 请确保替换your_password为您的密钥存储文件密码。 步骤4:启动Spring Boot应用程序 现在,您可以启动Spring Boot应用程序并将其部署在HTTPS端口(默认为8443)上。应用程序将使用您配置的SSL证书来保护传输的数据。 测试SSL配置 为了确保SSL配置正常工作,您可以使用Web浏览器或工具(如Qualys SSL Labs)对您的应用程序进行测试。如果一切正常,您应该看到浏览器地址栏中的锁图标,表示连接是安全的。 自动续签SSL证书 通常,SSL证书具有一定的有效期。为了确保证书不会在过期后导致连接问题,您需要考虑自动续签证书。证书颁发机构通常提供自动续签选项,或者您可以设置定期检查证书并进行续签的脚本。 结论 在Spring Boot应用程序中配置SSL是确保用户数据和通信安全性的关键步骤。通过遵循上述步骤,您可以轻松地将SSL证书集成到您的应用程序中,保护用户的隐私和数据。

AI创业,大龄程序员被逼的上路

开始创业记录 多年前有个创业类电视节目叫《赢在中国》,当年(2008年)也是我第一次创业,经常看这个节目。节目的主题歌叫《在路上》,刘欢唱的。每次听到这首歌,就回想起当年创业的情景。 现在又一次在路上,AI创业快2个月了,今天开始记录一下每天的进展和思考,给大家一下思考启发。 网易云音乐《在路上》部分评论 今年我很惨 今年都说难,有个朋友在公司说他忍辱负重快抑郁了,但是还得忍着,没办法不敢辞职。不被裁就是幸事了。很多人今年的上班的感受,上班上的很憋屈! 这憋屈与我亏100多万(不止)来说算不了什么。卖房挂出去,看的少,出价的更少,价格只能一降再降。终于在9月底有买家下订单。不焦虑了,十一假期好好放松一下。认了,就想做生意,有赚有赔,没什么。 只要身体健康,可以重头再来!返租了买家,明年开始又过租房的生活。 从卖劳动力到卖产品,可能是正道 找远程工作,和在公司上班,我认为本质是没有变化的。都是给别人打工,打一天工,拿一天工资。不工作了就没有收入了。一份工作只能卖一次,也不能靠远程工作赚大钱了。 靠上班养家糊口是没问题的。最终要改变这种卖自己时间换工资的赚钱模式。 比如我开发一个收费软件,这个软件可以卖出去无数份,卖的越多赚的越多。我录制了一个课程,这个课程也可以卖出去无数份,卖的越多赚的越多。 往这个方向上转,慢慢转。 前期肯定很难的,尤其在职场干螺丝钉的人,只是负责流水线上一个环节的,很难转过来。 AI有机会吗 互联网、移动互联网、微信公众号、抖音、自媒体到现在的AI,在中国,创业的机会真的。但是程序员的眼里就是技术,如何提升自己的技术。 靠技术不能致富。至少我靠技术写代码,在IT行业干了十多年,没有让我变富。 刚才和一个朋友聊了AI的应用,身边的人,真正在每天用AI的非常少。AI应用大爆发还需要一些时间。 那么有没有AI的刚需的场景?比如雅思、考公务员等这类的热度一直很高,就是刚需。 目前经济下,都收紧了钱包,boss直聘服务器都扛不住的,访问量太大,都在刷工作。 AI目前是小众用户在用,那么1年,2年后能替代多少人的工作? 已经晚上11点半了,不要以牺牲身体健康为前提的工作。今天先发了,明天继续,看看能坚持写多久。(我2016年在创业时,春雨医生APP的创始人因突发心肌梗塞,不幸于2016年10月5日晚在北京去世,享年44岁)。

基于RK3588平台的机器学习模型部署

目录 硬件平台介绍rk3588 NPU及开发工具介绍rknn-toolkit2安装测试连板运行 总结 硬件平台介绍 这次体验的硬件平台是来自飞凌嵌入式的OK3588-C开发板,该开发板基于Rockchip新一代旗舰 RK3588处理器开发,采用核心板+底板的分体式设计,将FET3588-C核心板的全部功能引脚以最便利的方式引出,并针对不同的功能做了深度优化,方便用户二次开发的同时简化用户设计。 rk3588 NPU及开发工具介绍 rk3588专门针对机器学习模型部署的需求配置了性能强劲的NPU,rk3588配置的NPU不仅提供6TOPS的算力,还支持INT4/INT8/INT16/FP16格式的混合操作。除了非常不错的硬件支持之外,Rockchip公司还提供了便捷的开发工具rknn-toolkit2 和 rknpu2-api,让开发者可以方便的将自己的机器学习模型进行转换和部署。 rknn-toolkit2 根据rockchip提供的《Rockchip_User_Guide_RKNN_Toolkit2》开发文档介绍: RKNN-Toolkit2 是为用户提供在 PC、Rockchip NPU 平台上进行模型转换、推理和性能评估的 开发套件,用户通过该工具提供的 Python 接口可以便捷地完成以下功能: 模型转换: 支持 Caffe、TensorFlow、TensorFlow Lite、ONNX、DarkNet、PyTorch 等模型 转为 RKNN 模型,并支持 RKNN 模型导入导出,RKNN 模型能够在 Rockchip NPU 平台 上加载使用。量 化 功 能 : 支 持 将 浮 点 模 型 量 化 为 定 点 模 型 , 目 前 支 持 的 量 化 方 法 为 非 对 称 量 化

JVM笔记 —— 垃圾回收(GC)详解

一、垃圾回收的分类 针对HotSpot JVM的实现,它里面的GC其实准确分类只有两大种: Partial GC:部分收集模式 Young GC:只收集年轻代的GCOld GC:只收集老年代的GC。只有CMS中有这个模式。Mixed GC:收集整个年轻代以及部分老年代的GC。只有G1有这个模式 Full GC:收集整个堆和方法区。 堆是垃圾回收的主要区域,方法区很少会被回收。 本文所讨论的均指HotSpot JVM 二、死亡对象判断方法 堆中几乎放着所有的对象实例,对堆垃圾回收前的第一步就是要判断哪些对象已经死亡(即不能再被任何途径使用的对象)。 1. 引用计数法 给每个对象中添加一个引用计数器: 每当有一个地方引用它,计数器就加 1;每当引用失效,计数器就减 1;任何时候计数器为 0 的对象就是不可能再被使用的。 但是引用计数法很难解决对象之间循环引用的问题,因此目前主流的虚拟机中并没有选择这个算法。 2. 根可达性分析算法 这个算法的基本思想就是通过一系列的称为 “GC Roots” 的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连的话,则证明此对象是不可用的,需要被回收。 下图中的 Object 6 ~ Object 10 之间虽有引用关系,但它们到 GC Roots 不可达,因此为需要被回收的对象。 哪些对象可以作为 GC Roots 呢? 虚拟机栈(栈帧中的本地变量表)中引用的对象本地方法栈(Native 方法)中引用的对象类静态常量引用的对象常量池中被引用的对象所有被同步锁持有的对象 对象被回收前如果该对象重写了finaize()方法则需先执行此方法后才能被回收。Object 类中的 finalize 方法一直被认为是一个糟糕的设计,影响了 Java 语言的安全和 GC 的性能,JDK9 版本及后续版本中各个类中的 finalize 方法会被逐渐弃用移除。 参考:Java基础知识点之finalize方法详解 三、引用类型分类 无论是通过引用计数法判断对象引用数量,还是通过可达性分析法判断对象的引用链是否可达,判定对象的存活都与“引用”有关。 Java中将引用分为了强引用、软引用、弱引用、虚引用四种。非强引用通常用来指向某些只需要暂时缓存的数据。 1. 强引用 引用变量默认就是强引用,以下其它三种将引用通过特殊包装的才能形成其它引用。 强引用的对象在GC Roots可达时不会被回收。

【深入浅出C#】章节5:高级面向对象编程:委托和事件

委托和事件是高级面向对象编程中的重要概念,用于实现程序的灵活性、可扩展性和可维护性。它们在实现回调、事件处理和异步编程等方面发挥着关键作用。 委托允许我们将方法视为一种对象,可以将方法作为参数传递、存储在变量中,并在需要时进行调用。这种能力使得委托非常适合用于实现回调函数,将一个方法传递给另一个方法,使得后者在适当的时候调用前者。委托还支持委托链和多播委托的概念,可以将多个方法链接在一起形成一个委托链,依次执行它们。 事件是委托的一种特殊形式,用于实现观察者模式和事件驱动编程。事件提供了一种简洁和可靠的方式来处理和响应特定的程序事件,如用户交互、消息通知等。通过事件,我们可以定义事件的发布者和订阅者,发布者触发事件时,订阅者会收到通知并执行相应的操作。这种松耦合的设计模式使得程序更具可扩展性和可维护性。 委托和事件在异步编程中也起到重要的作用。它们可以帮助我们处理异步操作的回调和通知,提高程序的响应性和效率。通过将异步操作封装在委托或事件中,我们可以在异步操作完成后执行相应的处理逻辑,而不需要阻塞主线程或进行复杂的线程管理。 一、委托的概念和基本使用 1.1 委托的定义和特点 委托是C#中的一种引用类型,它允许我们将方法视为对象,并将方法作为参数传递、存储在变量中,并在需要时进行调用。 委托的定义包括两个主要部分:委托类型的声明和委托实例的创建。委托类型声明指定了方法的签名,包括参数类型和返回类型。委托实例则是根据委托类型创建的对象,可以引用一个或多个方法。委托的主要特点如下: 委托是类型安全的:委托类型定义了方法的签名,只有具有相同签名的方法才能被赋值给该委托类型的实例。委托是可组合的:多个方法可以通过委托链的方式组合在一起,形成一个委托链。委托链可以依次调用其中的每个方法。委托是可变的:委托实例可以动态地添加或移除方法。可以使用"+“运算符添加方法,使用”-"运算符移除方法。委托是异步编程的基础:委托可以用于处理异步操作的回调函数,通过在异步操作完成后调用委托实例来进行相应的处理。 委托在实现回调、事件处理、多线程编程等方面有着重要的作用。它们提供了一种灵活、可扩展和可维护的方式来处理方法的调用和通信,使得程序设计更加灵活和可扩展。 1.2 委托的语法和声明 委托的语法和声明主要包括以下几个步骤: 定义委托类型:使用 delegate 关键字来定义委托类型。委托类型定义了方法的签名,包括参数类型和返回类型。语法格式如下: delegate <返回类型> <委托类型名>(<参数列表>); 例如,定义一个接受两个整数参数并返回整数的委托类型: delegate int MyDelegate(int x, int y); 创建委托实例:根据委托类型创建委托实例,将方法赋值给委托实例。可以使用匿名方法、lambda 表达式或具名方法来创建委托实例。语法格式如下: <委托类型> <委托实例名> = new <委托类型>(<方法名>); 例如,创建一个委托实例并将其赋值给一个具名方法: MyDelegate myDelegate = new MyDelegate(MyMethod); 调用委托实例:使用委托实例调用方法。可以像调用普通方法一样使用委托实例进行调用。 int result = myDelegate(10, 20); 在调用委托实例时,委托会按照所关联的方法的顺序依次调用这些方法,并返回最后一个方法的结果(如果有返回值)。 注意事项: 委托类型的参数列表和返回类型必须与关联的方法的签名一致。委托实例只能调用与委托类型匹配的方法。如果委托实例调用了不匹配的方法,将导致编译错误。委托类型是引用类型,可以通过委托实例传递方法的引用,而不是直接调用方法。可以使用 += 和 -= 运算符来添加和移除方法。+= 运算符将一个方法添加到委托链中,-= 运算符将一个方法从委托链中移除。 1.3 委托的实例化和调用 委托的实例化和调用主要涉及以下几个步骤: 创建委托实例:根据委托类型创建委托实例,并将其与一个或多个方法关联。可以使用匿名方法、lambda 表达式或具名方法来创建委托实例。 <委托类型> <委托实例名> = new <委托类型>(<方法名>); 例如,创建一个委托实例并将其关联到一个具名方法: MyDelegate myDelegate = new MyDelegate(MyMethod); 调用委托实例:通过委托实例调用关联的方法。委托实例可以像调用普通方法一样进行调用,传递参数并获取返回值。

人工智障购买双色球(未开奖)

本文采用多变量输入多变量输出LSTM进行了双色球的号码预测,预测的是2023年10月28日的双色球号码,明日开奖,一起期待吧。 下面是人工智障的实现代码 首先需要爬取双色球的历史数据,本文爬取了2003年至今的双色球开奖号码 #!/usr/bin/python # -*- coding: UTF-8 -*- #爬取2003年2月23日至今的双色球开奖号码 import requests import os from bs4 import BeautifulSoup def download(url,page): html = requests.get(url).text soup = BeautifulSoup(html,'html.parser') list = soup.select('div.ball_box01 ul li') ball = [] for li in list: ball.append(li.string) write_to_excel(page,ball) print(f"第{page}期开奖结果录入完成") def write_to_excel(page,ball): f = open('C:/Users/kaiyang/Desktop/blog/彩票/双色球开奖结果.csv','a',encoding='utf_8_sig') f.write(f'第{page}期,{ball[0]},{ball[1]},{ball[2]},{ball[3]},{ball[4]},{ball[5]},{ball[6]}\n') f.close() def turn_page(): url = "http://kaijiang.500.com/ssq.shtml" html = requests.get(url).text soup = BeautifulSoup(html,'html.parser') pageList = soup.select("div.iSelectList a") for p in pageList: url = p['href'] page = p.

使用MATLAB实现串联超前校正附带校正失效时的补偿策略

本题的例题为: 题目中给出的是时域指标,在进行频域法校正的时候要将时域指标转换成频域指标,转换的公式是根据,胡寿松第五版《自控原理》第239页高阶系统经验公式来进行的,在matlab中解方程即可: clc; clear; % 超前校正例题 % 时域指标 rou = 0.275; ts = 1.7; K_gain = 10; % 根据要求: 首先将时域指标转化成频域指标并得出K % r(t)=t,ess<0.1,K=10 % 超调量<=27.5%,根据经验公式计算要求的相位裕度r_star syms r_star equa_0= rou==0.16+0.4*(1/sind(r_star)-1); r_star = solve(equa_0); r_star = vpa(r_star(2),3); % 调整时间ts<=1.7,根据经验公式估算: K0_exp = 2+1.5*(1/sind(r_star)-1)+2.5*(1/sind(r_star)-1)^2; syms omega_c_star equa_1 = (K0_exp)*pi/omega_c_star==ts; omega_c_star = solve(equa_1); omega_c_star = vpa(omega_c_star,3); % 开始实施串联超前校正 num = 10; den = conv([1,0],[conv([1/2,1],[1/30,1])]); G0 = tf(num,den); [Gm,Pm,wcg,wcp] = margin(num,den); margin(G0);hold on % 直接用相位裕度求解fai_m,进而求解倍频比 % 需要设定补偿量delta delta = 13.

Python与Conda创建虚拟环境

这里写自定义目录标题 CondaPython Conda 创建 conda create -n myenv -python=3.10 说明:这会在conda目录下创建一个独立的环境。 激活 conda activate myenv 取消激活 conda dactivate myenv Python python -m venv myenv 说明:这会在当前目录下新建一个名为myenv独立的python环境,注意是当前目录下。如果想在其他目录下:比如home python -m venv /home/myenv 激活: source myenv/bin/activate 如果在home目录下则: source /home/myenv/bin/activate 取消激活: deactivate 如果要指定python版本: python -m venv --python=/path/to/python3.10 myenv 注意:使用conda创建虚拟环境指定python版本时,即使你的机器中不存在这个版本,也可以创建,因为conda会去下载对应的python版本。而使用python创建虚拟环境,必须首先保证你指定的python版本要在你的机器上存在,即/path/to/python3.10必须存在。

用《斗破苍穹》的视角打开C#3 标签与反射(人物创建与斗技使用)

随着剧情的发展,主线人物登场得越来越多,时不时跳出一个大佬,对我张牙舞爪地攻击。眼花缭乱的斗技让我不厌其烦,一个不小心,我就记不清楚在哪里遇上过什么人,他会什么斗技了。这时候,我就特别希望有个办法,能把所有登场得人物都自动检测出来,到时候就可以直接调用了。比方说萧炎和云韵: [Hero] class 萧炎 { [Skill] public void 八极崩() { } [Skill] public void 焰分噬浪尺() { } [Skill] public void 佛怒火莲() { } } [Hero] class 云韵 { [Skill] public void 风之极陨杀() { } [Skill] public void 风之极落日曜() { } [Skill] public void 风吹势() { } [Skill] public void 风灵分形剑() { } } 这里特意用标签标注了哪些是英雄,哪些是技能。接下来,只要识别这些标签,然后通过反射,就能在最需要的时候,让这些人物登场了。 using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace FrameworkDemo { // 只写Hero也可以,但是规范地写法会加上"

一个tomcat下如何部署多个项目?小编为你详细解答!

一个tomcat下如何部署多个项目?Linux跟windows系统下的步骤都差不多,以下linux系统下部署为例。windows系统下部署同理。 1 不修改端口,部署多个项目 清楚tomcat目录结构的应该都知道,项目包是放在webapps目录下的,那能否在同一个tomcat的webapps目录下运行多个不同项目呢? 答案是可以的。 1、将多个项目包放入webapps文件夹下 2、修改conf下的server.xml文件,新增web应用节点 定位到server.xml文件结束标签之前,新增web应用节点,一个节点代表一个项目 以上新增内容说明: docBase属性: 指定Web应用的文件路径,可以是绝对路径,也可以给定相对路径 path属性: 指定访问该Web应用的URL入口。 reloadable属性: 若这个属性为true,tomcat服务器在运行状态下会监视WEB-INF/classes和WEB-INF/lib目录下class文件的改动,如果监测到class文件被更新,服务器会自动重新加载Web应用。 注意:每个项目本身的一些配置文件修改,例如数据库连接信息配置,请自行配置好,这里不做赘述。另外,以上第2步server.xml中新增节点不是必须的,可以直接进入第3步,也ok。 3、重启tomcat,浏览器输入访问项目地址 注意:以开发提供的项目部署文档说明中地址为准,去进行访问测试; 浏览器访问第一个项目地址ip:8080/ningmengban/app/register/regiseter.html,成功。 浏览器访问第二个项目地址ip:8080/erp/regist,成功。 2 修改端口,部署多个项目 我们已经清楚一个webapps下面可多个项目。另外一种思路则是,可否多个webapps,每个webapps下面运行一个项目? 答案也是可以的。 1、tomcat目下复制webapps目录,并重命名为webapps1 Tomcat下webapps已经部署了一个项目,复制webapps重命名为webapps1,并在该文件夹下删除第一个项目,放第二个项目 2、修改tomcat的conf目下的server.xml文件,设置端口等信息 1)server.xml已有第一个项目的配置信息,现在需要新增第二个项目的配置,在Server节点下,新增Service节点;第2个Service节点复制第1个Service内容 2)复制后,做如下端口等配置修改 以上修改信息说明: Service的name属性修改为Catelina1; http协议访问的Connector port属性修改为8081; AJP协议访问的Connector port属性修改为8010; Engine的name属性修改为Catelina1; Host的appBase属性修改为webapps1; 3、重启tomcat,浏览器输入访问项目地址 浏览器访问第一个项目地址ip:8080/ningmengban/app/register/regiseter.html,成功。 浏览器访问第二个项目地址ip:8081/erp/regist,成功。 最后:下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】 软件测试面试文档 我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

从0开始python学习-31.selenium 文本输入框、下拉选择框、文件上传、时间插件选择元素定位

目录 1. 纯文本输入框 2. 存在默认值的文本输入 3. 下拉选择框 4. 输入后下拉选择框 5. 文件上传 6. 时间插件 1. 纯文本输入框 driver.find_element(By.XPATH,'/html/body/div[2]/td[2]/input').send_keys('测试名称') 2. 存在默认值的文本输入 注意: 1. 这种存在默认值的情况在做自动化测试的时候可以选择不做处理,直接略过该元素,也可以先将默认值清除后再进行输入的方式进行测试 2.如果是下图这种需要具有唯一性的数据,可以使用随机数的方式进行写入,可以有效避免冲出ID出现 driver.find_element(By.XPATH,'/html/body/div[2]/tr[3]/td[2]/input').clear() driver.find_element(By.XPATH,'/html/body/div[2]/tr[3]/td[2]/input').send_keys('ID123'+str(randint(100,999))+'K') 3. 下拉选择框 Select(driver.find_element(By.XPATH,'/html/body/div[2]/tr[8]/td[2]/select')).select_by_value('1') 4. 输入后下拉选择框 注意:下拉选择的元素为【<strong>baidu12 [null]</strong>】,使用xpath的方式可能无法定位到,可以通过手写xpath来完成 # 先找到元素后输入关键词 driver.find_element(By.XPATH,'/html/body/div[2]/tr[6]/td[2]/input[1]').send_keys('baidu12') sleep(2) # 等待2秒让下拉框能加载完成后选择需要的选择后点击 # 这种下拉选择元素的xpath不确定,所以可以根据标签来手动写xpath driver.find_element(By.XPATH,'//strong[text()="baidu12"]').click() 5. 文件上传 文件上传因为点击【浏览】选择的框非浏览器中的操作了,因为无法使用自动化脚本来进行选择,选择使用强制写入的方式将文件路径写入文件上传有个明显特征就是【type="file"】,只要照导这个就能进行写入,如下 driver.find_element(By.XPATH,'/html/body/div[2]/tr[14]/td[2]/span/div[1]/div/div/button').click() sleep(5) # 这里应该【本地上传】的xpath一直会变,所以使用文本的方式点击会更准确一点 //li[text()='本地上传'] driver.find_element(By.XPATH,'//li[text()="本地上传"]').click() sleep(2) # 文件上传需要写入外部文件,自动化脚本无法点击浏览器外的内容,所以这里选择强制写入文件的方式,注意一点就是文件的type=file,所以这里一定要找type=file的元素对应xpath driver.find_element(By.XPATH,'//input[@type="file"]').send_keys(r'D:\python\test\1.png') sleep(1) driver.find_element(By.XPATH,'/html/body/div[6]/div[1]/div[3]/span[1]/input').click() 6. 时间插件 时间插件选择首先需要获取到输入框的xpath:e = driver.find_element(By.XPATH,'//*[@id="start_time"]')根据获取到的XPATH在js中可以调试:$x('//*[@id="start_time"]')[0].value='2023-10-06 10:00:38'然后进行强制写入的方式进行:driver.execute_script('arguments[0].value="2023-10-06 10:00:38"',e) driver.implicitly_wait(3) e = driver.find_element(By.XPATH,'//*[@id="start_time"]') # 时间插件可以使用强制输入的形式写入时间,但是需要配合JS进行,方法如下 driver.execute_script('arguments[0].value="2023-10-06 10:00:00"

Channel 底层原理

channel(通道)用于goroutine(协程)之间的通信。它提供了一种在不同协程之间传递数据的机制。channel是一种类型安全的、阻塞的、先进先出(FIFO)的数据结构,确保发送的数据按照发送的顺序接收。Go语言提供通过通信来共享内存,而不是通过共享内存来通信 1. 基本数据结构 channel的底层源码和相关实现在src/runtime/chan.go中 hchan是Channel底层数据结构对应的结构体 对应的字段说明如下: qcount : 循环数组中的元素数量,长度 dataqsiz :循环数组的大小,容量 buf :指向底层循环数组的指针(环形缓冲区) elemsize : closed:是否关闭的标志,0:未关闭,1:已关闭 elemtype *_type : channel中的元素类型 sendx: 下一次写的位置 recvx :下一次读的位置 recvq:读等待队列 sendq:等待队列 lock mutex:互斥锁,保证读写channel时的并发安全问题 2. Channel的创建 2.1Channel语法 2.2Channel的基本用法 2.3创建源码分析 func makechan(t *chantype, size int) *hchan { //获取无素类型 elem := t.elem // 元素的大小必须小于64K // 编译器已经检查了这一点,但是为了安全起见再次进行检查 if elem.size >= 1<<16 { throw("makechan: invalid channel element type") } if hchanSize%maxAlign != 0 || elem.align > maxAlign { throw("makechan: bad alignment"

前端和后端是Web开发中的两个不同的领域,你更倾向于哪一种?

前端和后端是Web开发中的两个不同的领域,你更倾向于哪一种? 以下是我对前端开发和后端开发的看法。 一、引言 编程世界就像一座大城市,有前端开发和后端开发两个街区供我们探索。对于刚开始学习编程的人来说,这就像站在一个交叉口,不确定该选择哪个街区前进。每个街区都有自己的魅力和机遇,让人眼花缭乱。 ![(https://img-blog.csdnimg.cn/e737919b1db24ec3a847e903edefadf9.png) 二、两者的对比分析 想象一下,前端开发就像城市中繁华的商业区。这是一个直接面向用户的界面设计领域,使用HTML、CSS和JavaScript等技术创造出精美的用户界面。作为前端开发者,你是类似建筑师的存在,设计和构建用户能够直接互动的界面。当用户打开一个网站或应用程序时,他们所看到的就是由前端开发者所创建的界面。因此,前端需要注重美观、用户体验和互动性,给人留下深刻的印象。 作为初学者,站在这个交叉口可能会感到困惑。但是,无论你选择前端还是后端,都是值得探索的领域。前端开发让你能够创造出直接面向用户的界面,给人们带来愉悦的体验。而后端开发则是你深入了解系统运作的机会,处理复杂的数据和逻辑。每个街区都有自己的魅力和挑战,探索它们将带给你无尽的学习和成长。 不管是初学者还是经验丰富的开发者,编程世界就像一座大城市,前端开发和后端开发就像城市的两个不同街区。每个街区都有着特色和机遇,等待着我们去发现。所以,让我们一同踏上这段编程之旅,找到属于自己的那个街区吧!

Lambda表达式的前世今生(生动详细得我自己都被感动了)

Lambda表达式的形成 Lambda这个小宝宝出生之前,大家为了把委托或事件写得简洁优雅(其实就是想偷懒),采用了匿名表达式。可是,在实际使用过程中,大家还想再继续偷点懒,于是就绞尽脑汁地想把匿名表达式不断简化。所以,Lambda表达式的使用前提是:在委托或事件中使用,单独拎出来使用是会报错的。首先,我们通过匿名方法,来写一个委托。 delegate int MyDel(int x); void main(string[] args){ MyDel mc += delegate(int x) {return x}; } 因为C#编译器能对返回值类型做出自动判断,mc的值可以被自动识别为MyDel,所以,MyDel这个类型可以直接省略不写,于是代码就被简化成了这样。 delegate int MyDel(int x); void main(string[] args){ mc += delegate(int x) {return x}; } 然而,delegate这个关键字那么长,写起来好麻烦啊,但又不能不写(要用它标明这是委托类型),于是,人们就想着,用=>来代替delegate关键字,读作goes to。 delegate int MyDel(int x); void main(string[] args){ mc += (int x) => {return x}; } 这时候,大家在想,既然我在定义委托类型的时候,已经写了参数类型,那我在写匿名函数的时候,再写一遍参数类型不就重复了吗?于是再省略一点,就出现了Lambda表达式的基础形态,后续的Lambda表达式在此基础上,出现各种演变。 delegate int MyDel(int x); void main(string[] args){ mc += (x) => {return x}; } 有参无返回值 Action<string> action = msg => Console.

STM32F103+RFID-RC522模块 实现简单读卡写卡demo

目录 前言特别声明:代码下载:功能介绍: 接线STM32STM32F1开发指南(精英版)-库函数版本_V1.2STM32中文参考手册 RFID-RC522RFID射频模块电路原理图 使用图+效果图测试程序0 RC522_Handle()最终效果一、先用手机软件NFC Writer读取空卡看看内容1、打开软件和NFC(ps:我的手机是小米10)2、将空卡贴于手机背部,弹出提示发现新卡,点击“好的”3、上面的新卡片左滑到新卡片1,单击这个卡片4、进入卡片信息详细页面钥匙扣卡M1空白卡 二、编译、烧写程序三、将钥匙扣卡发在模块上,打开串口,开始测试 测试程序1 RC522_Handle1() 核心代码main.crc522.hrc522.c 额外资料 前言 特别声明: 本仓库发布的程序,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。 本人对任何脚本问题概不负责,包括但不限于由任何脚本错误导致的任何损失或损害。 间接使用脚本的任何用户,包括但不限于建立VPS或在某些行为违反国家/地区法律或相关法规的情况下进行传播, 本人对于由此引起的任何隐私泄漏或其他后果概不负责。 任何以任何方式查看此项目的人或直接或间接使用该项目的任何程序的使用者都应仔细阅读此声明。本人保留随时更改或补充此免责声明的权利。一旦使用并复制了任何相关脚本或Script项目的规则,则视为您已接受此免责声明。 本文不含任何广告性质,仅供学习参考。写卡需谨慎!!!,不然可能会玩崩了。血的教训!!! 参考资料: 浅谈IC卡数据分析 智能卡 ISO14443 协议 解读 STM32F103ZET–RFID-RC522使用例程(战舰版) M1卡使用说明书 M1卡介绍 STM32-RC522 Mifare1技术说明(M1卡说明文档) 源码参考:RFID-RC522,不能使用,我进行了一定的修改。下载参考下方传送门。 开发板:正点原子 STM32F103 精英版 语言:C语言 开发环境:Keil5 开发板使用了 LED SPI USART RFID-RC522模块 钥匙扣卡 M1卡 Win10软件 SSCOM串口调试 FlyMcu烧录(ps:电脑安装驱动CH340) 安卓软件 NFC Writer (手机需有NFC功能) 代码下载: ⭐⭐⭐⭐⭐⭐⭐⭐⭐ ⭐⭐ 码云 | GitHub ⭐⭐ ⭐⭐⭐⭐⭐⭐⭐⭐⭐ 功能介绍: 寻卡-》防冲撞-》选卡-》验证2扇区密钥-》读取2扇区0区块数据-》写入数据到2扇区0区块-》再读取2扇区0区块数据。 串口打印卡UID,验证结果,读取到的2扇区0区块数据等信息。 注意:只有验证成功的扇区,才能对此扇区进行读写操作! // 验证A密钥 块地址 密码 SN // 注意:此处的块地址0x0B即2扇区3区块,此块地址只需要指向某一扇区就可以了, // 即2扇区为0x08-0x0B这个范围都有效,且只能对验证过的扇区进行读写操作 status = PcdAuthState(0x60, 0x0B, KEY_A, SN); // 读取M1卡一块数据 块地址 读取的数据 // 注意:因为上面验证的扇区是2扇区,所以只能对2扇区的数据进行读写,即0x08-0x0B这个范围, // 超出范围读取失败。 status = PcdRead(0x08, DATA); 另外:3区块的密钥A单片机读取出来是全00,手机是全ff

Groovy入门学习[脚本编程入门]

文章目录 1 注释和变量定义2 数据类型及方法2.1 运算符2.2 数值2.3 字符串-不可变对象2.4 列表2.5 映射2.6 range-范围 3 正则表达式4 输入输出5 自定义方法6 内置方法7 流程控制7.1 while7.2 for7.3 if7.4 switch7.5 循环关键字:break/continue 8 闭包 closure9 文件和命令行参数10 解析 XML11 执行本地命令12 获取Gerrit仓库分支 Apache Groovy is a powerful, optionally typed and dynamic language, with static-typing and static compilation capabilities, for the Java platform aimed at improving developer productivity thanks to a concise, familiar and easy to learn syntax. It integrates smoothly with any Java program, and immediately delivers to your application powerful features, including scripting capabilities, Domain-Specific Language authoring, runtime and compile-time meta-programming and functional programming.

linux文件组 avc: denied { dac_read_search } for capability=2

linux文件组 avc: denied { dac_read_search } for capability=2 scontext=u:r:xxx:s0 avc: denied { dac_override } for capability=1 scontext=u:r:xxx:s0 tcontext=u:r:xxx:s0 tclass=capability permissive=0 1、当报这种dac的 avc selinux权限是一般是因为不在同一个用户组导致的无法访问。 2、我们可以查看需要访问的文件的用户组: ls -lZ 或者有时候不知道需要在哪个组里才能访问我们需要的文件时,我们可以查看当前可以访问该文件的进程所在的用户组: adb shell ps -AlZ | grep -Ei "xxx" u:r:xxx_app:s0 5 S 1000 7867 1610 0 19 0 - 3727967 0 ? 00:00:00 android.xxxtest 首先查找进程的id号,这里是7867 adb shell cat proc/7867/status 输入 上面的命令查看 android.xxxtest 进程的信息 Name: android.xxxtest Umask: 0077 State: S (sleeping) Tgid: 7867 Ngid: 0 Pid: 7867 PPid: 1610 TracerPid: 0 Uid: 1000 1000 1000 1000 Gid: 1000 1000 1000 1000 FDSize: 64 Groups: 0 1000 1000 1003 1004 1007 1065 1077 2001 2901 3001 3002 3003 3007 9997 VmPeak: 15187360 kB VmSize: 14911868 kB VmLck: 0 kB VmPin: 0 kB VmHWM: 78300 kB VmRSS: 68440 kB RssAnon: 2576 kB RssFile: 65468 kB RssShmem: 396 kB VmData: 667424 kB VmStk: 8192 kB VmExe: 28 kB VmLib: 147056 kB VmPTE: 940 kB VmSwap: 36704 kB CoreDumping: 0 THP_enabled: 0 Threads: 17 SigQ: 3/12941 SigPnd: 0000000000000000 ShdPnd: 0000000000000000 SigBlk: 0000000080001204 SigIgn: 0000000000000001 SigCgt: 0000006e400084f8 CapInh: 0000000000000000 CapPrm: 0000000000000000 CapEff: 0000000000000000 CapBnd: 0000000000000000 CapAmb: 0000000000000000 NoNewPrivs: 0 Seccomp: 2 Speculation_Store_Bypass: thread vulnerable Cpus_allowed: 3f Cpus_allowed_list: 0-5 Mems_allowed: 1 Mems_allowed_list: 0 voluntary_ctxt_switches: 39 nonvoluntary_ctxt_switches: 45 这里可以看到就是我们需要的用户组信息:

jni不再需要javah啦!

以前的老方法javah不再需要啦,现在你在java文件添加一个接口,例如: public native int init(); 然后你只需要把光标定位到“init”然后按alt+enter按键,就会出现一个菜单项“Create JNI funcion”, 点击这个菜单项,就会自动生成了,方便多啦! 生成后的例子: extern "C" JNIEXPORT jint JNICALL Java_com_xxx_testlib_NativeLib_init(JNIEnv *env, jobject thiz){ }

linux之date命令

date 命令用于 显示 或 设置系统的时间或日期。 格式:date [参数] [+日期格式] 注意: date后面有一个空格,否则无法识别命令,shell对空格是很严格的。 1、Linux date命令参数 日期时间格式符号: %H 小时(以00-23来表示)。 %I 小时(以01-12来表示)。 %K 小时(以0-23来表示)。 %l 小时(以0-12来表示)。 %M 分钟(以00-59来表示)。 %P AM或PM。 %r 时间(含时分秒,小时以12小时AM/PM来表示)。 %s 总秒数。起算时间为1970-01-01 00:00:00 UTC。 %S 秒(以本地的惯用法来表示)。 %T 时间(含时分秒,小时以24小时制来表示)。 %X 时间(以本地的惯用法来表示)。 %Z 数字方式显示时区。 %a 星期几 ,缩写(Sun…Sat)。 %A 星期几 ,完整英文星期(Sunday…Saturday) %b 月份 (Jan…Dec) %B 月份 (January…December) %c 日期与时间。只输入date指令也会显示同样的结果。 %d 日(以01-31来表示)。 %D 日期(含年月日)。以MM/DD/YY显示日期。 %F 日期(含年月日)。以YYYY-MM-DD显示日期. %j 一年中的第几天 (001…366)。 %m 月份(以01-12来表示)。 %U 该年中的周数。 %u 一周中的第几天 (1…7) (1是星期一)

Maven项目打包时,如何将配置文件外置

在打包发布后,有时候需要修改配置文件,为了避免频繁打包,可将配置文件外置 <build> <resources> <!--指定src/main/resources资源要过滤--> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> <plugins> <!-- 可执行jar插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <!--这些配置将写入到MANIFEST.MF文件中--> <archive> <!--指定程序入口--> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <!--这里修改主类所在包--> <mainClass>com.*.*.Application</mainClass> </manifest> <!-- (配置文件外置目录) --> <manifestEntries> <Class-Path>config/</Class-Path> </manifestEntries> </archive> <!-- 排除jar包中的配置文件,只保留java代码 --> <excludes> <exclude>**/*.xml</exclude> <exclude>**/*.conf</exclude> <exclude>**/*.properties</exclude> <exclude>**/*.yml</exclude> <exclude>**/*/*.json</exclude> </excludes> </configuration> </plugin> <!-- maven资源文件复制插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>2.7</version> <executions> <execution> <id>copy-config</id> <phase>package</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/config</outputDirectory> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> <encoding>UTF-8</encoding> </configuration> </execution> </executions> </plugin> <!

qt开发从入门到实战2

以下是本人学习笔记 原视频:最新QT从入门到实战完整版|传智教育 qt开发从入门到实战1 练习示例 设计一个按钮,点击时弹出新窗口,再次点击时新窗口关闭 // exercise QWidget* second_window = new QWidget(); QPushButton* btn3 = new QPushButton("open", this); btn3->move(0, 100); connect(btn3, &QPushButton::clicked, second_window, [=](){ if(btn3->text() == "open"){ second_window->show(); second_window->resize(100, 100); btn3->setText("close"); }else if(btn3->text() == "close"){ second_window->close(); btn3->setText("open"); } }); 注意:加入窗口和加入对象树是两个不同的概念 一、窗口中的基础部件 1.创建菜单栏 讲解见注释 // 创建菜单栏 // 菜单栏最多只有一个 // menuBar构造函数已经把自身加入对象树了 QMenuBar* bar = menuBar(); // 将菜单栏放入窗口 setMenuBar(bar); // 创建菜单 QMenu* fileMenu = bar->addMenu("file"); QMenu* editMenu = bar->addMenu("edit"); // 创建菜单项 QAction* newAction = fileMenu->addAction("

从代理模式说起,简单聊聊Java的动态代理

从代理模式说起 「代理模式」是设计模式的一种,代理模式中有两个关键的成员:「代理类」(Proxy)和「被代理类」(RealSubject) 那Proxy有啥用呢,直接访问RealSubject不行嘛? 如果「被代理类」十分庞大(消耗内存空间),但真正需要它的时候很少,我们不希望立即初始化「被代理类」从而占用内存,交给轻量级的「代理类」Proxy完成任务即可。我们希望对「被代理类」进行一些增强,比如说在方法开始执行前后打印参数的变化,执行结果等等信息,为了解耦「被代理类」的业务实现和这种与业务无关的行为逻辑,我们需要将这些与业务无关的行为逻辑剥离出来,就可以封装在「代理类」中往往这种与业务无关的行为逻辑有很多共性,这些逻辑可以被抽象为「切面」,也就是AOP,面向切面编程,通过代理模式可以极大地减少重复代码。 代理模式的实现方法 代理模式一般有两种实现方法:静态代理和动态代理。 静态代理 静态代理就是上述UML图的实现方法,可以看到「代理类」Proxy内聚一个RealObject,实现共同的接口,可以很轻松地在这个方法上做加强。 接口: csharp 复制代码 public interface Subject { void dosth(); } 被代理类: java 复制代码 public class RealSubject implements Subject{ @Override public void dosth(){ System.out.println("dosth..."); } } 代理类: java 复制代码 public class Proxy implements Subject{ private Subject subject; @Override public void dosth(){ System.out.println("before-------执行前增强逻辑"); subject.dosth(); System.out.println("after--------执行后增强逻辑"); } } 静态代理的局限性 每需要一个类被代理,就需要为之编写一个代理类,这会导致文件数量膨胀。上文提到的Proxy的第三个好处,即AOP的功能还没有实现,我们希望一个代理类能代理多个类,并且被代理的方法是我们可以指定的,这就需要动态代理来解决了。 动态代理 动态代理又有两种常见的实现:JDK动态代理和CGLIB动态代理。 JDK动态代理 基本使用 JDK动态代理中:「代理类」Proxy不再实现Subject接口,而是implements InvocationHandler,但仍聚合了被代理类(通过构造函数传入被代理类,Object类型) 代理类implements InvocationHandler,重写invoke方法 java 复制代码 public class TestInterceptor implements InvocationHandler { private Object target;//目标对象的引用,这里设计成Object类型,更具通用性 public TestInterceptor(Object target){ this.

JavaScript入门——基础知识(3)

一、运算符 1.1 赋值运算符 目标:能够通过使用赋值运算符简化代码 赋值运算符:对变量进行赋值的运算符 将等号右边的值赋予给左边,要求左边必须是一个容器其他赋值运算符: +=-=*=/=%=使用这些运算符可以在对变量赋值时进行快速操作 例如+=赋值运算符 以前让一个变量加1如何做? <script> let num = 1 num = num + 1 console.log(num) // 结果是2 </script> 现在简单写法 <script> let num = 1 num += 1 console.log(num) // 结果是2 </script> 提问:想变量加3怎么写? ​ <script> let num = 1 num += 3 console.log(num) // 结果是4 </script> ​ 总结: =赋值运算符执行过程? 将等号右边的值赋予给左边,要求左边必须是一个容器+=出现是为了简化代码,比如让let num = 10,num加5怎么写呢? num += 5其他类型的赋值运算符,与+=赋值运算符一样 1.2 一元运算符 众多的JavaScript的运算符可以根据所需表达式的个数,分为一元运算符、二元运算符、三元运算符 二元运算符 例: let num = 10 + 20 一元运算符: 例:正负号问题:以前让一个变量每次+1,是怎么做的? let num = 1 num = num + 1 //或 let num = 1 num += 1 更简便的写法 自增: 符合:++作用:让变量的值+1,只能每次加一用法: 前置自增 let num = 1 ++num // 让num的值加1边2 后置自增 let num = 1 num++ // 让num的值加1边2 区别: 前置自增:先自加1,再参与运算(口诀:++ 在前 先加) let i = 1 console.

react-hook

一、hook基本概念 react组件中分为两种:一种是类组件,一种是函数组件 类组件: 通过class类组件进行开发内部有内部state状态拥有生命周期函数 函数组件: 通过函数来定义组件内部没有state内部状态没有生命周期 二、hook的由来 随着react版本的更迭,到了react16.8版本的时候,新增了hook特性,让函数组件内部也可以拥有内部状态,以及生命周期。没有this指向。 类组件: class App extends React.Component { constructor(props) { super(props) } click = () => { } render() { return <div onClick={this.click}>类组件</div> } } 函数组件: function App(props) { function click() { } return <div onClick={click}>函数组件</div> } 为什么会有hook函数? 从类组件的开发的难易程度来说,类组件要求储备的知识量更大,而函数组件要求更低,如果函数组件拥有了内部状态那么就可以使用函数组件开发任何组件。类组件开发基于面向对象的方式进行开发,类与类之间形成了一种强依赖,继承的方式有时候不是最好的解决方案,从代码拆分的难易程度来说,类组件相比之下不好拆分。语法上来说,函数组件更加的简洁 hook的使用规则 只在最顶层使用 Hook 不要在循环,条件或嵌套函数中调用 Hook, 确保总是在你的 React 函数的最顶层调用他们。遵守这条规则,你就能确保 Hook 在每一次渲染中都按照同样的顺序被调用。这让 React 能够在多次的 useState 和 useEffect 调用之间保持 hook 状态的正确。(如果你对此感到好奇,我们在下面会有更深入的解释。) 只在 React 函数中调用 Hook **不要在普通的 JavaScript 函数中调用 Hook。**你可以:

[论文阅读]RTMDet——实时目标检测

RTMDet RTMDet: An Empirical Study of Designing Real-Time Object Detectors 设计实时目标检测器的实证研究 论文网址:RTMDet 摘要 本文的目标是设计一种超越 YOLO 系列的高效实时目标检测器,并且可以轻松扩展到实例分割和旋转目标检测等许多目标识别任务。为了获得更高效的模型架构,本文探索了一种在主干和颈部具有兼容能力的架构,该架构由大内核深度卷积组成的基本构建块组成。在动态标签分配中计算匹配成本时进一步引入软标签以提高准确性。再加上更好的训练技术,最终的目标检测器(名为 RTMDet)在 NVIDIA 3090 GPU 上以 300+ FPS 的速度在 COCO 上实现了 52.8% 的 AP,优于当前主流的工业检测器。 RTMDet 针对各种应用场景实现了tiny/small/medium/large/extra-large模型尺寸的最佳参数精度权衡,并在实时实例分割和旋转对象检测方面获得了最先进的性能。 引言 最佳效率始终是物体检测的首要追求,特别是对于自动驾驶、机器人和无人机的现实世界感知而言。为了实现这一目标,YOLO系列探索不同的模型架构和训练技术,以不断提高单级目标检测器的准确性和效率。 本报告的目标是突破 YOLO 系列的极限,并贡献一个新的目标检测实时模型系列,名为 RTMDet,它还能够进行以前的工作尚未探索的实例分割和旋转对象检测。吸引人的改进主要来自于大内核深度卷积的更好表示以及动态标签分配中软标签的更好优化。 具体来说,首先在模型的主干和颈部的基本构建块中利用大内核深度卷积,这提高了模型捕获全局上下文的能力。由于直接将深度卷积放在构建块中会增加模型深度从而减慢推理速度,因此进一步减少构建块的数量以减少模型深度并通过增加模型宽度来补偿模型容量。本文还观察到,在颈部放置更多参数并使其容量与主干兼容可以实现更好的速度精度权衡。模型架构的整体修改允许 RTMDet 的快速推理速度,而不依赖于模型重新参数化 [Yolov6, Yolov7, PP-YOLOE]。 本文进一步重新审视训练策略以提高模型的准确性。除了更好地结合数据增强、优化和训练计划之外,本文凭经验发现,在匹配地面真值框和模型预测时,通过引入软目标而不是硬标签,可以进一步改进现有的动态标签分配策略[TOOD, YOLOX] 。这样的设计提高了成本矩阵的辨别力以实现高质量匹配,同时也降低了标签分配的噪声,从而提高了模型的准确性。 RTMDet 是通用的,只需很少的修改就可以轻松扩展到实例分割和旋转对象检测。通过简单地添加内核和掩码特征生成头[ Sparse instance activation for real-time instance segmentation-2022, Conditional convolutions for instance segmentation-2020],RTMDet 仅需大约 10% 的额外参数即可执行实例分割。对于旋转物体检测,RTMDet 只需要扩展框回归层的维度(从 4 到 5)并切换到旋转框解码器。本文还观察到,对通用目标检测数据集 [Microsoft COCO] 的预训练有利于空中场景中的旋转目标检测 [Dota]。