搭建网页vscode服务器Code-Server

一、硬件基础 cm311-1a 是的,一个机顶盒,然后运行amrbian(可以看成是ubuntu的arm版本),当然你也可以使用x86、x64等其他架构的机器安装linux-server搭建。(具体区别会提到) 二、安装amrbian 感谢op大佬的固件。这里给出github仓库地址:https://github.com/ophub/amlogic-s9xxx-armbian 具体如何安装可以自行查找教程,这里不过多赘述 如果你是x86/x64的机器可以安装ubuntu-server 三、下载code-server code-server仓库地址:https://github.com/coder/code-server 在release中选择与你机器对应的安装包。 github的访问还是有点难搞的,建议下载到电脑上,然后用ftp传到机器上。 这里推荐使用FinalShell或者WinScp传文件到机器 这里要记住你传包的路径,以我的为例我的安装包位置在 /home/enen/download_file 你的路径可以和我不一样,下面的几个文件是vscode的插件现在不用管。 四、安装 ssh连接到机器命令行输入下面的/home/enen/download_file要替换成你第三步上传的路径 进入上传路径: #路径记得替换成你自己的 cd /home/enen/download_file 建议输入ls看一下有没有安装包 然后命令行输入 输入完sudo dpkg -i 后只用输入code后按tab就i能自动补齐,包名版本和我的可能不同,但是应该也是code开头即可。 安装: sudo dpkg -i code-server_4.5.1_arm64_2.deb 等待安装完成。 安装完成需要更改~/.config/code-server/config.yaml文件,使用vi、vim、nano甚至用finalshell编辑都可以。把 bind-addr:127.0.0.1:8080 改成 bind-addr: 0.0.0.0:8080 然后输如命令生效: sudo systemctl restart code-server@$USER 浏览器输入机器的 ip:8080 例如我这台机器在 192.168.6.247,就在浏览器输入 192.168.6.247:8080 出现如下界面就安装成功了 五、配置 官方教程:https://coder.com/docs/code-server/latest 初始密码文件在~/.config/code-server/config.yaml 查看初始密码: cat ~/.config/code-server/config.yaml password后面就是随机生成的初始密码 更改密码或者端口直接编辑config.yaml文件即可 更改密码或端口生效: sudo systemctl restart code-server@$USER 后面就是配置vscode了,如果没有搜索到自己想要的插件可以去vscode官网https://marketplace.visualstudio.com/VSCode下载你想要的插件,用FTP传上去在网页界面安装即可 完结撒花(❁´◡`❁)

Jetson嵌入式系列模型部署-1

目录 前言1. What、Why and How1.1 What1.2 Why1.3 How 2. tensorRT2.1 什么是tensorRT?2.2 tensorRT特性2.3 tensorRT工作流程 3. 驾驭tensorRT的几种方案3.1 repo1 https://github.com/wang-xinyu/tensorrtx3.2 repo2 https://github.com/NVIDIA-AI-IOT/torch2trt3.3 repo3 https://github.com/shouxieai/tensorRT_Pro 4. tensorRT_Pro4.1 Protobuf4.1.1 Protobuf简介4.1.2 基本使用流程 4.2 ONNX4.2.1 概念4.2.2 组成 5. Jetson nano6. 结语7. 下载链接8. 参考 前言 本文旨在为大家提供jetson嵌入式系列模型部署两个简单的技术路线,直白的说就是给大家安利两个仓库分别是tensorrtx和tensorRT_Pro。本文采用常见的yolov5(v6.0版本)目标检测算法实现在jetson nano上的模型部署工作(PS:手头只有nano,太穷了,😂)。假设各位看官的jetson nano环境配置已经完成,能够使用yolov5成功训练自己的数据集。我们重点关注jetson nano上的部署工作。有错误欢迎各位批评指正!!! 本次训练的模型使用yolov5s-6.0,类别数为2,为口罩识别😷。先看效果图,第一张图为tensorrtx在jetson nano上的推理效果图,可参考Jetson嵌入式系列模型部署-2查看详细流程;第二张图为tensorRT_Pro在jetson nano上的推理效果图,可参考Jetson嵌入式系列模型部署-3查看详细流程。 1. What、Why and How 问题: 什么是深度学习模型部署?为什么需要部署?如何去部署呢? 1.1 What 什么是深度学习模型部署? 简单来说就是将你训练好的深度学习模型应用在不同场景下的不同设备上(即特定环境下运行),这些设备可能是服务器、移动端、嵌入式… 1.2 Why 为什么要学习部署呢? 直接将模型放在不同的设备上跑不就完事了吗😕?其实不然,这样做存在两个问题:模型框架兼容性差以及模型运行速度慢。大家知道目前训练模型都基于深度学习框架如pytorch、tensorflow、paddle等,这些框架的兼容性差(直白点说就是环境配置麻烦,一想起深度学习环境配置就头痛🙃),而且这些框架基于python语言其运行速度无法和C++这类语言相比。 假设我们需要在jetson nano上去部署属于自己的yolov5模型,难道要求我们在jetson nano上配置pytorch等深度学习环境吗?那未免也太折磨人了,单纯基于pytorch等框架去进行模型的推理存在以下几个问题: 环境配置繁琐,且不说在arm架构的嵌入式上配置深度学习环境了,光在PC端都要折腾一阵携带的框架太过笨重,训练出的模型太冗余需要优化才能满足实际需求语言问题,框架大多基于python语言,运行速度慢移植问题,框架环境依赖性强,耦合性高,无法更加方便的移植参考自模型部署简介 基于以上问题,我们想能不能将框架隔离呢?即仅通过pytorch、tensorflow、paddle等框架训练模型,后续在不同场景下的部署实现仅需要训练好的模型即可,而不需要依赖框架推理。 1.3 How 如何去部署? 即解决方案。怎么利用训练好的模型不依赖框架推理呢?——通过模型推理部署框架,依旧是框架不过这次换成了模型推理框架😎。目前主流的模型推理部署框架有以下几种: NVIDIA的TensorRT。首当其冲的肯定是tensorRT,NVIDIA通过其自家的GPU,CUDA、CUDNN等软件环境形成了一个强大的生态圈。该推理框架主要是针对NVIDIA的显卡和其推出的jetson系列嵌入式设备。Intel的OpenVINO。openvino是Intel开发的基于inter CPU计算设备的推理引擎。Tencent的NCNN。ncnn是腾讯基于移动端的推理引擎。Microsoft的ONNXRuntime。onnx是microsoft开发的一个中间格式,而ort(onnxruntime)是其为onnx开发的推理引擎Rockchip的RKNN。rknn是瑞芯微为其NPU设计的nn推理引擎。参考自业界主流模型推理部署框架,RKNN使用 具体使用那种推理框架呢?—看需求,部署的方式取决于需求。如果需要在jetson系列嵌入式平台上推理,那么选择tensorRT再合适不过了;如果需要在手机移动端推理,那么可以腾讯的ncnn推理框架;能做到见招拆招即可。参考自训练好的深度学习模型式怎么部署的?

Jetson nano部署YOLOv7

目录 前言一、YOLOv7模型训练1. 项目的克隆和必要的环境依赖1.1 项目的克隆1.2 项目代码结构整体介绍1.3 环境安装 2. 数据集和预训练权重的准备2.1 数据集2.2 预训练权重准备 3 训练模型3.1 修改模型配置文件3.2 修改数据配置文件3.3 训练模型3.4 推理测试 二、YOLOv7模型部署1. 源码下载2. 环境配置2.1 Jtop(option)2.1.1 配置pip2.1.2 安装jtop2.1.3 使用jtop 2.2 编译Protobuf2.2.1 解压2.2.2 编译2.2.3 安装2.2.4 环境配置(option) 2.3 配置CMakeLists.txt 3. ONNX导出3.1 源码下载3.2 修改代码3.3 导出ONNX模型3.4 拓展-正确导出ONNX文件 4. 运行4.1 源码修改4.2 编译4.3 模型构建和推理4.4 拓展-摄像头检测 结语下载链接参考 前言 yolov7模型部署流程和yolov5几乎完全一致,大家可以先查看我之前的Jetson嵌入式系列模型部署教程。考虑到nano的算力,这里采用yolov7-tiny.pt模型,本文主要分享yolov7模型训练和jetson nano部署yolov7模型两方面的内容。若有问题欢迎各位看官批评指正!!!​😃 一、YOLOv7模型训练 yolov7的代码风格和yolov5非常像,训练流程可参考yolov5的训练。博主主要参考炮哥带你学的利用yolov5训练自己的目标检测模型以及深度学习麋了鹿的yolov7训练测试自己的数据集 1. 项目的克隆和必要的环境依赖 1.1 项目的克隆 yolov7的代码是开源的可直接从github官网上下载,源码下载地址是https://github.com/WongKinYiu/yolov7,由于yolov7刚发布不久目前就只固定v0.1一个版本,而v0.1版本并未提供训练的详细说明,故采用主分支进行模型的训练和部署工作。Linux下代码克隆指令如下 git clone https://github.com/WongKinYiu/yolov7.git 也可手动点击下载,点击右上角的绿色的Code按键,将代码下载下来。至此整个项目就已经准备好了。也可以点击here[password:yolo]下载博主准备好的代码(注意该代码下载于2022/8/31日,若有改动请参考最新) 1.2 项目代码结构整体介绍 将下载后的yolov7的代码解压,其代码目录如下图 现在来对代码的整体目录做一个介绍 |-cfg:存放yolov7不同模型的yaml文件,如yolov7.yaml、yolov7-tiny.yaml等,包括训练和部署时的yolov7模型yaml|-data:存放一些超参数的配置文件以及配置训练集和验证集路径的coco.yaml文件,如果需要修改自己的数据集,那么需要修改其中的yaml文件|-deploy:针对部署的文件夹|-figure:存放yolov7测试的效果图片|-inference:存放推理时的图片|-models:存放yolov7整体网络模型搭建的py文件|-paper:存放yolov7论文|-scripts:脚本文件,用于获取coco数据集|-tools:该文件夹主要存放一些示例教程,如yolov7关键点检测、yolov7实例分割、yolov7onnx等等|-utils:存放工具类函数,包括loss、metrics、plots函数等|- detect.py:检测代码,包括图像检测、视频流检测等export.py:模型导出代码,如onnx导出hubconf.py:pytorch扩展模型requirements.txt:文本文件,里面包含使用yolov7项目的环境依赖包以及相应的版本号test.py:测试代码train.py:训练代码train_aux.py:训练辅助头代码(不确定) 1.3 环境安装 关于深度学习的环境安装可参考炮哥的利用Anaconda安装pytorch和paddle深度学习环境+pycharm安装—免额外安装CUDA和cudnn(适合小白的保姆级教学),这里不再赘述。如果之前配置过yolov5的环境,yolov7可直接使用。 2. 数据集和预训练权重的准备 2.

js求数组最大值有哪些方式

JavaScript 中可以使用多种方式来求数组的最大值。 Math.max() 方法 可以使用 Math.max() 方法来获取数组中的最大值,例如: let arr = [1, 5, 3, 8, 2]; let maxNum = Math.max(...arr); console.log(maxNum); // 输出 8 在这个例子中,使用了展开运算符 ... 将数组中的元素作为参数传递给 Math.max() 方法。 循环遍历数组并比较 可以使用循环遍历数组,并使用一个变量来保存数组中的最大值。每当遇到一个比当前最大值大的元素时,更新变量的值。例如: let arr = [1, 5, 3, 8, 2]; let maxNum = arr[0]; // 假设第一个元素为最大值 for (let i = 1; i < arr.length; i++) { if (arr[i] > maxNum) { maxNum = arr[i]; } } console.log(maxNum); // 输出 8 使用 reduce() 方法 reduce() 方法可以将数组中的元素通过一个回调函数逐个进行计算,并返回最终的结果。可以在回调函数中比较每个元素和当前的最大值,并返回较大的值作为下一轮计算的最大值。例如:

Python基础——字典

字典的特征 通过键而不是通过索引来读取,字典有时也被称为关联数组或者散列表,它是通过键将一系列的值联系起来的,这样就可以通过键从字典中获取指定项,但是不能通过索引来获取。 字典是任意对象的无序集合。字典是无序的,各项是从左到右随机排序的,即保存在字典中的项没有特定的顺序,这样可以提高查找顺序。 字典是可变的,并且可以任意嵌套。字典可以在原处增长或者缩短(无须生成一个副本),并且它支持任意深度的嵌套(即它的值可以是列表或者其他的字典)。 字典中的键必须唯一。不允许同一个键出现两次,如果出现了两次,则后一个值会被记住。 字典中的键必须不可变。可以使用数字、字符串或者元组,但不能使用列表。 创建 定义字典时,每个元素都包含两个部分”键”和”值”,并且在键和值之间使用冒号分隔,相邻两个元素使用逗号分隔,所有元素放在一个大括号中。 dictionary={'key1':'value1',……,'keyn':'valuen'} 参数说明: dictionary:表示字典名称 key:表示元素的键,必须是唯一的,并且不可变,可以是数字、字符串、元组。 vaule:表示元素的值可以是任何数据类型,不是必须唯一。 #创建空字典 dictionary = {} 或 dictionary = dict() #通过映射函数创建字典 #zip()函数:用于将多个列表或元组对应位置的元素组合为元组,并返回包含这些内容的zip对象 #列表1:表示一个列表,用于生成指定要生成字典的键 #列表2:表示一个列表,用于指定要生成字典的值。 #如果list1和list2的长度不同,则与最短的列表长度相同 字典名称 = dict(zip(列表1,列表2)) #通过给定的键——值对创建字典 dictionary = dict(key1=value1,key2=value2,……) #使用dict对象的fromkeys()方法创建值为空的字典 #list1:作为字典的键的列表 dictionary = dict.fromkeys(list1) 添加、修改元素 字典名[键名]=值 因字典中键名的唯一性,当键不存在时为创建,当键存在时为修改 删除 删除整个字典 del 字典名 删除字典全部元素 字典名.clear() 执行后,原字典将变为空字典 删除字典指定元素 del 字典名[键名] #防止字典元素不存在,删除报错的改进 if 键名 in 字典名: del 字典名[键名] 访问字典 直接使用print()函数 print(字典名) 根据键获取值 #普通获取 print(字典名['键名']) #避免键不存在,出现异常 print(字典名['键名'] if ’键名‘ in 字典名 else ’字典中没有此键’) 使用字典对象get()方法获取指定键的值

树莓派视觉小车 -- OpenCV巡线(HSL色彩空间、PID)

目录 试错 试错1:形态学处理 试错2:HSV色彩空间 基础理论 1、HSV与HSL色彩空间 2、PID调节 一、OpenCV图像处理 1、在HSL色彩空间下得到二值图 2、 对二值图形态学处理 3、找出线的轮廓和中心点坐标 二、PID 三、运动控制 总代码 试错 试错1:形态学处理 一开始用的形态学处理,自行改变阈值,调试之后,进行处理,发现效果不是太好,于是改成了HSV色彩空间。 试错2:HSV色彩空间 之前没注意到,HSV色彩空间很难识别白色: HSV: 不难看出,如果寻白色线的话,HSV色彩空间不是一个很好的选择,下面引入HSL色彩空间: HSL: 所以,如果是巡白色的话,建议用HSL色彩空间。 注意:巡线小车的摄像头不能太低,如果太低了,可能让小车自己的影子会阻碍光线。 hsv中的效果: hsl中的效果: 可以看出,已经能大致找到白线了。 基础理论 1、HSV与HSL色彩空间 HSV: 不难看出,如果寻白色线的话,HSV色彩空间不是一个很好的选择,下面引入HSL色彩空间: HSL: 所以,如果是巡白色的话,建议用HSL色彩空间。 2、PID调节 个人理解: P:拉力 I:推动力 D:阻力 一、OpenCV图像处理 1、在HSL色彩空间下得到二值图 # 在HSV色彩空间下得到二值图 def Get_HSV(image): # 1 get trackbar's value hmin = cv2.getTrackbarPos('hmin', 'h_binary') hmax = cv2.getTrackbarPos('hmax', 'h_binary') smin = cv2.getTrackbarPos('smin', 's_binary') smax = cv2.getTrackbarPos('smax', 's_binary') lmin = cv2.getTrackbarPos('lmin', 'l_binary') lmax = cv2.

2021 Oral CVPR : Exploring Simple Siamese Representation Learning

论文 代码 1. 摘要 孪生网络已经成为无监督视觉表征学习的主流框架,最大化同一图像的两个增广图的相似性使其避免 崩溃解(collapsing solutions) 问题。本文提出了一个simple Siamese网络可以在不使用1) 负样本对;2)大批量; 3) 动量编码器取得好的结果。崩溃解存在于损失函数和网络中,但是可以通过stop-gradient操作避免崩溃解。SimSiam在ImageNet及下游任务上均取得了有竞争力的结果。 2. 引言 Siamese 网络是应用于两个或多个输入的 权重共享 神经网络,可以用来 比较(包括但不限于“对比”)实体。最近的方法将输入定义为一幅图像的两个增强,并根据不同的条件最大化相似性。本文提出的Siamese 既没有使用负样本对也没有使用动量编码器防止崩溃解,而是通过最大化同一张图片的两个视角相似度,既适用于典型的批量大小,也不依赖于大批量训练。 Contrastive learning:排斥来自不同图像的输入,同时吸引相同图像的两个增强图片。负对排除了来自解空间的恒定输出。 Clustering:在聚类表示和学习预测聚类分配之间交替。SwAV 通过从一个视图计算分配并从另一个视图进行预测来将聚类融合到一个孪生网络。SwAV在每个batch的平衡分区约束下执行在线聚类。为了提供充足的样本进行聚类,往往会使用大批量训练。 BYOL :从一个视图直接预测另一个视图的输出,它是一个分支为 动量编码器的孪生网络。 3. 方法 上述公式等价于规范化向量的MSE损失。与此同时,还定义了一个对称损失. 上述两个损失作用于每一张图像,总损失是所有图像损失的平均,故最小的可能损失为-1. 使用stop-gradient操作修改loss函数为: 在损失的第一项, x 2 \begin{array}{c}_{x_2 } \end{array} x2​​​不会从 z 2 \begin{array}{c}_{z_2 } \end{array} z2​​​接收梯度信息;在其第二项,则会从 p 2 \begin{array}{c}_{p_2 } \end{array} p2​​​接收梯度信息。 SimSiam伪代码实现如下 3.1 Baseline settings Optimizer: SGD用于预训练,学习率为, l r × b a t c h s i z e / 256 \begin{array}{c} lr\times batchsize {/} 256 \end{array} lr×batchsize/256​基础学习率为 l r = 0.

Layui数据表格

添加表格容器 设置id 和 lay-filter <div> <table id="active-info" lay-filter="active"></table> </div> 2. layui.use('table', function () { var table = layui.table; //第一个实例 table.render({ elem: '#active-info' , height: 312 , url: 'http://localhost:8080/Graduation_project_1_war/Activity_Servlet' //数据接口 , page: true //开启分页 , loading: true , toolbar: "#toolbarhead"//这是绑定表头工具栏 , text: { none: "您还没有参加任何活动" } , parseData: function (res) { console.log(res); return { "code": 0,//数据状态 "msg": "",//数据信息 "count": 5,//数据总数 data: res } } , cols: [[ //表头 , {field: 'activists', title: '活动名称', width: 200, sort: true,} , {field: 'activists_inf', title: '活动内容', width: 200, sort: true} , {field: 'activities_date', title: '活动日期', width: 200} , { fixed: 'right', title: '查看详情', width: 220, align: 'center', toolbar: '#toolbar'//这是绑定表格内工具栏 } ]] }); table.

为什么word修改下一节页眉奇偶不同会影响到下一节页眉的奇偶相同

问题 是这样的,学校论文格式要求目录页眉奇偶相同,从绪论往后页眉奇偶不同。我一开始没注意,设置的从目录及以后奇偶不同,奇数页是节标题,偶数页是学校名称 发现问题之后就将目录节改为奇偶相同,然后发现诶第一章怎么也奇偶相同了?将第一章改为奇偶不同,完了发现诶怎么目录也跟着变成奇偶不同了???? 解决方法 将目录节页眉改为奇偶不同的话要同时设置目录节的奇数页页眉和偶数页页眉为“目录”,不然就会沿用以前的偶数页页眉

Dempster-Shafer (D-S)证据理论

Dempster-Shafer (D-S)证据理论 自从上世纪70年代,A.P.Dempster提出了证据理论的雏形,而后他的学生G.Shafer在其研究的基础上加以完善和发展,形成了现在的证据理论,该理论针对于不确定问题的处理,区分不确定信息与未知信息对系统的影响,从而可以更好的处理多来源的相互独立的证据源的信息,有效消除证据的片面不确定性,使得到更加准确的结果。在证据理论的发展过程中,其在理论水平主要有两个问题:一是当证据中存在相违背的信息时,得到的结果可能会产生悖论;二是证据理论是以集合的形式存在的,当集合中的焦元数量过大时,在进行数据分析的过程中,可能会产生信息爆炸的问题。 D-S证据理论优点 D-S证据理论优点:由于在证据理论中需要的先验数据比概率推理理论中的更为直观、更容易获得,再加上Dempster合成公式可以综合不同专家或数据源的知识或数据,这使得证据理论在专家系统、信息融合等领域中得到了广泛应用。 D-S证据理论适用领域:信息融合、专家系统、模式识别、情报分析、法律案件分析、多属性决策分析,等等。 D-S证据理论局限性 D-S证据理论局限性: (1)要求证据必须是独立的,而这有时不易满足; (2)证据合成规则没有非常坚固的理论支持,其合理性和有效性还存在争议; (3)计算上存在着潜在的指数爆炸问题。 D-S证据理论用于故障诊断 近些年来,基于多传感器的故障诊断技术不断发展,并且在各个领域都有应用,其最大的进步在于利用更多的故障征兆参数更加准确及时的判别故障。D-S证据理论的联合规则在上世纪70年代提出后,被广泛的应用于多传感器数据融合领域,其融合算法基本固定,但信度函数分配的获取方法不尽相同,最终融合的结果与得到的信度函数分配紧密相连。 证据理论的主要优点是理论基础较强,可以通过证据的积累,不断缩小搜索空间,而且满足比概率论更弱的公理系统,并能区分不知道和不确定两种情况。 在一定条件下,证据推理的时间复杂度可能很低。其缺点主要表现在:对证据理论的不同解释可能有不同结果,D-S合成规则的真正含义仍不清楚,组合结果有时缺乏稳定性,而且D-S证据理论有潜在复杂性,要求全集中的元素满足互斥条件,在实际系统中不宜实现。由于D-S证据理论的融合法则的固定性,信度函数分配就关系到了最后得到融合结果。信度函数分配代表着对目标模式的支持程度,具有一定的主观色彩,不同的构造方法、不同的主观判断会构造出不同的信度函数分配。 对于大型设备和高端装备这种故障样本少,工况复杂的机电装备,可以通过对以往历史运行数据的统计,拟合出典型样本分布规律,利用分布规律的密度函数建立信度函数密度以得到信度函数,获得相应的基本概率分配,进行Dempster-Shafer (D-S)证据理论融合,利用更多的故障征兆参数更加准确、及时的实时判断故障类别,通过获取客观的信度函数是正确实现目标模式判别的关键,并且能够可以减小主观判断。 对大型设备的工作状态智能维护已经逐渐成为故障诊断领域新的研究热点。对设备性能退化的评估是智能维护技术的重要组成部分,也是对设备运行状态做出合理预测的基础。一般而言,从设备性能开始退化到设备完全失效通常要经过一系列不同的性能退化状态。如果能够在设备性能退化的过程中识别出设备性能退化的程度,就可以有针对性地组织生产和设备维修,防止设备异常失效的发生。性能退化评估所针对的设备往往是布置了多测点,使用多通道监测的关键大型机械。对该类设备的性能评估,不同于基于零件的局部评估,而是需要运用信息融合技术,综合来自各零部件的状态信息,同时消除各部件信息之间冗余与矛盾,降低不确定性,从而得出符合实际的性能评价。设备的性能退化阶段通常会持续较长的时间因此在对设备的性能进行评估时可以将设备的状态划分为正常状态、初始退化状态以及深度退化状态。Dempster-Shafer证据理论是将不同观测结果的信任函数根据合成法则进行融合的一种方法。运用 D-S证据理论融合来自局部的评估信息,消除多源信息之间的数据冗余和矛盾,从而得出对整个设备的性能评估。虽然在性能退化的过程中,来自不同部件的数据对设备性能变化都会有不同程度的反映,但是对设备整体性能的评价,是各部件的运行状态的综合考虑,而部件的运行状态只是设备状态的局部体现。通过信息融合技术的设备性能退化评估方法,可以实现先局部后整体的评估思路,不仅能够准确地描述设备性能变化的过程,同时还消除各部件之间状态矛盾对设备整体评估的影响,使评估结果的可靠度得到了提高。同时,考虑引入部件重要度的概念,分清主次,提高关键部位对设备整体性能评估值的影响作用,从而能够更有针对性地为实际设备维护提供有效的参考。进行设备的故障诊断集性能退化评估需要大量的故障数据样本参与训练,但在实际应用中,很难获取到设备的各类故障以及同一故障不同严重程度的大量数据样本,或者说设备故障可以模拟,但花费的代价较为昂贵,因而存在故障数据严重缺失的问题。 D-S证据理论信息不确定性建模和信息融合 Dempster-Shafer (D-S)证据理论是一种广泛应用于信息不确定性建模和信息融合的有效方法,但也存在一些缺陷: (1)需要事先知道所有可能的假设。D-S证据理论需要考虑所有可能的假设,而这些假设需要在先验知识的基础上选择,如果假设不全面,将会影响结果的准确性。 (2)理论计算和分析较为复杂。在D-S证据理论中,在证据融合过程中需要计算大量的条件概率和组合规则,因此需要复杂的数学分析和计算,实现起来工作量很大。 (3)对证据来源的信任度要求较高。D-S证据理论要求每个证据源提供的证据可信度足够高,否则将会影响融合的结果。 (4)仅能处理有限数量的证据。由于证据组合规则的复杂性,D-S证据理论仅能处理有限数量(2的n次方减1个)的证据,随着证据数量的增加,计算量及组合规则的复杂性会增加。 基于信息融合的发电设备智能集成故障诊断 国内外在大型设备和高端装备方面做了不少研究工作,也有不少产品和技术在实际中得到了较好的应用,但是受诸多因素的影响,在智能故障诊断与检修决策支持方面尚存在许多不足。由于大型设备和高端装备这种故障样本少,本身的复杂性和运行环境的不确定性,使得传感器反映的设备信息具有不确定性,这些不确定性的存在,必然导致故障诊断准确率的降低,甚至出现漏检和误诊现象。 传统的故障诊断方法只是通过一些简单的数学判据来完成的。传统的办法解决复杂问题突出表现在对临界模糊状态的误判,其根源就在于信息量的不够或不充分。随着大型设备和高端装备趋于高参数、大容量和复杂化,传感器的类型和数目急剧增多,众多的传感器形成了传感器群,由于传感器的组合不同,提供了设备不同部位、类型的信息,传统的故障诊断方法只是对设备状态信息中的一种或几种信息进行分析,从中提取有关设备行为的特征信息。虽然利用一种信息有时可以诊断设备的故障,但在许多情况下得出的诊断结果并不可靠。只有从多方面获得关于同一对象的多维信息,并加以综合利用,才能对设备进行更可靠、更准确的诊断。 多源信息融合技术利用统计或现代数学方法,在处理大量信息、目标识别和模糊控制等方面已经取得了很大成功。多源信息融合技术的发展,为解决复杂系统故障诊断的不确定性问题提供了一条新途径。大型设备和高端装备的故障诊断技术是一门多学科交叉渗透的综合性研究课题,为了提高故障诊断的可靠性,所以有必要开展基于信息融合技术的大型设备和高端装备故障诊断的研究。 总之,Dempster-Shafer(D-S)证据理论在信息不确定性和信息融合方面具有很强的能力,但仍然存在上述的缺陷。综上所述,在应用多传感器信息融合方法进行故障诊断时,需要深入了解不同信息融合理论的原理和特点,并根据故障诊断系统具体情况进行合理应用。

故障诊断的信息融合方法

故障诊断的信息融合方法 故障诊断的信息融合方法小样本数据、数据量少,计算资源有限的多传感器数据融合问题贝叶斯定理信息融合故障诊断方法模糊信息融合故障诊断方法Dempster-Shafer (D-S)证据理论信息融合故障诊断方法 故障诊断的信息融合方法 目前,故障诊断的信息融合方法按其融合算法的不同,主要以下几种应用广泛: 贝叶斯定理信息融合故障诊断方法;模糊信息融合故障诊断方法;Dempster-Shafer (D-S)证据理论信息融合故障诊断方法;神经网络信息融合故障诊断方法;集成信息融合故障诊断方法等。基于深度学习的多传感器数据融合方法是近年来非常流行的研究方向,具有较好的融合效果和优良的适用性。其中,一种比较典型的方法是利用卷积神经网络(CNN)和循环神经网络(RNN)相结合,可以有效地解决多传感器数据融合问题。具体来讲,该方法将不同传感器采集到的数据分别送入到不同的CNN中进行特征提取,然后再将提取的特征送入到RNN中进行序列化处理,从而实现了不同数据源之间的有效融合。该方法的主要优点如下:能够有效地提供具有时间序列性质的多源数据处理能力,因此适用于视频处理、语音识别等复杂场合。可以有效处理传感器不同类型、精度、不同采样率等异构数据问题。利用深度学习算法自适应学习传感器之间的相关性,具有良好的适应性和鲁棒性。可以对多源数据进行高质量的实时反馈,并可以实现多个传感器的联合优化,提高融合结果的准确性。但是该方法需要大量数据和运算资源,并且模型较为复杂,需要经过专业研究人员的精心优化才能达到较好的融合效果。因此,选取该方法时需要评估资源和时间等方面的投入。 针对小样本数据的多传感器数据融合问题,可以考虑使用迁移学习方法,将已经训练好的模型迁移到目标任务上,以完成少量数据的训练和融合任务。以下是一种基于迁移学习的小样本多传感器数据融合方法: (1) 预训练多模态特征提取器:首先,使用大规模数据对一个多模态的特征提取器进行预训练,例如使用深度卷积神经网络(DCNN)或者多通道的自编码器(MCAE),以提取多个传感器数据的共享特征,并且尽量减少模型的过拟合。 (2)针对目标任务进行微调:将训练好的多模态特征提取器的中间层截断出来,作为目标任务的输入,然后针对小样本数据进一步微调网络的输出层,从而实现多传感器数据的融合。 (3)解决传感器之间不平衡性的问题:不同传感器之间通常存在着数据不平衡的问题,因此需要将不同传感器的数据进行平衡,例如使用过采样或欠采样等方法计算权重进行平衡。 (4)融合结果的处理和优化:多传感器数据的融合结果通常是多维度的,因此可以采用聚类或者降维等方法,将其转化为二维图像或scatter图等形式进行可视化和处理,从而更好地揭示不同传感器之间的相关性。 基于迁移学习的小样本多传感器数据融合方法主要优点是能够在非常少量的训练数据上,完成多传感器数据的融合任务,同时,能够从大规模数据中减少过拟合问题,提高模型的泛化性能。但是该方法需要针对特定的任务进行调参,并且需要大量的计算资源作为支撑。 小样本数据、数据量少,计算资源有限的多传感器数据融合问题 对于小样本数据、数据量少,计算资源有限的多传感器数据融合问题,可以考虑使用贝叶斯定理信息融合故障诊断方法;模糊信息融合故障诊断方法;Dempster-Shafer (D-S)证据理论信息融合故障诊断方法;这些方法的主要优点是:不依赖于大量的数据集合昂贵的计算资源,能够在小样本数据集上实现高精度和实时数据融合,而且灵活性较高,支持处理不同类型和不同精度的传感器数据。同时,该方法也存在一定的缺点,如需要对数据建立复杂的概率模型,对于大量、多类型传感器的研究复杂性显然会提高。 贝叶斯定理信息融合故障诊断方法 贝叶斯定理信息融合故障诊断方法,贝叶斯定理信息融合故障诊断方法是一种基于贝叶斯定理的可靠性分析方式。该方法通过融合不同来源的故障信息,利用贝叶斯定理进行概率推断,提高了故障诊断的准确性和可靠性。该方法的具体步骤如下: (1)收集不同来源的故障信息,例如传感器数据、历史故障数据、操作员报告等。 (2)建立故障模型,并对不同故障类型进行概率建模。对于每种故障类型,建立其发生的概率分布函数。 (3)利用贝叶斯定理计算某一故障类型的后验概率。根据先验概率和收集到的不同来源的信息,利用贝叶斯定理计算出该故障类型的后验概率。 (4)融合不同故障类型的后验概率。对于每种故障类型,计算其后验概率,并将不同故障类型的后验概率进行融合,得到最终的故障诊断结果。 贝叶斯定理信息融合故障诊断方法具有较高的准确性和可靠性,可以应用于各种故障诊断场景,例如机械设备故障、电力系统故障等。 模糊信息融合故障诊断方法 模糊信息融合故障诊断方法,是一种基于模糊逻辑的故障诊断方法,其主要思想是通过模糊推理将多源不确定性信息进行融合,从而提高故障诊断的准确性和可靠性。该方法的具体步骤如下: (1)收集各种传感器、仪器的故障信息。由于传感器、仪器等数据源给出的故障信息存在不确定性和模糊性,因此需要将这些信息转化为模糊信息形式。 (2)将模糊信息进行归一化处理,使其在相同的隶属度下占有相同的权重。这有利于提高信息融合过程的准确性。 (3)利用模糊综合评价方法将模糊信息进行融合。模糊综合评价方法有很多种,例如模糊加权平均法、模糊层次分析法等。 (4)对融合后的信息进行模糊推理、模糊匹配,得到故障诊断结果。模糊推理基于模糊逻辑,可以考虑多种不同的因素,包括传感器数据、恶劣环境影响、历史故障等各种因素,从而提高了诊断结果的准确性和可靠性。 模糊信息融合故障诊断方法具有较高的适应性和可靠性,可以应用于各种不同的系统和设备的故障诊断场景。同时,该方法还可以扩展到多源信息融合的情况,从而提高故障诊断的效果和可靠性。 Dempster-Shafer (D-S)证据理论信息融合故障诊断方法 Dempster-Shafer (D-S)证据理论信息融合故障诊断方法,是一种目前比较流行的故障诊断方法之一。该方法是基于贝叶斯理论和证据理论相结合,在信息融合方面具有良好的优势。该方法的具体步骤如下: (1)收集多种传感器、仪器的故障信息。这些信息在不同场景下具有不同的权重和置信度,因此需要进行权重赋值和不确定性描述。 (2)构建证据集合。对于每个故障诊断问题,需要根据不同的证据来源构建相应的证据集合。 (3)利用D-S证据理论进行信息融合。D-S证据理论可以对不同证据进行合理有效的融合,提高了诊断结果的精准度和准确性。 (4)利用贝叶斯定理进行故障诊断。通过D-S证据理论融合得到的信息,再利用贝叶斯定理进行进一步计算和推理,得到故障诊断的结果。 D-S证据理论信息融合故障诊断方法具有良好的可信度和可靠性。它可以充分利用多源信息,解决信息不确定性的问题,确保故障诊断结果的正确性。该方法适用于各种不同的系统和设备的故障诊断场景。 在现有的数据融合技术中,Dempster-Shafer (D-S)证据理论以其融合算法简单实用、简洁明了而显示其优越性,在数据融合和模式识别中得到了广泛的应用。自上世纪 70年代该理论问世以来,已经逐渐成为研究的热点问题,在一些军工领域和电子技术领域都得到了广泛应用,并且在发电厂和电力系统中也得到了应用。但是 D-S 证据理论也有其固有缺陷,这导致了其在应用中存在瓶颈。因此,解决证据理论的应用瓶颈成为了现在该领域研究的方向。

Windwos netsh端口映射

netsh介绍 Windwos下的netsh介绍可以支持tcp的端口映射转发。 之前我们了解到计算机网络Socket套接字,它作为tcp下ip传输的应用识别。 此外,需要注意的是netsh只支持内部(IP)的端口映射访问,不支持外网IP的端口映射访问 什么是端口映射? 将内网/本地端口以一台机器的网络进行传输。 应用场景如:原本有个服务程序在PC2上运行,侦听着PC2上的B端口,现在希望在不动PC2及服务程序的前提下,外界能通过PC1的A端口与PC2上服务程序通信,这时就需要用端口映射(端口转发)来解决。 netsh命令 在windows的cmd下 配置 netsh interface portproxy add v4tov4 listenaddress=本机ip listenport=本机端口 connectaddress=映射ip connectport=映射端口 删除 netsh interface portproxy delete v4tov4 listenaddress=本机ip listenport=本机端口号 查看 netsh interface portproxy show v4tov4 以上在确保端口没有被使用情况下管理员身份运行 netsh案例 在虚拟机内运行linux系统,并且已知IP信息 将虚拟机的ip设置为本机的22端口 ssh实现连接到127.0.0.1(本机测试地址) 成功!

C2360***的初始化操作由case标签跳过的解决办法

C2360***的初始化操作由case标签跳过: 原报错代码: switch (***) { case 1: int ret_1 = 1; break; case 2: int ret_2 = 2; break; default: int ret_3 = 3; break; } 方法一: case后内容加{}: 修改后代码: switch (***) { case 1: { int ret_1 = 1; break; } case 2: { int ret_2 = 2; break; } default: { int ret_3 = 3; break; } } 方法二: 在switch之外初始化(这里就不举例了)

python求遍历、最短路径、最小生成树、旅行商问题并绘图展示

一、源数据 二、python程序 (1) 数据预处理 import numpy as np import pandas as pd from scipy.sparse import coo_matrix import networkx as nx import matplotlib.pyplot as plt # 避免图片无法显示中文 plt.rcParams['font.sans-serif']=['SimHei'] # 显示所有列 pd.set_option('display.max_columns', None) pd.set_option('display.width', 1000) # 读取数据 data=pd.read_excel('data.xlsx',sheet_name='Sheet1',index_col=0) data=data.fillna(0) print('矩阵的空值以0填充:\n',data) coo=coo_matrix(np.array(data)) # 矩阵行列的索引默认从0开始改成从1开始 coo.row+=1 coo.col+=1 data=[int(i) for i in coo.data] coo_tuple=list(zip(coo.row,coo.col,data)) coo_list=[] for i in coo_tuple: coo_list.append(list(i)) # 出发点 start_node=1 # 目的地 target_node=14 # 设置各顶点坐标(只是方便绘图,并不是实际位置) pos={1:(1,8),2:(4,10),3:(11,11),4:(14,8),5:(5,7),6:(10,6),7:(3,5),8:(6,4),9:(8,4),10:(14,5),11:(2,3),12:(5,1),13:(8,1),14:(13,3)} 输出结果如下: 矩阵的空值以0填充: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1 0.

c++语法入门

命名空间 什么是命名空间? 我们先来看一个案例! 在校内,有一天,4班的小胖摔了一跤,于是a同学对b同学说:“小胖摔了一跤”。 b同学说:“哪个小胖”?a同学又说,就是4班的那个小胖啊! 注意看上面的案例,我们可以把上面的案例代入到代码中 小胖:变量 a同学:程序员 b同学:编译器 在校内:在全局范围内 4班:其实就是对应c++中的命名空间 分析:当一个项目中,我们可能要定义两个/以上的同名变量,但是如果同名对象,程序就会报错,因为编译器不会像b同学一样问a同学是哪个?它只有对与不对之分!而人与人之间可以加限定词来修饰一个变量,程序又如何限定呢?由此我们引出了命名空间! 关键字:namespace+空间名 如果要访问的话就是:空间名::变量名 namespace修饰的空间其实我们可以看成一个作用域,里面的内容的作用域被限制在了命名空间中,命名空间外除非用特定的方式,不然无法访问 这里的"::"表示的是域访问符 了解了以上内容我们写个代码试试 再看下面 三个注意事项 命名空间可以用来放函数/变量/结构体....它就是一个域,把命名空间与命名空间之外的东西隔离开来 命名空间里的变量那些都是全局的 命名空间中变量不允许重复赋值 命名空间的三种访问形式 第一种:空间名:: 变量名 这个上面介绍过,如果命名空间中的某些东西用的次数很频繁,为了方便一点我们引入第二种 第二种:using 空间名::函数名/变量名/结构体 这里的意思是展开S1命名空间中的a变量,展开后a变量就失去了命名空间的隔离效果 要注意的是,这里的using要放在定义命名空间之后,因为using展开以后是向上进行查找,如果在定义命名空间之前,则会导致using无法找到命名空间 但有时候在我们在平时练习时有些库函数要用,但一个一个展开又太麻烦了,有什么办法可以一次性展开整个命名空间吗?由此我们引入第三种访问形式 第三种:using namespace 空间名 这个的意思是展开命名空间中的所有东西,展开后整个命名空间中的内容都失去了命名空间的隔离效果 但要注意的是这个展开方式在实际工程中不推荐使用,因为当代码量过大且很多人一起操作一个项目时容易与命名空间中的某些函数重复。 在实际工程中,推荐使用第一种或第二种! 关于命名空间的一些问题 命名空间可以嵌套使用吗? 答:可以,看如下代码 命名空间如果也是一样的名字该怎么办? 答:如果命名空间是一样的名字,那么编译器就是把两个命名空间的内容合为一个! 例如 这个代码就跟如下的代码是相等的 3.命名空间和结构体有什么不同? 命名空间:是一个域,他限制了命名空间外面的访问必须要通过特定的方式 结构体:是一个自定义的类型,本质上跟int这种内置类型一样,区别就是结构体是你自己实现的类型 一个图总结命名空间,你能否全部答上来呢? std命名空间及cin&cout 简介 我们先看一段代码 我们一段一段来解释这个代码 using namespace std:由上一个命名空间章节可知,std是一个命名空间, std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中,using是展开的意思,所以这里的意思是展开命名空间中所有的定义 #include<iostream>:#include功能是包含对应的头文件/库函数,而iostream是c++中的库函数,这个库函数叫做"输入输出流",他的定义是在命名空间std的 cout:实际上是std中的一个类型为istream的全局变量,他放在std中,这里大概理解成cout就是一个控制台这样就够了,c++后期会学IO流的原理 "<<"运算符:官方名称为流插入运算符,上述代码你可以翻译为:变量x中的字符串流向cout控制台所以控制台上就打印出来了 cin:是一个类型为ostream的全局变量,这里也可以把cin理解成一个控制台,他放在std中 ">>":官方名称为流提取操作符,上述代码可以翻译为把cin这个控制台上的内容(也就是你输入的内容)流向x这个变量 endl:这个可以简单理解为是对应c++中的换行 注意:cin输入也是以空格/换行为分隔符,这一点和scanf一致 关于cin/cout有更复杂的语法(如控制浮点数输出精度,控制整形输出进制格式等 等。)这里用起来没有c语言的方便,而且也不经常用所以不加以赘述。 c++输入和输出比起c语言的有什么优势? c++的可以自动识别类型,不用再写%d,%s,%lf....,而c语言是一定要写的 一张图理清std及cin&cout的知识点,你能答出来吗? 缺省参数 初识缺省参数 理解缺省参数之前,让我们回顾一下c语言中的函数调用

K-means聚类算法的三种改进(K-means++,ISODATA,Kernel K-means)介绍与对比

目录 一、概述 二、经典K-means算法 三、K-means++算法 四、ISODATA算法 六、数据集测试 一、概述 在本篇文章中将对四种聚类算法(K-means,K-means++,ISODATA和Kernel K-means)进行详细介绍,并利用数据集来真实地反映这四种算法之间的区别。 首先需要明确的是上述四种算法都属于"硬聚类”算法,即数据集中每一个样本都是被100%确定得分到某一个类别中。与之相对的"软聚类”可以理解为每个样本是以一定的概率被分到某一个类别中。 先简要阐述下上述四种算法之间的关系,已经了解过经典K-means算法的读者应该会有所体会。没有了解过K-means的读者可以先看下面的经典K-means算法介绍再回来看这部分。 (1) K-means与K-means++:原始K-means算法最开始随机选取数据集中K个点作为聚类中心,而K-means++按照如下的思想选取K个聚类中心:假设已经选取了n个初始聚类中心(0<n<K),则在选取第n+1个聚类中心时:距离当前n个聚类中心越远的点会有更高的概率被选为第n+1个聚类中心。在选取第一个聚类中心(n=1)时同样通过随机的方法。可以说这也符合我们的直觉:聚类中心当然是互相离得越远越好。这个改进虽然直观简单,但是却非常得有效。 (2) K-means与ISODATA:ISODATA的全称是迭代自组织数据分析法。在K-means中,K的值需要预先人为地确定,并且在整个算法过程中无法更改。而当遇到高维度、海量的数据集时,人们往往很难准确地估计出K的大小。ISODATA就是针对这个问题进行了改进,它的思想也很直观:当属于某个类别的样本数过少时把这个类别去除,当属于某个类别的样本数过多、分散程度较大时把这个类别分为两个子类别。 (3) K-means与Kernel K-means:传统K-means采用欧式距离进行样本间的相似度度量,显然并不是所有的数据集都适用于这种度量方式。参照支持向量机中核函数的思想,将所有样本映射到另外一个特征空间中再进行聚类,就有可能改善聚类效果。本文不对Kernel K-means进行详细介绍。 可以看到,上述三种针对K-means的改进分别是从不同的角度出发的,因此都非常具有代表意义。目前应用广泛的应该还是K-means++算法(例如2016年底的NIPS上也有针对K-means++的改进,感兴趣的读者可以进一步学习https://papers.nips.cc/paper/6478-fast-and-provably-good-seedings-for-k-means)。 二、经典K-means算法 算法描述如下,非常清晰易懂。经典K-means算法应该是每个无监督学习教程开头都会讲的内容,故不再多费口舌说一遍了。 图1. 经典K-means算法 值得一提的是关于聚类中心数目(K值)的选取,的确存在一种可行的方法,叫做Elbow Method:通过绘制K-means代价函数与聚类数目K的关系图,选取直线拐点处的K值作为最佳的聚类中心数目。但在这边不做过多的介绍,因为上述方法中的拐点在实际情况中是很少出现的。比较提倡的做法还是从实际问题出发,人工指定比较合理的K值,通过多次随机初始化聚类中心选取比较满意的结果。 三、K-means++算法 2007年由D. Arthur等人提出的K-means++针对图1中的第一步做了改进。可以直观地将这改进理解成这K个初始聚类中心相互之间应该分得越开越好。整个算法的描述如下图所示: 图2. K-means++算法 下面结合一个简单的例子说明K-means++是如何选取初始聚类中心的。数据集中共有8个样本,分布以及对应序号如下图所示: 图3. K-means++示例 假设经过图2的步骤一后6号点被选择为第一个初始聚类中心,那在进行步骤二时每个样本的D(x)和被选择为第二个聚类中心的概率如下表所示: 其中的P(x)就是每个样本被选为下一个聚类中心的概率。最后一行的Sum是概率P(x)的累加和,用于轮盘法选择出第二个聚类中心。方法是随机产生出一个0~1之间的随机数,判断它属于哪个区间,那么该区间对应的序号就是被选择出来的第二个聚类中心了。例如1号点的区间为[0,0.2),2号点的区间为[0.2, 0.525)。 从上表可以直观的看到第二个初始聚类中心是1号,2号,3号,4号中的一个的概率为0.9。而这4个点正好是离第一个初始聚类中心6号点较远的四个点。这也验证了K-means的改进思想:即离当前已有聚类中心较远的点有更大的概率被选为下一个聚类中心。可以看到,该例的K值取2是比较合适的。当K值大于2时,每个样本会有多个距离,需要取最小的那个距离作为D(x)。 四、ISODATA算法 放在最后也是最复杂的就是ISODATA算法。正如之前所述,K-means和K-means++的聚类中心数K是固定不变的。而ISODATA算法在运行过程中能够根据各个类别的实际情况进行两种操作来调整聚类中心数K:(1)分裂操作,对应着增加聚类中心数;(2)合并操作,对应着减少聚类中心数。 下面首先给出ISODATA算法的输入(输入的数据和迭代次数不再单独介绍): [1] 预期的聚类中心数目Ko:虽然在ISODATA运行过程中聚类中心数目是可变的,但还是需要由用户指定一个参考标准。事实上,该算法的聚类中心数目变动范围也由Ko决定。具体地,最终输出的聚类中心数目范围是 [Ko/2, 2Ko]。 [2] 每个类所要求的最少样本数目Nmin:用于判断当某个类别所包含样本分散程度较大时是否可以进行分裂操作。如果分裂后会导致某个子类别所包含样本数目小于Nmin,就不会对该类别进行分裂操作。 [3] 最大方差Sigma:用于衡量某个类别中样本的分散程度。当样本的分散程度超过这个值时,则有可能进行分裂操作(注意同时需要满足[2]中所述的条件)。 [4] 两个类别对应聚类中心之间所允许最小距离dmin:如果两个类别靠得非常近(即这两个类别对应聚类中心之间的距离非常小),则需要对这两个类别进行合并操作。是否进行合并的阈值就是由dmin决定。 相信很多人看完上述输入的介绍后对ISODATA算法的流程已经有所猜测了。的确,ISODATA算法的原理非常直观,不过由于它和其他两个方法相比需要额外指定较多的参数,并且某些参数同样很难准确指定出一个较合理的值,因此ISODATA算法在实际过程中并没有K-means++受欢迎。 首先给出ISODATA算法主体部分的描述,如下图所示: 图4. ISODATA算法的主体部分 上面描述中没有说明清楚的是第5步中的分裂操作和第6步中的合并操作。下面首先介绍合并操作: 图5. ISODATA算法的合并操作 最后是ISODATA算法中的分裂操作。 图6. ISODATA算法的分裂操作 最后,针对ISODATA算法总结一下:该算法能够在聚类过程中根据各个类所包含样本的实际情况动态调整聚类中心的数目。如果某个类中样本分散程度较大(通过方差进行衡量)并且样本数量较大,则对其进行分裂操作;如果某两个类别靠得比较近(通过聚类中心的距离衡量),则对它们进行合并操作。 可能没有表述清楚的地方是ISODATA-分裂操作的第1步和第2步。同样地以图三所示数据集为例,假设最初1,2,3,4,5,6,8号被分到了同一个类中,执行第1步和第2步结果如下所示: 而在正确分类情况下(即1,2,3,4为一类;5,6,7,8为一类),方差为0.33。因此,目前的方差远大于理想的方差,ISODATA算法就很有可能对其进行分裂操作。 五、聚类算法源代码 我已经将上述三种算法整合成一个Matlab函数Clustering.m。读者可以直接使用该函数对数据集进行聚类。由于代码比较长,而且代码插件还不怎么会用,就不在文中介绍了。需要使用的读者可以点击下面的链接下载使用(欢迎Star和Fork,之后会不定期补充新的算法和优化的): GitHub - xuyxu/Clustering: Clustering / Subspace Clustering Algorithms on MATLAB

使用opencv将多帧图片合成为视频并保存

使用 cv2.VideoWriter函数,需要os库,cv2库即可,若用可自行导入 # l为帧目录名,l为一个文件夹地址,./就是当前目录 l = os.listdir('./vedio_save') #print(l) #设置帧率 fourcc = cv2.VideoWriter_fourcc(*'mp4v') #创建保存视频的对象,设置视频保存路径,编码格式,帧率,图像的宽高等 #这里的outpy.mp4v就是视频保存路径 out = cv2.VideoWriter('outpy.mp4v', cv2.VideoWriter_fourcc(*'DIVX'), 10, (width, height)) """ 注意这里的width和height一定要和图片的一致,否则保存的视频是无法播放的 """ #i是帧图片的名字(含有后缀名) for i in l: img12 = cv2.imread(savepath + i)#savepath为图片帧目录名 out.write(img12)#out为刚刚创建的保存视频的对象 out.release() 那么如何查看对应图片的大小来获取参数width和height呢 cap = cv2.VideoCapture(vedio_path) width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

老潘的部署之路2.0.1

好久没更文了,每次偷懒一段时间再更文的时候,总会发现技术发展太快了,之前写的东西有点过时了。 尤其是AI领域,变动太快,大家的风向也一直在变,前两年还在VR/XR的搞,今年因为ChatGPT的大伙,不少公司已经加大这方面的投入了。 最主要是ChatGPT在普通人中也是爆火,距我上篇文章(让ChatGPT回答大家喜闻乐见的深度学习部署问题)也就不到俩月吧,很多人真真确确感受到了ChatGPT对自己工作和效率的影响,ChatGPT也提升了我工作的效率。比如有些不熟悉的API终于不用查了,浪费时间,直接给ChatGPT一说就行。 话说回来,技术发展快,稍不留神自己用的技术就过时了(我还在用v5,别人已经V8了!)。 现在AI部署也很卷,资料繁多,开源代码也不少,学习群更是一堆。你说学这个我说学那个真有点乱,但又不想错过,所以干脆总结下,之后会找个网站放着随时更新(等我弄好语雀的图床转换就可以上传了!)。 我是卷不动了,列个清单你们卷吧! 部署之路 之前也写过不少关于部署的文章,但技术更迭很快,写出来的内容也不可能覆盖所有地方,而且很多小伙伴也会问我一些新的问题。干脆写一个比较全的总结版,挂到github和自己的博客上,之后有新想法了、新点子了,也会随时更新。大家想找学习路线看这一篇跟着学就对了。当然我也不是什么大佬,难免存在纰漏,望大家及时提醒,我好及时纠正。 尽管说是部署之路,重点是部署,但多多少少也要会一些模型训练和设计,只有理解模型的具体使用场景、使用要求,才能够使用更多方式去优化这个模型 整理了下,涉及到训练、优化、推理、部署这几块,暂时把我能想到的都列出来了,后续也会不断更新(立个flag): 首先要有模型模型转换那些事儿模型优化那些事儿了解很多推理框架开始部署吧!高性能计算/AI编译器 本文也仅仅是总结的作用,尽可能把东西都列全。每部分的细节,会总结相关文章再展开描述,可能是我写的,也可能是其他人优秀的文章。 附上之前的两篇文章: 老潘的思考(AI部署、方向、就业)老潘的AI部署以及工业落地学习之路 学习建议 诚然,我们想学的东西很多。但很多方向我们不可能每个都精通、像单独领域中的大佬一样,因为我们每个人的时间精力问题,我们可以雨露均沾,但是不可能样样大神,学的再多,也是沧海一粟。 于是最好的办法就是抓重点学习,比如: 一些特别基础的知识,其他知识点都依赖它,这种基础是必须要学的,也是性价比最高的项目中的要学习的一些知识点,自己之前没有接触过的,需要边学边做,这种从0到1是收获最快的一些JD中的岗位需求,找人自己感兴趣并且想转方向的,有心去参考下 比如商汤的2023年HPC团队招聘计划,一些岗位需求也可以参照学习: 很多需要学习的点,也一一列出来了,又或者你想学习高性能计算: 这些JD已经把需要你的,你需要的技能点都列出来了,自己按需点满即可。 学习是自己的事儿,自己想干啥想学啥,最好有个明确的目标,不要瞎学不要浪费时间。 学习FAQ 如果想做模型压缩、量化这些,需要先做算法相关的吗 肯定懂算法是最好的,毕竟模型压缩和量化是对模型做事情,搞算法的已经提前了解了模型的结构、op特点(训练时和推理时)、op种类、特殊结构等等。模型压缩、量化或者转换的时候都要经过这些op,难免会遇到很多问题,知道op细节对于解决这个问题肯定是有帮助的(比如BN在训练时和推理时表现不一样,转化的时候就需要注意),有很多坑。 不过都是可以慢慢学的,转换的时候再看也行,遇到不会的算子再去查阅。 如果想搞硬件需要补哪些基础 这个比较泛了,硬件现在分的挺多,单片机(stm32)、嵌入式板子(arm、jetson)、FPGA都是三个不同的路线,三个的知识栈也都不同。如果不确定哪个的话,可以先学习基本的硬件知识,从计算机组成原理开始看,可以先看简单的单片机(51、stm32),cpu内存寄存器外围接口都看看,同时可以看计算机组成原理这本书,熟悉计算机的结构,然后尝试写一些深度学习模型的算子,把深度学习在这些板子上跑起来,图像编码解码、传到模型中,获取结果,都自己做一遍,遇到不会de就看就学。 首先要有模型 搞深度学习部署最重要的当然是模型,大部分的场景都是靠模型和算法共同实现的,这里的算法又包含逻辑部分(俗称if-else)、算法部分(各种各样与场景相关的算法,比如滤波算法blabla等)、图像处理部分(我这里主要指的是视觉场景,比如二值化、最大外接矩形等等)等等。当然这是我的经验,可能其他场景有不同的组合。 模型当然是最重要的,因为模型效果或者速度不行的话,用传统图像方法或者逻辑(if-else)捞case是比较困难的,在某些场景中模型可以直击要害,抓需求重点去学习。 举个极端的例子,比如你要识别一个人的动作,这个人跳起来然后落下来算一个,也就是无绳跳跃。如果训练一个检测模型,首先检测这个人,然后分两类,跳起来算一类,落下来算一类,产出一个分两类的检测模型,那这个问题就好解多了,逻辑只需要根据模型结果来判断即可。但如果没有这个模型的话, 你可能会通过检测人的模型+姿态检测+时序算法来判断这个人到底有没有跳跃一次了。 知道模型的重要性了,关于怎么收集数据怎么训练这里姑且先不谈了。涉及到部署的话,模型就不能只看精度了,了解些部署的算法工程师在设计模型的时候通常也会注意这一点,**实用好用(好训练好部署,比如YOLOv5、V7)**才是重点。 实际应用中的模型,往往有以下一些要求: 模型精度达到要求,当然这是前提模型大小符合要求,部署的场景能放得下这个模型的权重信息模型op符合要求,部署的平台库可以支持这个模型的op模型的速度符合要求,这时候需要模型的op和设计共同决定 模型的设计需要考虑计算量、参数量、访存量、内存占用等等条件。可以参考这篇:深度学习模型大小与模型推理速度的探讨,内容很详实! 相关参考: 深度学习模型大小与模型推理速度的探讨 自己造模型 有了想法,有了目标,有了使用场景,那就训练一个模型吧! 如何设计模型 关于设计模型的思路,大部分人会直接参考GITHUB上找开源的模型结构,这个没问题,根据场景选对就行: 首先确定任务类型,分类、检测、分割、识别、NLP根据任务特点选择(数据集分布,数据特点)移动端和桌面端考虑的情况不同,比如移动端更看重计算量,而桌面端更看重访存。两个平台都有能用的backbone待补充 如果自己对模型优化也有特定了解的话,可以针对特定平台设计一些对硬件友好的结构(这里举个例子,比如重参数化的RepVGG),一般来说大公司会有专门的高性能计算工程师和算法工程师对齐,当然小公司的话,都要干了555。 模型结构 根据经验和理论知识来设计模型的结构(比如dcn系列、比如senet中的se模块、yolo中的fcos模块);根据任务来设计模型;NAS搜索模型; 有很多优秀的模型块结构,属于即插即用的那种,这里收集一些常见的: DCNv2系列,已经比较成熟,DCNv3(InternImage)重参数化结构(RepVGG)待补充 训练框架 训练框架这里指的不是Pytorch或者TensorFlow,而是类似于mmlab中各种任务框架,比如mmyolo、mmdetection这种的。 你如果想自己训练一个检测模型,大概是要自己基于Pytorch去重新实现一些方法:数据处理、模型搭建、训练优化器、debug可视化等等。比较烦而且浪费时间,如果有这些已经完善的轮子你自己使用,个人觉着是比较舒服的,但是当然有优劣: 自己实现可能自定义性更好,但是比较费时间去造轮子使用轮子,上手轮子可能也比较花时间,尤其是比较重的轮子,上手周期也挺长使用现有的轮子,这个轮子不断更新的话,你也可以享受到这个新功能或者实用的功能,不用你自己实现或者移植 一些大的轮子可以参考: https://github.com/facebookresearch/detectron2https://github.com/open-mmlab/mmyolo/ 一些小的轮子可以参考: https://github.com/xingyizhou/CenterNethttps://github.com/open-mmlab/mmyolo/tree/damo-yolo 我个人之前使用的是detectron2,但是官方貌似不怎么维护了,因为我打算增加一些新功能,但是没有时间搞。后来发现mmlab2.0出来了,之前那会使用过mmdet1.0版本,感觉封装的太深了,训练的模型导出很费劲儿就没怎么用。后来2.0简单看了看上手稍微简单了些,打算切到mmlab系列,主要原因还是支持比较丰富,各种pr很多,有的模型不需要你移植就已经有人移过去了,省去很多造轮子的时间。 后面我也会比较下detectron2和mmdet2.0这俩框架。 导出模型 自己的模型在训练完毕后,如果不是直接在训练框架中推理(好处就是模型精度和你eval的时候一致,而且不需要花时间转模型的格式,坏处就是模型运行速度不能保证,而且python环境比较依赖python解释器),大部分是要导出的。 导出的格式有很多,我也不一一列了,可以参考Netron模型Viewer的介绍: 导出模型也就是模型转换,只不过因为是自己训练的,一般会从自己训练框架为起点进行转换,可以避免一些中间转换格式。 比如我经常使用Pytorch,如果训练完模型后,需要转为TensorRT的模型,正常来说可能会Pytorch->ONNX->TensorRT。但是这样会经过ONNX这个中间模型结构,可能会对最终模型精度产生不确定性,我可能也会直接从Pytorch转为TensorRT: torch2trttorch.fx2trttorchscript2trt 因为Pytorch支持比较好,所以能这样搞,支持不好的,可能还要走ONNX这个路子。 nas搜索 nas就是搜索一个在你平台上一个速度最优的模型结构,目前我只了解过DAMO相关的一个搜索,还未深度尝试: DAMO-backbone的搜索指南 https://github.

STM32-SPI驱动7针脚OLED,显示中文,字符串,数字,图片。

STM32-SPI驱动7针脚OLED,显示中文,数字,图片。 本文为STM32f103rct6利用SPI驱动7针脚oled模块显示中文,数字和图片。 1,如图,为本次驱动的oled模块 2,引脚定义: GND--电源地; VCC--电源正极(3.3v~5v); D0--时钟线; D1--数据线; RES--复位线; DC--数据/命令控制线; CS--片选线,低电平有效,如果不用,必须接地; 首先我们自己从淘宝或者其他渠道购买的OLED屏幕,都是先找到OLED需要的屏幕资料和驱动代码,如果没有可以找商家要,我们本次驱动的oled为下图的像素为128x64的oled模块。X轴的范围是0-127,单位是列,Y轴的范围是0-63,单位是行。 3,OLED屏幕接线: // OLED模块 STM32单片机 VCC 接 DC 5V/3.3V //OLED屏电源正 GND 接 GND //OLED屏电源地 D1 接 PB15 //OLED屏SPI写信号 CS 接 PB11 //OLED屏片选控制信号 RES 接 PB12 //OLED屏复位控制信号 DC 接 PB10 //OLED屏数据/命令选择控制信号 D0 接 PB13 //OLED屏SPI时钟信号 因为D1对应的是数据线,我们可以选择主入从出(MISO)或者主出从入(MISI).这里我们选用的是主出从入(MISI)。 4.代码的移植和修改 bmp.h是图片的代码,oled.c是驱动代码,oled.h是引脚代码,oledfont.h是一些字库和汉字代码 这个时候我们初始化引脚。 1,显示数字(GUI_ShowNum) * @函数: 显示编号 x: 数字的开始坐标x Y: 数字的起始Y坐标 num: (0 ~ 4294967295) Len: 显示号的长度 大小: 显示编号的大小 模式: 0-白底黑字,1-黑底白字 void GUI_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 Size,u8 mode) { u8 t,temp; u8 enshow=0,csize; if(Size == 16) { csize = Size/2; } else if(Size == 8) { csize = Size/2+2; } else { return; } for(t=0;t<len;t++) { temp=(num/mypow(10,len-t-1))%10; if(enshow==0&&t<(len-1)) { if(temp==0) { GUI_ShowChar(x+csize*t,y,' ',Size,mode); continue; }else enshow=1; } GUI_ShowChar(x+csize*t,y,temp+'0',Size,mode); } }

GitHub提交时出现Host key verification failed无法读取远程仓库的解决方案

tags: Git Debug Tips 问题 今天提交代码时候发现有这样一个问题: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdropping on you right now (man-in-the-middle attack)! It is also possible that a host key has just been changed. The fingerprint for the RSA key sent by the remote host is SHA256:uNiVztksCsDhcc0u9e8BujQXVUpKZIDTMczCvj3tD2s. Please contact your system administrator. Add correct host key in ~/.

CentOS yum使用

朋友们好啊,欢迎来看我发的文章。 介绍 yum可以说是Linux下的软件管家 介绍 yum是linux快捷安装软件的程序,就如同widnows下的软件管家,可以帮你安装所需要的软件,而不是去网站/官网下载。 除了yum类似还有rpm,但rpm不会去自动解决依赖库的问题。 在Linux系统上,一个软件所需要依赖库是非常多的,并且可能需要配置好相关的环境,而yum很好的解决这一点。 YUM安装 在没有YUM环境下的系统,可以使用下面命令进行 apt-get install build-essental sudo apt-get install yum YUM源 yum的有官方源和三方源 源就好比腾讯、360的不同的软件管家平台一样,你要什么软件得从上面获取,至此有一个好的源是非常重要的。 官方源:centos、epel 第三源:阿里云镜像源、华为云镜像源、清华大学镜像源、网易163源等 /etc//yum.repos.d/ 它是作为yum源目录文件 备份源 在更换源建议备份下,在/etc//yum.repos.d/ 目录下,给它更改下名字: mv CentOS-Base.repo CentOS-Base.repo.back 下载新的YUM源 wget http://mirrors.163.com/.help/CentOS7-Base-163.repo 基础使用YUM 1.安装程序 yun install 软件名 如:yum install java 2.更新程序 yum update 软件名 如:yum update java 详细使用YUM yum参数命令-h显示帮助信息install 安装软件-y默认都使用Yesupdata 更新软件-c指定配置文件check-update 检查是否有可用更新-q 安静模式安装remove 删除软件包-v 详细模式list显示软件信息-d 设置错误等级search 检查软件包信息-r最大化等待时间info 显示指定软件包描述-c完全从缓存中运行,不更新clean清理过期缓存-c完全从缓存中运行,不更新localinstall显示本地软件包deplist 显示软件依赖 同步更新:https://blog.go176.net/post-7.html

机器学习----线性回归

第一关:简单线性回归与多元线性回归 1、下面属于多元线性回归的是? A、 求得正方形面积与对角线之间的关系。 B、 建立股票价格与成交量、换手率等因素之间的线性关系。 C、 建立西瓜价格与西瓜大小、西瓜产地、甜度等因素之间的线性关系。 D、 建立西瓜书销量与时间之间的线性关系。 2、若线性回归方程得到多个解,下面哪些方法能够解决此问题? A、 获取更多的训练样本 B、 选取样本有效的特征,使样本数量大于特征数 C、 加入正则化项 D、 不考虑偏置项b 3、下列关于线性回归分析中的残差(预测值减去真实值)说法正确的是? A、 残差均值总是为零 B、 残差均值总是小于零 C、 残差均值总是大于零 D、 以上说法都不对 答案:1.BC 2.ABC 3.A 第2关:线性回归的正规方程解 #encoding=utf8 import numpy as np def mse_score(y_predict,y_test): ''' input:y_predict(ndarray):预测值 y_test(ndarray):真实值 ouput:mse(float):mse损失函数值 ''' #********* Begin *********# mse=np.mean((y_predict-y_test)/2) #********* End *********# return mse class LinearRegression : def __init__(self): '''初始化线性回归模型''' self.theta = None def fit_normal(self,train_data,train_label): ''' input:train_data(ndarray):训练样本 train_label(ndarray):训练标签 ''' #********* Begin *********# x = np.

非常想学黑客技术,但是却又不知道如何入门?看这里就够了

黑客攻防是一个极具魅力的技术领域,但成为一名黑客毫无疑问也并不容易。你必须拥有对新技术的好奇心和积极的学习态度,具备很深的计算机系统、编程语言和操作系统知识,并乐意不断地去学习和进步。 如果你想成为一名优秀的黑客,下面是12种最重要的基础条件,请认真阅读: 第一点:了解黑客的思维方式 我们生活中用到的网站、软件等,都是由程序员编写的代码构成的。 这些代码在设计的过程中,都是基于一种正向的逻辑进行的,为了实现某个目的,完成某个操作的流程或数据传输逻辑。 而黑客的思维是逆向的,他们会去分析目前这个操作流程或数据传输逻辑中,是否存在一些验证不严谨或者隐秘信息被泄露的风险,并加以利用,从而绕过正常的操作逻辑达到未授权访问或操作的能力。 通俗点说,程序员是造房子的,而黑客则是看看房子是不是哪里漏了个风,缺了个口。翻进去为所欲为;有的甚至直接将房子拆了。 第二点:学习一门编程语言 黑客的武器也是代码。想要成为黑客,首先要学会一门黑客需要的编程语言。对于没有代码经验的小白,可以从python、PHP或C学起。 第三点:学习网络安全基础知识 前面有提到,黑客其实就是安全工程师。安全工程师也分为几类,每一类的学习路径也有所不同。 以Web安全举例。 首先要对Web技术有所了解,比如你想破解一个网站,首先你得会搭建一个网站。所以需要掌握:通信协议,如TCP、HTTP,操作系统,如Linux、Windows、服务架设:Apache、Nginx等,数据库:MySQL或Oracle,以及编程语言,包括前端和后端语言。 接着对于Web安全技术也需要掌握:后端安全如SQL注入、文件上传、Webshell(木马)等,前端安全如XSS跨站脚本攻击、CSRF跨站请求伪造等。 黑客所涉及到的基础技能点是很多的,大部分人抱着三分钟热度,学着学着就放弃了。所以我们在学习过程中应该先去梳理一份知识图谱,然后进行系统性学习。 第四点:实战操作 如果你成功通过第三点,那么恭喜,你已经是一个初级小黑客了。接下来不如上手实践一下,比如SRC漏洞挖掘,WIFI网络破解,配套靶场练习等等。当然,你也可以尝试破解一下你女朋友的QQ密码。 第五点:懂法律,懂法律,懂法律! 《网络安全法》 第二十七条:任何个人和组织不得从事非法侵入他人网络、干扰他人网络正常功能、窃取网络数据等危害网络安全的活动;不得提供专门用于从事侵入网络、干扰网络正常功能及防护措施、窃取网络数据等危害网络安全活动的程序、工具;明知他人从事危害网络安全的活动的,不得为其提供技术支持、广告推广、支付结算等帮助。 《网络安全法》第四十四条: 任何个人和组织不得窃取或者以其他非法方式获取个人信息,不得非法出售或者非法向他人提供个人信息。 《刑法》 第二百八十六条:违反国家规定,对计算机信息系统功能进行删除、修改、增加、干扰,造成计算机信息系统不能正常运行,后果严重的,处五年以下有期徒刑或者拘役;后果特别严重的,处五年以上有期徒刑。 不谈技术,单谈品质。恶意侵入其他电脑的系统作出破坏的“Cracker”是非常可耻的。互联网不是法外之地,我向大家科普黑客的知识也绝不是想去助长某些朋友的不良心态。 我觉得作为一个技术人员了解和学习黑客知识是必要的,因为这样才能在日常工作中应对安全风险,在较高的安全意识上完成编程和运维工作;当然,如果你能成功掌握了一些黑客原理和技术,当你遇到攻击时,也不仅仅是严防死守,而是抓住内鬼,反将一军。 技术本身并不罪恶,滥用技术才会导致罪恶! 第六点:黑客学习资源分享 需要这份学习资料的同学看文章结尾 自学网络安全方向会遇到哪些问题? 1.打基础的时间长 学基础花费了很长的时间,光学语言都有好几门,有的人会止步于学习linux系统及命令的路上,更多的人会停在学习语言上面; 2.知识点掌握的不够清楚 对于网络安全基础内容,很多人不清楚到底需要学到什么程度,导致在基础上花费了太多的时间;很多同学,买了HTML,PHP,数据库,计算机网络 等书籍,每本还很厚,很多写得也很深,却发现越学越没自信,别人学个PHP或者数据库就可以找到工作,而网络安全要学这么多,越来越怀疑自己到底是不是选错了方向; 3.知识点不清楚重点 很多同学花费了很大精力学完了基础内容,但是发现很多知识和后续网络安全关联不大,没有分清重点,浪费了很多的时间; 4.知识点学习不够系统 看到很多同学在b站找了好多学习视频,也到别的平台购买了一些小课,百度云盘上也有1-2T的学习资料和视频内容,但每学完一类都需要花费不少的时间,且内容很多有重复性,学完SQL注入后,后面又看到另一家讲这个SQL注入,还不错,又会去学习一遍,发现学完所有web漏洞原理后,自己还是不太确定自己是否把Web漏洞这块的知识点学全了没有,导致自己到底学没学完都不知道; 5.自己解决问题的能力不足 对于初学者来说,很多人都会自己搭建一些靶场,但是由于配置环境的原因,耽误的时间会很多,尤其对于初学者碰到连续3个问题无法解决的时候,很容易放弃;对于一些动手能力较差的同学,这块可能会直接影响到继续学习的信心; 6.实战水平不足 对于学网络安全,渗透测试方向的技术,其实很大程度上学习的就是“黑客”技术,通过学习怎么进攻和入侵,才能够更清楚系统和应用怎么去防御;而这块也恰恰是网络安全的核心,如果光有理论,实战经验少,也是较难去就业。在平时学习中,除了可以搭建一些开源的靶场用于练习,最好还是要有真实漏洞组成的靶场用于学习,当然也可以去SRC平台去渗透测试一些真实网站(一定要获得授权才可以渗透真实网站),但是难度发现又比较大,很多初学者会丧失信心,怀疑自己的能力; 7.内网的学习困难比较大 Web渗透这块的资料在互联网各个平台到处都是,学习起来相对较为轻松,但是内网这块的资料在互联网平台上面相对较少,能够借鉴的资料不多,另外也需要有相应的靶场配合练习,才能有技术上的提高和经验的积累,学习难度会比较大。 我经常会看到这一类的问题: 学习XXX知识没效果; 学习XXX技能没方向; 学习XXX没办法入门; 给大家一个忠告,如果你完全没有基础的话,前期最好不要盲目去找资料学习,因为大部分人把资料收集好之后,基本上都是放在收藏夹吃灰,同时资料收集的多了,学起来就会迷茫,也会让自己很有压力。 磨刀不误砍柴工,如果你是准备自学的话,要分步骤去进行: 第一步:搭建自学知识框架,具体怎么搭建学习框架,在后面我会讲; 第二步:按照学习框架给自己定制阶段性的学习计划和目标,最好是按周自我反馈和调整; 第三步:针对每周的学习计划寻找合适的自学资源,注意,只找当前需要的,不要贪多 第四步:找几个懂得人,和他们处理好关系,后面学习过程中遇到问题还能有人给你解答; 这些都要一步一步来,不要想着一口气吃成一个大胖子。 搭建学习框架也是有诀窍的,比如我常用的三种方式: 和牛人成为朋友,身边的朋友或公司的同事都可以,但要注意,记得请人家吃饭联络好感情,不然到关键时刻,很少有人会去帮你; 从各个博客网站上面搜索想了解的知识点路线图,然后找高赞的博文,基本上不会差,但要注意辨别真伪; 多找几个培训机构,看他们整理的课程大纲是什么样的,涉及哪些知识点,然后做归类汇总,具体的我就不说了,免得让大家认为我在给培训机构打广告; 废话不多说,先上一张图镇楼,看看网络安全有哪些方向,它们之间有什么关系和区别,各自需要学习哪些东西:

Android PackageManagerService总结(四) APK安装流程

一. 概述 PackageManagerService(简称PKMS),是Android系统中核心服务之一,管理着所有与package相关的工作,常见的比如安装、卸载应用, 信息查询等工作, 主要完成以下核心功能 1. 解析AndroidManifest.xml清单文件,解析清单文件中的所有节点信息 2. 扫描本地文件,主要针对apk,主要是系统应用、本地安装应用等。 3. 管理本地apk,主要包括安装、删除等等 4. 管理设备上安装的所有应用程序,并在系统启动时加载应用程序 5. 根据请求的Intent匹配到对应的Activity、Provider、Service,提供包含包名和Component的信息对象 6. 调用需要权限的系统函数时,检查程序是否具备相应权限从而保证系统安全 7. 提供应用程序的安装、卸载的接口 本篇文章重点介绍一下apk安装流程 二. 安装apk的方式 Android应用安装有如下四种方式: 1. 系统应用和预制应用安装――开机时完成,没有安装界面,在PKMS的构造函数中完成安装; 2. 网络下载应用安装――通过应用商店应用完成,调用PackageManager.installPackages(),有安装界面; 3. ADB工具安装――没有安装界面,它通过启动pm脚本的形式,然后调用com.android.commands.pm.Pm类,之后调用到PKMS.installStage()完成安装; 4. 第三方应用安装――通过SD卡里的APK文件安装,有安装界面,由packageinstaller.apk应用处理安装及卸载过程的界面。 上述几种方式均通过PackageInstallObserver来监听安装是否成功 三. apk文件结构 生成的APK文件本质还是一个zip文件,只不过被Google强行修改了一下后缀名称而已。所以我们将APK的后缀修改成.zip就可以查看其包含的内容了. 1)主要有7部分组成 (下图来源于其他作者博客: Android apk结构分析 ) 2)META-INF目录下3个重要文件 3)res目录下的文件说明 细节说明: META-INF:关于签名的信息存放,应用安装验证签名的时候会验证该文件里面的信息, 里面的资源文件,是被编译过的。raw和图片是保持原样的,但是其他的文件会被编译成二进制文件。 res: 这里面的资源是不经过编译原样打包进来的 AndroidManifest.xml:程序全局配置文件。该文件是每个应用程序都必须定义和包含的文件,它描述了应用程序的名字、版本、权限、引用的库文件等等信息。 classes.dex:Dalvik字节码文件,Android会将所有的class文件全部放到这一个文件里。 resources.arsc:编译后的二进制资源文件,保存资源文件的索引,由aapt生成 lib: 如果存在的话,存放的是ndk编出来的so库 四. apk安装过程 这里我们主要来讲解下载APK后,点击进行安装的过程, 整体上来说,大致分为4个步骤: 1. 将APK的信息通过IO流的形式写入到PackageInstaller.Session中; 2. 调用PackageInstaller.Session的commit方法,将APK的信息交由PKMS处理; 3. 拷贝APK; 4. 安装apk. 整个过程涉及到3个跨进程通信的Binder 客户端跨进程通信AIDL文件 服务端 PackageManager(抽象类) 它的实现类:ApplicationPackageManager

python 时间time()及日期datetime()函数

Python 程序能用很多方式处理日期和时间,转换日期格式是一个常见的功能。 Python 提供了一个 time 、datetime和 calendar 模块可以用于格式化日期和时间。 时间间隔是以秒为单位的浮点小数。 每个时间戳都以自从1970年1月1日午夜(历元)经过了多长时间来表示。 1、python中时间日期格式化符号 %y 两位数的年份表示(00-99)%Y 四位数的年份表示(000-9999)%m 月份(01-12)%d 月内中的一天(0-31)%H 24小时制小时数(0-23)%I 12小时制小时数(01-12)%M 分钟数(00-59)%S 秒(00-59)%a 本地简化星期名称%A 本地完整星期名称%b 本地简化的月份名称%B 本地完整的月份名称%c 本地相应的日期表示和时间表示%j 年内的一天(001-366)%p 本地A.M.或P.M.的等价符%U 一年中的星期数(00-53)星期天为星期的开始%w 星期(0-6),星期天为星期的开始%W 一年中的星期数(00-53)星期一为星期的开始%x 本地相应的日期表示%X 本地相应的时间表示%Z 当前时区的名称%% %号本身 2、time()模块使用 2.1 获取当前时间戳 Python 的 time 模块下有很多函数可以转换常见日期格式。如函数time.time()用于获取当前时间戳, 如下实例: import time # 引入time模块 c_time = time.time() print('当前时间戳为:', c_time) 运行结果: 2.2 获取当前本地时间 从返回浮点数的时间戳方式向时间元组转换,只要将浮点数传递给如localtime之类的函数。 示例代码: import time # 引入time模块 c_time = time.localtime(time.time()) print('当前本地时间为:', c_time) 运行结果: 2.3 获取格式化的时间 可以根据需求选取各种格式,但是最简单的获取可读的时间模式的函数是asctime().

Python爬虫:HTML网页解析方法小结

要理解python是如何解析网页的,首先要理解什么是网页解析器。 简单的说就是用来解析html网页的工具,准确的说:它是一个HTML网页信息提取工具,就是从html网页中解析提取出“我们需要的有价值的数据”或者“新的URL链接”的工具。 解析HTML: 层次化的数据有多个解析HTML的第三方库,例如:LXML,BeautifulSoup,HTMLParser等等。解析HTML面临的问题:没有统一的标准、很多网页并没有遵循HTML文档 我们知道爬虫的原理无非是把目标网址的内容下载下来存储到内存中,这个时候它的内容其实是一堆HTML,然后再对这些HTML内容进行解析,按照自己的想法提取出想要的数据。 今天主要讲讲Python中解析网页HTML内容的四种方法: BeautifulSouplxml的XPathrequests-html正则表达式 其中BeautifulSoup和XPath是python中解析网页常用的两个库,对于新手来说是利器,零基础小白建议先打好Python基础再去上手爬虫会容易一些。 **“零基础如何学Python”**在csdn看到过一篇比较好的文章,讲的很实用,大家伙可以移步去看看,链接分享在下方。 零基础学Python有什么建议? 1、BeautifulSoup 大名鼎鼎的BeautifulSoup库,在Pyhton的HTML解析库里属于重量级的库。 安装途径: pip install beautifulsoup4 解析的第一步,是构建一个BeautifulSoup对象。 >>> from bs4 import BeautifulSoup >>> soup = BeautifulSoup(html_doc, 'html.parser') 第二个参数表示解析器,BeautifulSoup支持以下多种解释器: BeautifulSoup对应一个HTML/XML文档的全部内容; BeautifulSoup类的基本元素 任何存在于HTML语法中的标签都可以用soup.访问获得,当HTML文档中存在多个相同对应内容时,soup.返回第一个。 每个都有自己的名字,通过.name获取,字符串类型 Tag的attrs:一个可以有0或多个属性,字典类型 NavigableString可以跨越多个层次 1)访问标签 通过点号操作符,可以直接访问文档中的特定标签,示例: >>> soup = BeautifulSoup(html_doc, 'lxml') >>> soup.head <head><title>The Dormouse's story</title></head> >>> soup.head.title <title>The Dormouse's story</title> >>> soup.a <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a> 这样的方式每次只会返回文档中的第一个标签,对于多个标签,则通过find_all方法返回多个标签构成的列表。 >>> soup.find_all('a') [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="

Python 爬虫:Header 的设置

在编写爬虫的过程中,有些网站会设置反爬机制,对不是来源于浏览器的访问进行拒绝,此时我们会收到 403 错误响应码,或者收到“抱歉,无法访问“等字眼,这就需要在爬虫程序中修改请求的 headers 伪装浏览器访问,从而绕开网站的反爬机制获取正确的页面。 一、了解 requests 中 get 与 post 的 headers 参数 requests 发送的请求所带的请求头中 User-Agent 会标识为 python 程序发送的请求,如下所示: import requests url = 'https://httpbin.org/headers' response = requests.get(url) if response.status_code == 200: print(response.text) 在上面的代码中,倒数第二行是对服务器返回的状态代码进行判断。这里的200就是请求成功的反馈。所有的状态代码的取值一般在 100-599 之间,超出这个范围的响应状态码就不是标准的状态响应码了。[所有的状态码]可以分成 5类: 100–199:信息反馈(Informational responses);200–299:成功反馈(Successful responses),上面的代码的 200 status code就属于这里;300–399:重定向消息(Redirection messages);400–499:客户端错误响应(Client error responses),这个区间包含了我们常见的 403 和 404 错误响应码500–599:服务器错误响应(Server error responses) 返回结果: 注:[https://httpbin.org]是一个开源的,用于测试网页请求的网站,比如上面的/headers的链接,将会返回所发送请求的请求头。详情请参考其官网。 User-Agent: 用户代理(英语:User Agent)指的是代表用户行为的软件代理程序所提供的对自己的一个标识符。用于标识浏览器类型及版本、操作系统及版本、浏览器内核、等信息的标识。详情见维基百科词条:[User agent] 如上图所示,如果我们直接用 request 包,上来就调用 get 或者 post 方法就是干,对方的服务器会根据我们发送的**““User-Agent”: “python-requests/2.25.1””**了解到,你是用 python 调用的 request 包来访问他们的服务器的。

k8s管理工具

k8s管理工具 文章目录 k8s管理工具Kuboard(💕17.3k)KubeOperator(💕4.6k)Rainbond(💕3.8k)KubeSphere(💕12k) Kuboard(💕17.3k) Kuboard 是一款免费的 Kubernetes 管理工具,提供了丰富的功能,结合已有或新建的代码仓库、镜像仓库、CI/CD工具等,可以便捷的搭建一个生产可用的 Kubernetes 容器云平台,轻松管理和运行云原生应用。 KubeOperator(💕4.6k) KubeOperator 是一个开源的轻量级 Kubernetes 发行版,专注于帮助企业规划、部署和运营生产级别的 Kubernetes 集群。 Rainbond(💕3.8k) Rainbond 是一个云原生多云应用管理平台,使用简单,不需要懂容器、Kubernetes和底层复杂技术,支持管理多个Kubernetes集群,和管理企业应用全生命周期。主要功能包括应用开发环境、应用市场、微服务架构、应用交付、应用运维、应用级多云管理等。 KubeSphere(💕12k) KubeSphere 是以 Kubernetes 为内核的云原生分布式操作系统,它的架构可以非常方便地使第三方应用与云原生生态组件进行即插即用(plug-and-play)的集成,支持云原生应用在多云与多集群的统一分发和运维管理。

【MySQL】WITH CHECK OPTION的用法

系列文章 C#底层库–MySQL脚本自动构建类(insert、update语句生成) 本文链接:https://blog.csdn.net/youcheng_ge/article/details/129179216 C#底层库–MySQL数据库访问操作辅助类(推荐阅读) 本文链接:https://blog.csdn.net/youcheng_ge/article/details/126886379 C#底层库–SQLiteHelper访问操作辅助类 本文链接:https://blog.csdn.net/youcheng_ge/article/details/123666958 【提升编程效率】Excel数据批量导入工具 本文链接:https://blog.csdn.net/youcheng_ge/article/details/126427323 【Oracle】数据库服务器限制ip访问 本文链接:https://blog.csdn.net/youcheng_ge/article/details/122220930 【Oracle】Excel导入数据教程 本文链接:https://blog.csdn.net/youcheng_ge/article/details/118722756 【Oracle】数据库还原教程_数据泵 本文链接:https://blog.csdn.net/youcheng_ge/article/details/118054855 【SQL】如何查询表字段并识别主键 本文链接:https://blog.csdn.net/youcheng_ge/article/details/110820405 SQL outer apply的用法 本文链接:https://blog.csdn.net/youcheng_ge/article/details/79903489 MySQL安装教程(详细) 本文链接:https://blog.csdn.net/youcheng_ge/article/details/126037520 MySQL卸载教程(详细) 本文链接:https://blog.csdn.net/youcheng_ge/article/details/129279265 MySQL分类汇总(group by…with rollup),如何显示“总计”字段? 本文链接:https://blog.csdn.net/youcheng_ge/article/details/128217837 MySQL WITH CHECK OPTION的用法 本文链接:https://blog.csdn.net/youcheng_ge/article/details/128147196 MySQL 使用存储过程插入千万级数据如何提升效率? 本文链接:https://blog.csdn.net/youcheng_ge/article/details/77728189 MySQL 数据库表行列转置的实现 本文链接:https://blog.csdn.net/youcheng_ge/article/details/77625052 文章目录 系列文章前言一、技术介绍二、测试用例2.1 数据准备2.2 数据查询2.3 修改视图,加上WITH CHECK OPTION2.4 再次进行数据插入2.5 再次查询数据 三、用法总结 前言 本专栏为【数据库】,主要介绍SQL的功能与特点、SQL数据定义语言(表、视图、索引、约束)、SQL数据操作语言(数据检索、数据插入、数据删除、数据更新)、创建与删除触发器、SQL数据控制语言(安全性和授权、事务处理)以及嵌入式SQL。 如果你对本专辑感兴趣,持续关注吧。大家有任何问题,也可以评论区反馈,私信我。 一、技术介绍 视图的定义: 视图不是真实存在的基本表,而是一个虚拟表 视图的作用: 1、可以使视图集中数据、简化和定制不同用户对数据库的不同数据要求 2、使用视图可以屏蔽数据的复杂性,用户不必了解数据库的结构,就可以方便地使用和管理数据,简化数据权限管理和重新组织数据以便输出到其他应用程序中。 3、视图可以使用户只关心他感兴趣的某些特定数据和所负责的特定任务,而那些不需要的或者无用的数据则不再视图中显示。 4、视图大大地简化了用户对数据的操作。 5、视图可以让不同的用户以不同的方式看到不同或者相同的数据集。 6、在某些情况下,由于表中数据量太大,因此在表的设计时常对表进行水平或者垂直分割,但表的结构的变化对应用程序产生不良的影响。 7、视图提供了一个简单而有效的安全机制。 视图的创建: CREATE VIEW 视图名(列表名) AS SELECT 查询子句

Selenium vs. Playwright

下方查看历史精选文章 重磅发布 - 自动化框架基础指南pdfv1.1 大数据测试过程、策略及挑战 测试框架原理,构建成功的基石 在自动化测试工作之前,你应该知道的10条建议 在自动化测试中,重要的不是工具 Python自动化浏览器测试:Selenium vs. Playwright 在现代Web应用程序开发中,自动化浏览器测试成为了不可或缺的一部分。为了使测试更加高效、可靠,我们需要使用一些工具,例如Selenium和Playwright。这两个工具都是基于Python的自动化测试框架,本文将介绍它们的原理、架构、优劣对比以及代码实例。 原理 Selenium Selenium是一个自动化测试框架,它允许用户通过编写脚本来模拟用户在浏览器中的操作。Selenium可以与多个浏览器进行交互,包括Chrome、Firefox和Safari。Selenium通过模拟用户操作并收集页面元素的信息来实现自动化测试。 Playwright Playwright是由Microsoft开发的自动化测试框架,它与Selenium类似,可以模拟用户在浏览器中的操作。与Selenium不同的是,Playwright可以与多个浏览器交互,包括Chrome、Firefox、Safari和Edge。Playwright的目标是提供更快、更可靠的自动化测试体验,特别是在现代Web开发中。 架构 Selenium Selenium的架构包括三个主要部分:客户端库、WebDriver和浏览器驱动程序。 客户端库:用于编写测试脚本的API接口,支持多种编程语言,包括Python、Java和C#等。 WebDriver:用于控制浏览器的组件,通过HTTP协议与客户端库进行通信。 浏览器驱动程序:用于与浏览器进行通信的组件,负责将命令转换为浏览器可以理解的语言并返回结果。 Playwright Playwright的架构包括四个主要部分:客户端库、driver、浏览器实例和浏览器引擎。 客户端库:用于编写测试脚本的API接口,支持多种编程语言,包括Python、Java和C#等。 driver:用于控制浏览器的组件,通过WebSockets协议与客户端库进行通信。 浏览器实例:用于模拟浏览器的实例,可以与多个浏览器交互。 浏览器引擎:用于与浏览器进行通信的组件,负责将命令转换为浏览器可以理解的语言并返回结果。 优劣对比 Selenium 优点 成熟稳定:Selenium已经存在多年,拥有广泛的用户群体和社区支持。 易于使用:Selenium的API接口易于理解和学习,可以轻松编写测试脚本。 支持多个浏览器:Selenium可以与多个浏览器进行交互,包括Chrome、Firefox和Safari等。 缺点 执行速度慢:Selenium执行速度较慢,因为它使用JavaScript脚本来模拟用户操作。 不稳定:Selenium在某些情况下可能会出现不稳定的问题,例如在处理异步操作时。 Playwright 优点 快速稳定:Playwright在执行速度和稳定性方面表现出色,特别是在处理异步操作时。 开发人员友好:Playwright支持多种编程语言和开发环境,使其易于与其他开发工具集成。 支持多个浏览器:Playwright可以与多个浏览器进行交互,包括Chrome、Firefox、Safari和Edge等。 缺点 年轻不成熟:Playwright是一个相对新的框架,还没有像Selenium那样成熟稳定。 API接口相对复杂:Playwright的API接口相对复杂,需要一定的学习曲线。 代码实例 Selenium from selenium import webdriver from selenium.webdriver.common.keys import Keys # 初始化Chrome浏览器 browser = webdriver.Chrome() # 打开百度首页 browser.get('https://www.baidu.com') # 获取搜索框 search_box = browser.find_element_by_name('wd') # 在搜索框中输入关键字 search_box.

js求数组最大值

除了使用 Math.max() 方法之外,JavaScript 中还有多种方法可以求数组的最大值,下面介绍其中的几种。 使用循环遍历数组并比较 可以使用 for 循环遍历数组,并使用一个变量来保存数组中的最大值。每当遇到一个比当前最大值大的元素时,更新变量的值。例如: let arr = [1, 5, 3, 8, 2]; let maxNum = arr[0]; // 假设第一个元素为最大值 for (let i = 1; i < arr.length; i++) { if (arr[i] > maxNum) { maxNum = arr[i]; } } console.log(maxNum); // 输出 8 使用 apply() 方法结合 Math.max() 方法 可以使用 apply() 方法将数组中的元素作为参数传递给 Math.max() 方法。例如: let arr = [1, 5, 3, 8, 2]; let maxNum = Math.max.apply(null, arr); console.

SourceTree Git管理神器使用教程详解

目录 前言: SourceTree | Github Desktop | TortoiseGit 可视化管理工具对比: SourceTree介绍和Atlassian账号注册和登录教程: 连接Gitee or GitHub,获取代码: 全面概述Gitee和GitHub生成/添加SSH公钥: 在SourceTree中添加SSH密钥: Clone对应托管平台仓库(以Gitee为例): SourceTree设置默认工作目录: 设置SourceTree默认项目目录: SourceTree代码提交: 1.首先切换到需要修改功能代码所在的分支: 2.将修改的代码提交到暂存区: 3.将暂存区中的代码提交到本地代码仓库: 4.代码拉取更新本地代码库,并将代码推送到远程仓库: 5.在Gitee中查看推送结果: SourceTree分支切换,新建,合并: 1.分支切换: 2.新建分支: 3.合并分支: SourceTree代码冲突解决: 首先我们需要制造一个提交文件遇到冲突的情景: 直接打开冲突文件手动解决冲突: 采用外部文本文件对比工具Beyond Compare解决冲突: Sourcetree中的基本名词说明: Git分布式版本控制器常用命令和使用: SourceTree如何提交PR(Pull Request): 1、fork 项目: 2、克隆本地 3、根据文档创建分支 4、提交修改的代码到远程代码库 5、提交 Pull Request 前言: 俗话说的好工欲善其事必先利其器,Git分布式版本控制系统是我们日常开发中不可或缺的。目前市面上比较流行的Git可视化管理工具有SourceTree、Github Desktop、TortoiseGit,综合网上的一些文章分析和自己的日常开发实践心得个人比较推荐开发者使用SourceTree,因为SourceTree同时支持Windows和Mac,并且界面十分的精美简洁,大大的简化了开发者与代码库之间的Git操作方式。该篇文章主要是对日常开发中使用SourceTree可视化管理工具的一些常用操作进行详细讲解。 SourceTree | Github Desktop | TortoiseGit 可视化管理工具对比: https://blog.csdn.net/hmllittlekoi/article/details/104504406/ SourceTree介绍和Atlassian账号注册和登录教程: https://www.cnblogs.com/Can-daydayup/p/13128511.html 连接Gitee or GitHub,获取代码: 注意:这里介绍的是使用SSH协议获取关联远程仓库的代码,大家也可以直接使用过HTTPS协议的方式直接输入账号密码获取关联代码! 全面概述Gitee和GitHub生成/添加SSH公钥: https://www.cnblogs.com/Can-daydayup/p/13063280.html 在SourceTree中添加SSH密钥: 工具=>选择: 添加SSH密钥位置:C:\Users\xxxxx\.ssh\id_rsa.pub: SSH客户端选择OpenSSH: Clone对应托管平台仓库(以Gitee为例): 打开码云,找到自己需要Clone的仓库!

论文阅读:Towards Open-vocabulary Scene Graph Generation with Prompt-based Finetuning(ECCV22)

第一次看这种prompt的论文,虽然好久没写论文笔记了但是这篇有必要记录一下() pipeline如下: 先看左边的Pretraining VRM 这部分分为两个encoder,分别是上方的图像encoder(εi)和下方的文本encoder(εt) 1.图像encoder 图像encoder分为两个部分,分别是区域proposal特征提取器(Faster RCNN)和关系Transformer(RelTrans) 对于一对主客体对(s-o),使用关系Transformer对其编码,编码过程如下: 其中,rt是主客体对中左上角的区域,rb是右下角的区域,[r1,…rm]是与主客体对的union box有重叠的其他区域。区域来自Faster RCNN的输出。l是每个区域的位置embedding。经过关系Transformer的编码后,得到了[ht,h1,…hm,hb]的编码结果,我们需要的是ht和hb(即hs和ho)。 对于主客体对的union box,也需要用关系Transformer对其编码,编码过程跟上面的公式基本一样,只是将rt和rb换成了rso(即主客体的union box),编码结果为[hso,h1,…,hm],我们需要的是hso。然后对hso再执行下面的公式,得到hr。hr计算公式如下: 综上,hs,ho和hr是图像encoder的输出 2.文本encoder 这里应该用的是预训练好的文本encoder。使用的训练数据是VG里的dense caption,每张图像平均有50个caption,只是描述对应区域的,如下图左侧的框。 文本encoder也分为两个部分,先是embedding,再是文本Transformer,前面的embedding我觉得是下式的W2。下式的[w1,w2,…wk]是第i个caption的单词。l’是每个单词的位置embedding。[CLS]和[EOF]是可学习的特殊token,表示第一个单词和最后一个单词。ei是对第i个caption的编码结果。 综上,ei是文本encoder的输出 3.预训练的loss loss分为三个部分: (1)Lmrl,针对图像encoder里的关系Transformer,将输入的任一区域用特殊标记[mask]代替,通过对比损失使h[mask]尽可能和h[ground truth]接近,训练的是图像encoder (2)Lmtl,针对文本encoder里的文本Transformer,使用的交叉熵,也是将任一token mask掉,训练的是文本encoder (3)Lc,图像encoder的输出和文本encoder的输出尽可能接近,使用的余弦对比损失 至此,预训练结束。在后续的微调过程中,这两个encoder的参数不更新。 再看右边的基于prompt的微调 1.基于hard prompt的微调 模板如下,[CLS]表示第一个单词,[SEP]是句子和句子之间的分隔词。xs是主语的类别,xo是宾语的类别,[mask]是给谓语类别留出来的slot。 谓语的预测公式如下式所示: 其中,模板是Xpro,y是caption中的单词,用M()把它从caption的单词集合中映射到了谓语类别的集合中,ffill()是已经填充完slot的prompt。hr是关系Transformer里的,计算方式为hr=LN(hs,hso,ho)。θ是线性投影函数LN的参数,只有这部分参数更新。P()是得分函数,y_hat是置信度最高的谓语。 得分函数计算如下: 其中,ein( p )是p这个prompt经过文本Transformer的编码结果。这个公式是评估主客体的视觉区域和主语-谓语-宾语这种形式的prompt的余弦相似度,然后做了一个softmax。q是所有填充完的prompt。 1.基于soft视觉-关系prompt的微调 模板如下: 其中,xs’,…,xo’来自下图的V2T decoder。注意下图的εi/εt和预训练VRM那里的εi/εt是一个东西。 谓语的预测公式如下式所示: 相比hard prompt,少了hr。θ‘是V2T decoder的参数,只有这部分参数更新。 得分函数P如下: 其中,wr是数据集的谓语类别经过文本encoder的embedding,e[mask]是prompt中[mask]这个token的文本encoder输出 ------------------------------------------------一些碎碎念---------------------------------------------------- 在做新实验了 想方设法证明加的都是有用的() 最近沉迷史莱姆的视频 但是史莱姆都好贵啊。 感觉我的实验就像做史莱姆一样 加一堆胶水 搅和搅和 面多了加水水多了加面(bushi 最后变成一块()

记录一次pickle load报错问题

记录pickle load class类型数据的时候报错 将class数据储存为pickle文件保存,本以为在其他地方可以直接读进去的,可是报错了,说没有module,可是并没有import module啊 如下: pickle保存的如果是class类型的时候要格外注意!!!! 保存的pickle二进制文件中会记录你的class路径,表示你的class是是在哪里,如果你只open as file然后read一下文件里都是一些什么的时候你会发现有一个地方记录了class的位置: 这里就是记录了你保存的类其实是shelfDetectionUtils文件中的shelfContainer类,所以在加载的时候就会去找,但是其实你的路径已经发生了改变,这个地址可能不一定指向这个类了,所以在import module的时候就报错了 处理 1.一种方法就是把原来的类所在的路径以当前文件为基础,重新copy一份过来,构造一份相同的环境,在load的时候让他能找到这个类 2.

Nginx+keepalived双主配置(双机双主热备)

简介 这种方案,使用两个VIP地址,前端使用2台机器,互为主备,同时有两台机器工作,当其中一台机器出现故障,两台机器的请求转移到一台机器负担,非常适合于生产架构环境。 一、网络拓扑 四台虚拟机如下所示: 为什么使用keepalived呢? 使用keepalived就用来做高可用的,提供虚拟VIP 二、配置 将两台机器上的/etc/keepalived/keepalived.conf配置文件修改成如下: Nginx-A: [root@Nginx-A src]# vim /etc/keepalived/keepalived.conf !ConfigurationFilefor keepalived ############################ 全局配置 ############################# global_defs {# 定义管理员邮件地址,表示keepalived在发生诸如切换操作时需要发送email通知,以及email发送给哪些邮件地址,可以有多个,每行一个 notification_email {#设置报警邮件地址,可以设置多个,每行一个。 需开启本机的sendmail服务 13020176132@163.com }#keepalived在发生诸如切换操作时需要发送email通知地址,表示发送通知的邮件源地址是谁 notification_email_from 13020176132@163.com #指定发送email的smtp服务器 smtp_server 127.0.0.1#设置连接smtp server的超时时间 smtp_connect_timeout 30#运行keepalived的机器的一个标识,通常可设为hostname。故障发生时,发邮件时显示在邮件主题中的信息。 router_id swarm01 }############################ VRRPD配置 ############################# # 定义chk_http_port脚本,脚本执行间隔10秒,权重-5,检测nginx服务是否在运行。有很多方式,比如进程,用脚本检测等等 vrrp_script chk_http_port {#这里通过脚本监测 script "/opt/chk_nginx.sh"#脚本执行间隔,每2s检测一次 interval 2#脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -5 weight -5#检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间) fall 2#检测1次成功就算成功。但不修改优先级 rise 1}#定义vrrp实例,VI_1 为虚拟路由的标示符,自己定义名称,keepalived在同一virtual_router_id中priority(0-255)最大的会成为master,也就是接管VIP,当priority最大的主机发生故障后次priority将会接管 vrrp_instance VI_1{#指定keepalived的角色,MASTER表示此主机是主服务器,BACKUP表示此主机是备用服务器。注意这里的state指定instance(Initial)的初始状态,就是说在配置好后,这台服务器的初始状态就是这里指定的, #但这里指定的不算,还是得要通过竞选通过优先级来确定。如果这里设置为MASTER,但如若他的优先级不及另外一台,那么这台在发送通告时,会发送自己的优先级,另外一台发现优先级不如自己的高, #那么他会就回抢占为MASTER state MASTER#指定HA监测网络的接口。与本机 IP 地址所在的网络接口相同,可通过ip addr 查看 interface ens33# 发送多播数据包时的源IP地址,这里注意了,这里实际上就是在哪个地址上发送VRRP通告,这个非常重要, #一定要选择稳定的网卡端口来发送,这里相当于heartbeat的心跳端口,如果没有设置那么就用默认的绑定的网卡的IP,也就是interface指定的IP地址 mcast_src_ip 192.

Java程序运行在Docker等容器环境有哪些新问题?

第30讲 | Java程序运行在Docker等容器环境有哪些新问题? 如今,Docker 等容器早已不是新生事物,正在逐步成为日常开发、部署环境的一部分。Java 能否无缝地运行在容器环境,是否符合微服务、Serverless 等新的软件架构和场景,在一定程度上也会影响未来的技术栈选择。当然,Java 对 Docker 等容器环境的支持也在不断增强,自然地,Java 在容器场景的实践也逐渐在面试中被涉及。我希望通过专栏今天这一讲,能够帮你能做到胸有成竹。 今天我要问你的问题是,Java 程序运行在 Docker 等容器环境有哪些新问题? 典型回答 对于 Java 来说,Docker 毕竟是一个较新的环境,例如,其内存、CPU 等资源限制是通过 CGroup(Control Group)实现的,早期的 JDK 版本(8u131 之前)并不能识别这些限制,进而会导致一些基础问题: 如果未配置合适的 JVM 堆和元数据区、直接内存等参数,Java 就有可能试图使用超过容器限制的内存,最终被容器 OOM kill,或者自身发生 OOM。 错误判断了可获取的 CPU 资源,例如,Docker 限制了 CPU 的核数,JVM 就可能设置不合适的 GC 并行线程数等。 从应用打包、发布等角度出发,JDK 自身就比较大,生成的镜像就更为臃肿,当我们的镜像非常多的时候,镜像的存储等开销就比较明显了。 如果考虑到微服务、Serverless 等新的架构和场景,Java 自身的大小、内存占用、启动速度,都存在一定局限性,因为 Java 早期的优化大多是针对长时间运行的大型服务器端应用。 考点分析 今天的问题是个针对特定场景和知识点的问题,我给出的回答简单总结了目前业界实践中发现的一些问题。 如果我是面试官,针对这种问题,如果你确实没有太多 Java 在 Docker 环境的使用经验,直接说不知道,也算是可以接受的,毕竟没有人能够掌握所有知识点嘛。 但我们要清楚,有经验的面试官,一般不会以纯粹偏僻的知识点作为面试考察的目的,更多是考察思考问题的思路和解决问题的方法。所以,如果有基础的话,可以从操作系统、容器原理、JVM 内部机制、软件开发实践等角度,展示系统性分析新问题、新场景的能力。毕竟,变化才是世界永远的主题,能够在新变化中找出共性与关键,是优秀工程师的必备能力。 今天我会围绕下面几个方面展开: 面试官可能会进一步问到,有没有想过为什么类似 Docker 这种容器环境,会有点“欺负”Java?从 JVM 内部机制来说,问题出现在哪里? 我注意到有种论调说“没人在容器环境用 Java”,不去争论这个观点正确与否,我会从工程实践出发,梳理问题原因和相关解决方案,并探讨下新场景下的最佳实践。 知识扩展 首先,我们先来搞清楚 Java 在容器环境的局限性来源,Docker 到底有什么特别?

【Python】字典与zip()函数

字典是 无序、键不重复且元素只能是键值对的可变的一个容器。 怎么理解可变和不可变,简单来说,就是元素是否可以被更改。 data = { "k1":1, "k2":2 } 元素必须键值对 键不重复,重复则会被覆盖 data = { "k1":1, "k1":2 } print(data) 一、字典的定义 # 空字典的创建 empty_dict = {} empty_dict1 = dict() # 字典是无序的 dict1 = {'name': 'abc', 'age': 22} dict2 = {'age': 22, 'name': 'abc'} if dict1 == dict2: print("相等") # 字典是key是不能重复的,如果有重复的key,取最后的key的值 dict3 = {"name": 'abc', 'age': 22, 'name': 'nebula', 'name': 'nebula1'} print(dict3) 如果键重复,则按最后一个键的值为准 二、字典的键值对可变 字典元素添加 # 1) 赋值方法 通过赋值方法可以实现对字典进行新的元素添加 country_total = {"USA": 950, "

C# modbus TCP协议应用总结(一)

1.协议简介 Modbus由MODICON公司(现施耐德公司)于1979年开发,是一种工业现场总线协议标准。主要分为了RTU,ASCII,TCP三种协议类型。 本文我们只探讨C# modbusTCP的应用。 modbusTcp协议采用master/slave模型。在modbus总线中是以"一主多从"关系存在的。通讯方式是主站发出请求(广播或者单播),从站收到请求后应答。 2.Modbus Tcp 主从站关系 什么时候需要编写主站程序,什么时候需要编写从站程序,对于初学者总有些疑惑。 2.1 Modbus 主站(master):Modbus主站具有唯一性,可以主动发出读取、修改指令,对接多个Modbus从站。主站(master)一般作为工控机上位机程序来读取传感器设备的数据,编程时作为网络客户端(TCP Client),IP地址不需要固定。 2.2 Modbus从站(slave):Modbus从站可以有多个,不会主动发出读取指令,只能对接一个Modbus主站。从站(slave)一般是传感器部分的程序,需要一个固定的IP地址,从站编程时一般作为网络服务端(TCP Server),监听回应主站发来的请求。 3.Modbus的功能码 功能码 含义 0x01 读线圈 0x02 读离散量输入 0x03 读保持寄存器 0x04 读输入寄存器 0x05 写单个线圈 0x06 写单个保持寄存器 0x0F 写多个线圈 0x10 写多个保持寄存器 例程:0x03:读保持寄存器,从远程设备中读保持寄存器连续块的内容 请求 :19 15 00 00 00 06 01 03 05 4A 00 01 应答:19 15 00 00 00 05 01 03 02 11 22 请求解析: 19 15 为报文标识符(用户自定义),一般每次通信加1来表示区别不同报文 00 00 表示modbusTCP协议 00 06 表示后面的数据长度 01 从站号 03 功能码。 05 4A 读取数据的起始地址 00 01 读几位地址(寄存器数量) 应答解析: 19 15 为报文标识符 00 00 表示modbusTCP协议 00 05 表示后面的数据长度 01 从站号 03 功能码 02 表示读到的数据长度 11 22 表示读到的数据 4.

Modbus --- EasyModbus的简单读取与写入

一.模拟工具Modbus Slave 在这里可以模拟设备 本文模拟Modbus Tcp的方式 1.设置连接配置 2.设置 二. EasyModbusTCP的使用 EasyModbusTCP是C#在modbus的一个开源库. 1.下载Nuget包 注意 : 版本 <= .net framework4.8 读取示例 : ModbusClient modbusClient = new ModbusClient("127.0.0.1", 502); try { modbusClient.UnitIdentifier = 2; //地址 modbusClient.Baudrate = 9600; //波特率 modbusClient.Parity = Parity.None; //校验位 modbusClient.StopBits = StopBits.One; //停止位 modbusClient.ConnectionTimeout = 500; modbusClient.Connect(); int[] result = modbusClient.ReadHoldingRegisters(0, 1); //寄存器初始地址号 StringBuilder builder = new StringBuilder(); for (int i = 0; i < result.Length; i++) { builder.Append(Convert.ToString(result[i]) + "

解决Ubuntu界面在虚拟机中的大小问题

这里写自定义目录标题 打开时界面是这样 打开时界面是这样 安装完open-vm-tools 复制这个压缩包到到下载这里, 然后解压缩,到下图这个界面 单击打开这个文件 输入 sudu perl 和粘贴当前的文件名,然后按enter键,会到下面界面,然后输入你自己的密码,再按enter键 之后一直按enter键,直到出现当前界面 最后在你的VM ware里面有个 ,查看-自动调整大小-自动适应客户机,然后你的ubuntu界面 就变的和你电脑屏幕差不多大了

java导出excel的两种方式

博主简介:原互联网大厂tencent员工,网安巨头Venustech员工,阿里云开发社区专家博主,微信公众号java基础笔记优质创作者,csdn优质创作博主,创业者,知识共享者,欢迎关注,点赞,收藏。 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。” https://www.cbedai.net/xander 一、在后台实现,利用java的poi 1、导入jar包,需要导入lib文件夹下如下包: poi-3.11-20141221.jar poi-ooxml.jar poi-ooxml-schemas.jar 2、在util下写一个公共类,该类主要利用Jakarta POI HSSF API组件(用于操作Excel的组件),主要部分包括Excel对象,样式和格式,还有辅助操作。 常用组件: HSSFWorkbook excel的文档对象 HSSFSheet excel的表单 HSSFRow excel的行 HSSFCell excel的格子单元 HSSFFont excel字体 HSSFDataFormat 日期格式 HSSFHeader sheet头 HSSFFooter sheet尾(只有打印的时候才能看到效果) 样式: HSSFCellStyle cell样式 辅助操作包括: HSSFDateUtil 日期 HSSFPrintSetup 打印 HSSFErrorConstants 错误信息表 3、该类的操作代码如下: package com.bdqn.util; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFFont; import org.apache.poi.hssf.usermodel.HSSFRichTextString; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.ss.util.CellRangeAddress; public class ExportExcel { // 显示的导出表的标题 private String title; // 导出表的列名 private String[] rowName; private List<Object[]> dataList = new ArrayList<Object[]>(); // 构造函数,传入要导出的数据 public ExportExcel(String title, String[] rowName, List<Object[]> dataList) { this.

uniapp PUSH1.0

根据后端需求需要先绑定别名 bindUnipushAlias(name) { let alias = `a_${name}` var isAndorid, PushManager, context, Instance, GeTuiSdk; isAndorid = plus.os.name == 'Android' ? true : false if (isAndorid) { PushManager = plus.android.importClass("com.igexin.sdk.PushManager"); context = plus.android.runtimeMainActivity().getContext(); Instance = PushManager.getInstance(); } else { GeTuiSdk = plus.ios.importClass("GeTuiSdk"); } if (isAndorid) { //绑定别名 Instance.bindAlias(context, alias); } else { GeTuiSdk.bindAliasandSequenceNum(alias, alias); } }, 之后在App.vue里面调用方法 onLaunch(){ // #ifndef MP-WEIXIN //传入用户信息作为别名 let userInfo = storage.get('userInfo') if (userInfo.id) this.bindUnipushAlias(userInfo.id) //push点进来的方法 plus.push.addEventListener("click", function(res) { let url = res.

Python报错:ModuleNotFoundError: No module named ‘xxx‘可能的解决方案大全

Python报错:"ModuleNotFoundError: No module named 'xxx'"这个报错是个非常常见的报错,几乎每个python程序员都遇到过,导致这个报错的原因也非常多。 下面是我曾经遇到过的原因和解决方案: module包没安装 忘了import 没有__init__.py文件 package包的版本不对 自定义的包名与安装的包名相同,导致import包的时候导错了包 没设置PYTHONPATH或者 自建的module包所在路径不在PYTHONPATH下 不恰当的使用了相对导入 下面是每种情况分别的解决方案: 1、module包没安装 使用场景: pip安装的第三方的包找不到 这个原因比较常见,解决办法就是pip install相应的包即可。如果不确定是否安装了这个包,使用下面的命令查找报警的那个包名,如果有输出结果,说明存在这个包,否则说明不存在这个包。 pip list | grep xxx #把xxx替换成你的包名即可 如果在pip install的过程中提示包找不到,没有这个版本的包,可能是需要加上内置源,比如想要下载公司内部的包,那肯定需要加上公司的内置源才能找到相应的包。内置源的的使用方式加上-i参数即可。 pip install xxx -i https://xxx.xx.org/simple # 比如下面是清华的源 # https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple/ 2、忘了import 使用场景: pip安装的第三方的包找不到、自建的module包找不到 module安装了但是没有import,这个原因也经常碰到,比如使用了datetime对象, 但是没有导入datetime包。解决方案同样非常简单,import 相应的包即可。比如下面的案例: import os import sys import time import datetime 这种情况最容易出现在从别处copy了一段了代码,但是没有把所有用到的module导入进来。 3、没有__init__.py文件 使用场景: 自建的module包找不到 因为python在解释包的时候会给本文件夹也就是本module下的所有文件建立一个索引放在当前路径下的__init__.py文件中,如果没有module的文件索引,我们即使import了指定的包,解释器还是找不到这个module下的文件的,因而我们一般会在每个文件夹下建一个空的__init__.py文件。如果一个文件夹下没有__init__.py文件,不会被当做一个module。 解决方案: 如果这个包是你自己写的,不妨检查一下待导入的包的根目录是否存在一个__init__.py文件,没有的话建一个空的__init__.py文件即可 (注意:不光要检查待导入的包根目录是否存在__init__.py文件,还需要检查当前程序所在文件夹是否存在这个文件)。如果这个包是pip install来的,那基本上可以忽略这种可能了,继续尝试下面的原因吧。 对于缺少__init__.py文件这种情况,还有一种报错形式是: ImportError: attempted relative import with no known parent package 4、安装的第三方module包的版本不对 使用场景: pip安装的第三方的包找不到

Jenkins离线部署方法

一、前言 1、在项目开发过程中以及UAT测试阶段,为解决频繁发布问题,往往我们会安装一个jenkins部署工具,减少我们频繁发布等问题,在测试阶段我们需要客户提供一台服务器安装此插件,由于客户服务器网络限制等问题,Linux系统服务器不能连接外网导致在安装jenkins过程中不能正常的安装我们需要的插件,由于jenkins从官网下载后,默认是没有插件的,需要我们自己安装对应的插件,安装插件过程中需要连接外网进行下载,如果是有网络的情况下安装是非常方便的,但是如果是离线安装会多出几步操作,官方给出了离线安装方法,但是给出的文档有的小伙伴看不懂,网上详细资料也非常少,今天借此机会在参照官方的给出的安装方法再次进行补充,今天在这里做下记录分享给在项目中需要的小伙伴仅做参考。 一、jenkins下载 1、jenkins下载地址:War Jenkins Packages 2、选择对应的安装版本、注意每个版本支持的jdk 3、选择对应的版本号,本次安装采用war包方式启动 二、jenkins离线下载插件 1、官方提供的离线安装方法:Installing Jenkins 2、下载离线安装插件工具 3、进入plugin-installation-manager-tool:注意、最新的插件工具默认jdk最低要求只支持jdk11上GitHub - jenkinsci/plugin-installation-manager-tool: Plugin Manager CLI tool for Jenkins 4、第三步是自己下载源码自己打jar包,也可以采用第四步官方下载一个打包的jar包,下载地址: 5、下载插件工具包地址: Release 2.12.11 · jenkinsci/plugin-installation-manager-tool · GitHub 6、下载后放到wind本地使用命令启动 java -jar jenkins-plugin-manager-2.12.11.jar --war C:\Users\xunliu\Desktop\jenkins\jenkins.war --plugin-file C:\Users\xunliu\Desktop\jenkins\plugins.txt --plugins delivery-pipeline-plugin:1.3.2 deployit-plugin 输入命令后,会读取C:\Users\xunliu\Desktop\jenkins\plugins.txt文件内容对应的插件名称,在输入上面命令前,需要先把需要的插件名称写入到plugins.txt后,在执行此命令会自动去官网下载war包对应的插件依赖,第一次有点久需要等待几分钟不要关闭窗口,下载完成后会自动关闭jar服务。 ant antisamy-markup-formatter batch-task credentials cvs external-monitor-job javadoc junit ldap mailer matrix-auth matrix-project maven-plugin pam-auth powershell publish-over-ftp publish-over-ssh rebuild role-strategy script-security ssh-credentials ssh-slaves subversion translation view-job-filters windows-slaves Localization Localization: Chinese (Simplified) 下载完成后的插件路径:

jmeter如何进行websocket压测?

1.首先下载一个websocket包 下载地址:pjtr / JMeter WebSocket Samplers / Downloads — Bitbucket 2.将下载的文件复制/移动到jmeter目录安装目录下 安装目录:G:jmeter\apache-jmeter-4.0\apache-jmeter-4.0\lib\ext 3.重启jmeter,先添加线程组,再点击添加sampler,就可以看到websocket信息 4.添加WebSocket request-response Sampler请求 5.选择协议ws/wss,输入ip、端口、路径、请求参数(没有参数可不填) 6.上面参数都弄好了之后,点击启动,查看结果树即可。 希望对你有所帮助,谢谢~

如何解决:安装linux时报错Operating System not found 怎么办?

大家出现这个问题了,肯定是在网上找资料。其实我也找了很多资料,但是呢,我找的都没有用,后来我自己又从新从头到尾的重新装了几遍,然后就发现了问题所在之处。 操作步骤: 1.首先关闭刚配置的虚拟机 首先右键点击这个安装出错的虚拟机,然后再右键,选择电源=》关闭客户机=》关机 2.移除此虚拟机 3.新增一个虚拟机 文件=》新建虚拟机=》典型=》下一步 4.安装虚拟机 进入到这个页面后会默认选择第三个选项,这个要改成第二个选项,然后再下一步,设置自己的简易安装信息后,进入到下一步 5.最后就是下一步下一步,安装完成之后,再打开你刚刚安装的虚拟机。注意:打开你刚刚的虚拟机之时,如果有其他的虚拟机你一定要关闭。安装成功就会进入如下的画面,这个时候只要等它自动安装完成就行。 还有一种解决办法就是重新去官网下载虚拟光驱就行。 下载地址:Download Linux | Linux.org 你安装的是哪个你就选择哪个,我安装的是centos,所以下载的就是centos。 希望对你有所帮助,谢谢~

Mybatis数据库一对多查询

1,进行一对多查询,首先准备两个mysql数据表,查询读者与借书信息的关联关系 #创建readers表用来储存读者信息 CREATE TABLE `readers`( `id` INT PRIMARY KEY AUTO_INCREMENT, `name` VARCHAR(255) NOT NULL, `phone` DOUBLE(30,0) NOT NULL, `code` VARCHAR(50) NOT NULL ); #插入数据 INSERT INTO readers VALUES(1,'admin',19872675353,'AS0001'); #创建lend_books表用来储存书籍信息 CREATE TABLE `lend_books`( `id` INT PRIMARY KEY AUTO_INCREMENT, `bksName` VARCHAR(255) NOT NULL, `price` DOUBLE(30,2) NOT NULL, `date` DATE NOT NULL, `bksCode` VARCHAR(50) NOT NULL, `lend_id` INT UNIQUE, FOREIGN KEY (lend_id) REFERENCES readers(id) ); #插入数据 INSERT INTO lend_books VALUES(NULL,'《测试》',100.00,'2023-3-24',2023843,NULL); 2,在IDEA创建maven项目并命名JavaEE 在项目src/main/java下创建com.three.pojo包

基于QT的TCP通信实现(TCPServer和TCPClient)

文章目录 一、软件介绍1.1 TCPServer服务端界面1.2 TCPClient客户端界面1.3 服务端和客户端建立连接并通信演示 二、QT实现TCPServer和TCPClient2.1 TCPClient客户端2.1 TCPServer服务端 三、代码分享 近期因为测试需要用到 TCPServer(TCP服务端)和 TCPClient(TCP客户端)来进行通信和数据的发送以及接受,所以用QT分别写了TCP服务端和TCP客户端,本文分享以下基于QT开发TCPServer和TCPClient的经验, 文中包括源码,在文末处包含项目的源码文件。 一、软件介绍 TCPServer可以绑定一个ip地址并监听一个端口,在TCPServer绑定并监听状态时,可以使用TCPClient来连接服务端绑定的ip地址和端口,连接成功后便可进行通信了。下面首先演示以下服务端和客户端界面以及通信流程。 1.1 TCPServer服务端界面 在服务端的界面中,“开始监听”按钮可以在设置“监听地址”、“监听端口”后点击既开始对此ip地址和端口进行监听,当有TCPClient客户端针对此ip地址和端口进行请求连接时便可进行连接,随后开始通信。“停止监听”可以停止对ip地址和端口号的监听。“清空文本框”按钮可以清空消息记录,方便连续信息的阅读。“退出”按钮即关闭此软件。“发送消息”可发送已经输入的内容。 1.2 TCPClient客户端界面 在客户端的界面中,“连接”按钮可以在设置“连接地址”、“端口”后点击既开始对此ip地址和端口进行请求连接,当有TCPServer服务端针对此ip地址和端口进行监听时便可进行连接,随后开始通信。“断开连接”可以讲服务端和客户端已经建立的连接断开。“清空文本框”按钮可以清空消息记录,方便连续信息的阅读。“发送消息”和“清除”按钮分别可发送和清除已经输入的内容。“退出”按钮即关闭此软件。 1.3 服务端和客户端建立连接并通信演示 首先在Server端我们绑定ip:192.168.31.222,端口:1200,然后点击“开始监听”按钮,这时服务端就开始等待Client端请求建立连接。 接下来我们使用客户端,连接地址和端口号设置为服务端所绑定的ip:192.168.31.222,端口:1200,然后点击“连接”按钮,可以看到双方建立连接成功,软件出现连接成功建立提示信息。 双方建立连接成功便可以开始通信,我们首先点击“清空文本框”把提示信息清除,然后使用TCPServer服务端发送一条信息“Hello,I’m TCPServer~”,可以看到客户端成功收到服务端发送的信息,[in]后边的内容为本端收到的信息,[out]后边的内容为本端发送的信息。 接下来我们使用TCPClient客户端给服务端发送一条信息“Hi,I’m TCPClient!”,可以看到服务端成功收到信息。 二、QT实现TCPServer和TCPClient 我们想要在QT中实现TCP通信需要在.pro文件中添加下面一行代码: QT += network 2.1 TCPClient客户端 首先我们应该包含下面三个头文件来支持我们调用内部的通信函数: #include <QTcpSocket> #include <QHostAddress> #include <QHostInfo> 创建QTcpSocket套接字对象 tcpClient = new QTcpSocket(this); 使用tcpClient 对象连接服务器 tcpClient ->connectToHost(IP, port); 然后我们用write()函数向服务器发送数据 tcpClient ->write(data); 当tcpClient 接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据 connect(tcpClient,SIGNAL(readyRead()),this,SLOT(onSocketReadyRead())); void MainWindow::onSocketReadyRead() {//readyRead()信号槽函数 while(tcpClient->canReadLine()) ui->plainTextEdit->appendPlainText("[in] "+tcpClient->readLine()); } 在我们通信完毕后需要断开连接 void MainWindow::on_actDisconnect_triggered() {//断开与服务器的连接 if (tcpClient->state()==QAbstractSocket::ConnectedState) tcpClient->disconnectFromHost(); } 下面给出TCPClient的代码

try-catch 处理异常 以及一些基础的使用方法(重点)

try { 可能出现异常的代码; } catch(异常类名 变量名) { 异常的处理代码; } 程序从 try 里面的代码开始执行 出现异常,就会跳转到对应的 catch 里面去执行 执行完毕之后,程序还可以继续往下执行 public static void main(String[] args) { int[] arr = null; try { printArr(arr); } catch (NullPointerException e) { System.out.println("参数不能为空"); } } private static void printArr(int[] arr) { if (arr ==null){ throw new NullPointerException(); }else { for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } } } 如果 try 中没有遇到问题,怎么执行?

mysql和mysql2模块的区别!!(nodejs中的模块)

mysql 和 mysql2 都是 Node.js 中常用的操作 MySQL 数据库的模块,它们的主要区别是在实现方式上略有不同。 mysql:是 Node.js 中比较早期的 MySQL 操作模块,该模块底层使用的是回调函数(callback)来实现异步操作。在处理大量并发请求时,由于回调函数的嵌套会导致代码难以维护、阅读和调试,因此在性能和可维护性上都有一定的劣势。此外, mysql 模块在连接池等方面的表现也较为一般。 mysql2:是 mysql 模块的替代品,该模块使用 Promise 和回调函数(callback)两种方式来实现异步操作,因此在性能和可维护性上都具有优势。此外,mysql2 模块还新增了支持多语句查询、预处理语句等功能,提供了更丰富的 API,使用起来更方便。 因此,在实际开发中,建议使用 mysql2 模块来操作 MySQL 数据库,它相对于 mysql 模块更加稳定、灵活、易用。当然,如果使用的是较老的版本,可能需要依赖 mysql 模块,但这种情况下需要自己承担潜在的风险和限制。 例如:使用mysql时:一般是这样用:而不是Promise的方式 db.query(sql, req.params.id, (err, results) => { if (err) return res.cc(err) if (results.length !== 1) return res.cc("获取对应文章失败!") res.send({ status: 0, message: "获取对应文章分别成功!", data: results[0] }) }) 且在相应的db文件夹下的index.js文件中应该这样写 const mysql = require("mysql") const db = mysql.createPool({ host: "127.0.0.1", user: 'root', password: "