Janus版本:janus-gateway-0.11.5,注册版本与各组件版本的对应关系,注意组件间依赖的版本匹配问题。
1.安装依赖库:
下载最新的源代码需要git,若没有安装git可以使用下面命令进行安装:
sudo apt-get install git -y
安装lua库
sudo apt-get install liblua5.3-dev
编译运行 Janus Server 需要依赖较多的一些第三方库,而这些依赖库在 Ubuntu 下主要通过 aptitude 进行安装,首先通过安装 aptitude:
sudo apt-get install aptitude
还有一些编译的aptitude依赖库,相关安装命令如下:
sudo aptitude install libmicrohttpd-dev libjansson-dev libnice-dev
sudo aptitude install libssl-dev libsofia-sip-ua-dev libglib2.0-dev
sudo aptitude install libopus-dev libogg-dev libcurl4-openssl-dev pkg-config f
sudo aptitude install gengetopt libtool automake libconfig-dev doxygen graphviz
sudo apt-get install cmake openssl libssl-dev -y
sudo apt-get install -y
2.安装libsrtp2.2.0:
下载源码:https://github.com/cisco/libsrtp/releases/tag/v2.2.0
论文:原文
没代码,离谱
被Graph transformer吸引,看看什么叫图transformer。
0.Abstract
TransMOT有效地对大数量的目标之间的关系进行了建模。它通过将已跟踪的目标作为稀疏带权图的集合来安排轨迹,并且构建一个空间的graph transformer的Encoder层,一个时域的graph transformer的Encoder层,一个空间的graph transformer的Decoder层。
为了提高精确度,提出了一个级联的关联结构,来处理低置信度的检测和长期遮挡。 但这个结构会消耗很大的计算资源。
在MOT15,16,17,20上都是SOTA。
\space 1.Introduction
在Introduction的开始,作者说了当前的基于Transformer的方法(引用的是TransTrack和TrackFormer)的缺陷:
1.一个视频包含了很多的目标。用Transformer对这些目标之间的关系进行时空建模是不太有效的,因为并没有将目标的时空结构纳入考虑。
2.要求比较大的计算资源和数据
3.不是SOTA
我不是很同意第一条。这些基于基本范式的Transformer的方法考虑到时空结构了。对于query-key机制,一般是一个query代表一个object,这些query作为transformer的输入,transformer是可以学习输入间的关系的,这考虑了空间结构。利用自回归的方式,这些query可以携带object的信息在帧间传输,这也考虑了时间结构。但是用graph的方式更直接,而已有的工作更含蓄。
对于第三点,不是SOTA问题也不大,我觉得,想法好就行了
\space 后面大概介绍了TransMOT的工作方式。
所有被跟踪的目标的轨迹都被弄成一系列稀疏的带权图,这些带权图是用目标的空间关系进行构建的,如下图所示:
(如图,graph直接反映了目标在图片里的位置关系)
\space 基于这些稀疏图,TransMOT就建立了一个空间graph transformer Encoder,一个时域graph transformer Encoder,一个空间transformer decoder来建模。
由于图的稀疏性,计算起来更有效。
作者也建立了一个级联关联结构,来处理低置信度的检测和长时间遮挡。通过将TransMOT整合到这个级联关联结构中,不需要额外地学习关联的部分。
\space TransMOT整体结构如下图:
\space \space 3.Overview
这部分大体介绍了TransMOT的工作方式。
在 t t t时刻,整个框架有 N t − 1 N_{t-1} Nt−1个tracklets,每个tracklet代表一个被追踪的目标。每个tracklet L i t − 1 \textbf{L}_i^{t-1} Lit−1维持一个状态的集合,比如说过去 T T T帧的位置 { x ^ t ′ i } t ′ = t − T t − 1 \{\hat{x}_{t'}^i\}_{t'=t-T}^{t-1} {x^t′i}t′=t−Tt−1外观特征 { f ^ t ′ i } t ′ = t − T t − 1 \{\hat{f}_{t'}^i\}_{t'=t-T}^{t-1} {f^t′i}t′=t−Tt−1.
文章目录 创建数组append函数concatenate函数stack函数列表中的 numpy 数组合并 import numpy as np 创建数组 a1 = np.arange(0,6).reshape(2,3) a1 array([[0, 1, 2], [3, 4, 5]]) a2 = np.arange(6,12).reshape(2,3) a2 array([[ 6, 7, 8], [ 9, 10, 11]]) append函数 np.append(a1,a2) array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) np.append(a1,a2,axis=0) array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 9, 10, 11]]) np.append(a1,a2,axis=1) array([[ 0, 1, 2, 6, 7, 8], [ 3, 4, 5, 9, 10, 11]]) concatenate函数 np.
(以下操作建议以root用户身份操作)
打开终端,插入u盘,出现下图,勾选虚拟机,之后确定即可。
利用指令fdisk -l 查看磁盘分区情况
我知道我的u盘59.6G,linux虚拟机40G,所以 u盘设备名为/dev/sda1
这里我们将挂载点定在目录/mnt下,在该目录下创建挂载点usb.
挂载u盘的类型是vfat,将/dev/sda1 以vfat文件系统挂载到/mnt/usb上。
切换到usb目录下,输入ls指令即可查看U盘文件。
拔出u盘前先卸载u盘,指令 umount /mnt/usb(为挂载点),可能遇到这种情况,这是因为U盘正在被占用,需要杀死U盘进程。
这时可以输入指令 fuser -kvm /mnt/usb杀死进程。
也可以查看占用者,输入lsof /mnt/usb显示bash占用,输入指令kill -9 4438(bash的PID),杀死bash.
杀死进程后,切换回root用户身份
再次输入umount /mnt/usb成功卸载。
实训题目:部署LAMP环境安装zabbix进行配置
实训环境:Linux+Apache+MariaDB+PHP+zabbix-(server+agent)
实训目的:学习安装zabbix的全过程,使用zabbix前端来监视服务器系统
一.zabbix服务主机进行配置(192.168.160.154)
1.关闭防火墙
[root@promote ~]# systemctl stop firewalld
[root@promote ~]# systemctl status firewalld
2.安装zabbix前的安装准备
[root@bogon ~]# rpm -Uvh https://repo.zabbix.com/zabbix/4.0/rhel/7/x86_64/zabbix-release-4.0-1.el7.noarch.rpm
[root@bogon ~]# yum clean all
[root@bogon ~]# yum install -y zabbix-server-mysql zabbix-web-mysql zabbix-agent mariadb mariadb-devel mariadb-server httpd php php-devel
3.启动 mariadb 数据库服务
[root@promote ~]# systemctl start mariadb
[root@promote ~]# systemctl status mariadb
4.进入数据库后进行创建数据库、授权账号和刷新权限操作。
[root@bogon ~]# mysql -u root -p
5.导入数据库脚本
[root@promote ~]# zcat /usr/share/doc/zabbix-server-mysql*/create.sql.gz | mysql -uzabbix -p zabbix
二、在使用import win32api时,报错:No module named win32api
网上查到有下面解决办法: pip install pypiwin32
或
pip3 install pypiwin32
或
python -m pip install pypiwin32
最近有些时间,开始升级安装在移动硬盘上的linux系统〈〉
如果你使用旧版Fedora版本,比如Fedora 30/31/32/33,可以通过以下三段命令来升级到Fedora Linux 34版本。
升级命令
打开系统终端,依次执行以下命令:
sudo dnf install dnf-plugin-system-upgrade
sudo dnf system-upgrade download --releasever=34
sudo dnf system-upgrade reboot
注:重新启动系统后就可以进入到新升级的Fedora Linux 34桌面中了。以上releasever=34代表升级到Fedora 34
有时中间会报一个错!key的问题。执行一下下面命令就行了
安装现有的 gpg 公钥,在 /etc/pki/rpm-gpg/ 下,将那个for fedora-34-x86_64的导入就行了。
#rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-fedoara-34-x86_64
可以 sudo rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY*,直接把所有的都安装。
首先去官网下载资源:Releases - OpenCV
将资源下: 安装路径\opencv\build\x64\vc15\bin 添加到环境变量
然后包含目录、库目录、附加依赖项请参考:C++项目引入OpenCV库 - 简书
这个时候遇到的问题就是:
error LNK2019: 无法解析的外部符号 "void __cdecl cv::xxxx
解决方案:项目右击 -> 属性 -> 最上面的配置管理器,效果如下
选择x64平台,Debug配置,不然和opencv的配置不兼容。
再然后又遇到一个问题,库正常引入了,但是读取有点问题:
代码: Mat M = imread(imageName, IMREAD_COLOR); 一直无法正确读取到图片。
原因:
这里只需要引入带 xxxxxd.lib 不带d的那个lib不需要引入,否则无法正常读取图片。
也就是在Debug模式下应该选择带'd'的lib,在Release模式下就选择不带'd'的lib。而实际我们在配置OpenCV环境的时候往往图方便将Debug和Release的目录都一起加了进去,再修改起来也比较麻烦。所以这时候最简单的办法就是在程序的开始加上:
#pragma comment(lib,"opencv_world454d.lib")
导航🚀 多态向上转型动态绑定方法重写 理解多态 抽象类接口实现多个接口 多态 向上转型 在刚才的例子中, 我们写了形如下面的代码
Bird bird = new Bird("圆圆"); 这个代码也可以写成这个样子
Bird bird = new Bird("圆圆"); Animal bird2 = bird; // 或者写成下面的方式 Animal bird2 = new Bird("圆圆"); 此时 bird2 是一个父类 (Animal) 的引用, 指向一个子类 (Bird) 的实例. 这种写法称为 向上转型.
向上转型这样的写法可以结合 is - a 语义来理解.
例如, 我让我媳妇去喂圆圆, 我就可以说, “媳妇你喂小鸟了没?”, 或者 “媳妇你喂鹦鹉了没?”
因为圆圆确实是一只鹦鹉, 也确实是一只小鸟
为啥叫 “向上转型”?
在面向对象程序设计中, 针对一些复杂的场景(很多类, 很复杂的继承关系), 程序猿会画一种 UML 图的方式来表示类之间的关系. 此时父类通常画在子类的上方. 所以我们就称为 “向上转型” , 表示往父类的方向转.
向上转型发生的时机:
直接赋值方法传参方法返回 直接赋值的方式我们已经演示了. 另外两种方式和直接赋值没有本质区别.
今天重点从四个方面来和大家对需求阶段需求分析做一个讲解。
阅读测试文档
参与需求评审
测试需求分析
提取功能点
去做这些对应的事情之前,我们要先了解到底什么是需求?需求评审我们要从哪些点去评审?我们要去提取功能点要怎么样去进行提取。
回忆测试流程:
需求阶段------测试计划------测试设计------测试执行------测试评估
实际工作中,需求阶段有时候测试开发团队并不是每一个人都会去参与。在这里我们应该给它分两个事情。
参与需求评审工作(并不是每个测试人员都会参与)
阅读测试文档
参与需求评审
进行需求文档的分析(每个测试人员都要负责的工作)
测试需求分析
提取功能点
所谓的软件需求:
需求是产品必须完成的事以及必须具备的品质。需求包括:功能性需求、非功能性需求和限制条件。(功能性需求非功能性需求都会加上限制条件)需求这个概念我们理解就可以了。
功能性需求:功能性需求是产品必须完成的那些事,要求一定的功能和品质。
案例:微信可以给好友发消息、发红包、发语音和视频等操作--产品考虑的一些点,必须完成这些
功能
非功能性需求:非功能性需求是产品必须具备的属性或品质。诸如观感、可用性、安全性和法律限制等。
例子:x平台用户数为5万人,每天登录用户数为1万左右,网络的带宽为100M带宽。在工作时间根据资料名称条件进行搜索,可以在3秒内得到搜索结果。--性能测试
>2021年天猫活动的订单处理峰值达高于58.3万笔/秒,要求订单成功率为100%
>注意:在项目中一般优先分析功能性需求(满足需求),产品的功能确定之后再分析非功能性需求。
观看书面性的阐述,好像还是有点抽象?
比如我们之前没有微信,产品经理张小龙脑海里有这样子的一个想法:我想做一个聊天交友的软件,它可以与好友进行聊天,发红包,可以发语音、视频。那么其实都是最开始有了一个想法,觉得这个东西是可行的。
他就去做一个调研,去分析一下大部分人的想法,他们对这个软件是怎么看的,这个软件的诞生有没有价值。
调研之后觉得可行性高,就会把想法写下来,形成规范的文档。把一系列的想法以书面文字的形式进行记录。包括了需要去实现的功能,软件的界面是什么样子的雏形。加上一些关于体验性的非功能性需求。
这就形成了最终的------微信产品需求说明书。(想法、调研、写下来)
接下来就会进行召开会议,微信产品需求分析会议。那么这个就是我们需求阶段需要做的第一个事情,参与需求的评审工作。其实这个需求评审它就是众多的人合在一起,然后对产品经理张小龙生成的这个想法以及调研之后写成的需求文档(说明书),一起探讨参与评审。
那么这个会议一般会有哪些人参与?
产品经理,大部分想法都是产品经理提出来的,有一些是甲方客户提出来的。
开发代表,因为这个东西能不能够做成,开发提供的技术支持,都是至关重要的(这个需求做不了。/这个需求别人能做,你不能做?--常有的摩擦)
测试代表,还有的话就是我们测试工程师。并不是说开发所有的人和测试说有的人都会参加这个会议,只是会有几个代表。
运营,
基本上这个会议,产品经理按照需求来进行主持。他首先会给大家来介绍一遍,我们接下来要做的这个产品拥有一些什么功能,界面大概做成一个什么样子,制作周期是怎么计划的,什么时候进行上线,会从哪些渠道进行产品上线的推广宣传,后期会有一些什么盈利。后面我们还可能会加一些什么什么功能。
产品经理表述完之后,就各个代表进行发言。
问开发代表这个需求能不能实现,哪些东西是不能实现的,或者有什么问题需要提出,他就会说一大堆。(通常在这个会议阶段产品经理和开发会有你来我回)问测试代表的一些看法建议之类的。(后期我们的测试思维格局打开了之后,在这个会议上要站在测试工程师的角度多发表自己的观点)基本上这个会议就是做这样子的一个事情。
然后就会把产品需求说明书发到每一个代表人物,回各自团队里面之后,再进行一次会议。告诉大家我们现在接到一个什么产品了,我们会怎么样去做,对于这个产品大家有什么意见或者建议,一起聊一下然后进行一个收集反馈。
需求评审工作就是这一些事情。
如果你通过努力成功进入到了心仪的公司,一定不要懈怠放松,职场成长和新技术学习一样,不进则退。
1.免费领取一份325页软件测试工程师面试宝典文档资料。
2.软件测试学习路线以及相对应的视频学习教程免费分享!
更多 | 学习资源 | 职业规划 | 等,欢迎私信留言。
心怀感激,对帮助过自己的人,给予真诚的回馈,记得把阿沐推给你的朋友。
点赞+在看+收藏,这个对我很重要。
软件测试工程师工作职责
工作职责
测试人员有不同的级别,或者说有不同的职位称呼。都有相对应不同的工作职责。
如果你想了解现在企业里面最新的职位需求的话,最简单的一个方式就是直接去大型招聘网站上BOSS直聘或者前程无忧、赶集网去搜索软件测试工程师招聘JD,其实里面岗位职责就会描述得非常明确。
测试经理------测试架构师------测试工程师------测试管理员
像这种基本上就是一些大公司的规模。只有大公司才会有测试管理员这个岗位,中心型公司基本都有没有,然后测试管理员的工作也是由测试工程师来做。
测试工程师:
具备计算机操作和测试的基础知识,会使用各种测试工具,熟悉测试工作流程。
独立或在管理员的帮助下搭建测试环境,按照要求使用测试管理系统和各种测试工具。
实施各个级别的测试活动,并记录和报告测试结果。
小结一下:
环境搭建
测试用例执行
测试工具使用(禅道、数据库、Postman、Fiddler)
测试用例设计(非常重要,因为这个哎上图中测试用例是测试架构师做的,其实实际情况测试架构师在公司中间的话,他大部分时间是去做框架、平台的一些设计)功能测试用例基本上都是由测试工程师自己来做,包括一些文档的管理。
测试记录
测试报告
……
像其他的一些职责的话,后面我们讲到不同环节这些职责,再给大家进行一个详细的讲解。像这个工作职责的东西,大家可以做一个相对应的匹配,尤其是对于我们零基础转行的小伙伴,先有个印象,我进公司大概要做一些什么样的事情。
测试管理员、测试经理要负责的职责我们快速过一遍即可,都写在了图上,大家可以放大,考虑到像素会被压缩等一系列外在因素,还是敲一遍吧!原创不易,燃烧秀发输出内容,有收获的伙伴记得点赞支持!
测试管理员:
具有系统管理、网络维护、设备安装和调试方面的知识和经验。
规划和搭建测试实验室,建立、设置和为何测试工作所使用的服务器和软件平台。
为何测试工作中的计算机、外设和网络环境的正常运行。
负责设备、软件、文档的等级、分配和归档管理。
测试经理:
具备软件测试、质量管理、项目管理等领域的知识和经验。
参与制定和评审测试计划和方案。
规划、组织和协调各种资源。
推动和监控测试活动的进行。
选择合适的测试度量,以评估测试过程和产品质量。
收集和分析测试过程中的相关数据,为测试过程改进提供信息。
测试架构师:
具有软件测试、软件工程和测试技术等领域的知识和经验。
分析和评审用户要求、规格说明、设计方案等内容。
设计测试用例,准备测试数据,开发测试脚本。
协助测试经理制定测试计划,协助推荐测试活动的进行。
如果你通过努力成功进入到了心仪的公司,一定不要懈怠放松,职场成长和新技术学习一样,不进则退。
1.免费领取一份325页软件测试工程师面试宝典文档资料。
2.软件测试学习路线以及相对应的视频学习教程免费分享!
更多 | 学习资源 | 职业规划 | 等,欢迎私信留言。
心怀感激,对帮助过自己的人,给予真诚的回馈,记得把阿沐推给你的朋友。
点赞+在看+收藏,这个对我很重要。
纯Java实现屏幕截图技术,根据URL得到网页快照 根据用户输入的URL,解析出是哪个网站的页面,然后再强制使用浏览器打开页面,进行截图生成网页快照。
其中url指的是用户输入的URL,pathname指的是快照保存的页面的位置
import javax.imageio.ImageIO; import java.awt.*; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.io.File; import java.net.URL; public class CutPicture { public static void CutImage(String url, File pathname) throws Exception { System.out.println("url===>" + url); System.out.println("pathname==>" + String.valueOf(pathname)); Desktop.getDesktop().browse(new URL(url).toURI()); Robot robot = new Robot(); robot.delay(1000);//使程序暂停一段时间,类似于线程的sleep()方法 Dimension d = new Dimension(Toolkit.getDefaultToolkit().getScreenSize()); int width = (int) d.getWidth(); int height = (int) d.getHeight(); // 最大化浏览器 robot.keyRelease(KeyEvent.VK_F11); robot.delay(100); Image image = robot.createScreenCapture(new Rectangle(0, 0, width, height)); BufferedImage bi = new BufferedImage(width, height, BufferedImage.
本篇目录链接 背景:ECS机器重启后故障后,无法正常开机,集群由原先的3主3从变成了双主3从。现象:k8s集群的新master节点无法加入到集群中,提示如下:原因:通过报错可以集群在进行节点加入时,检查etcd集群,但是10.7.54.135这台集群为故障主机,而由于之前在集群正常时该机器上有etcd的pod,当机器故障后,集群无法检测到该节点上的etcd服务,所以报错。处理办法:step1:登录任意正常的etcd的pod中,剔除故障节点的地址信息。step2:重置待加入master的节点,再次加入集群。 背景:ECS机器重启后故障后,无法正常开机,集群由原先的3主3从变成了双主3从。 现象:k8s集群的新master节点无法加入到集群中,提示如下: [control-plane] Creating static Pod manifest for
“kube-controller-manager” W1110 17:36:52.162178 17976
manifests.go:225] the default kube-apiserver authorization-mode is
“Node,RBAC”; using “Node,RBAC” [control-plane] Creating static Pod
manifest for “kube-scheduler” W1110 17:36:52.162925 17976
manifests.go:225] the default kube-apiserver authorization-mode is
“Node,RBAC”; using “Node,RBAC” [check-etcd] Checking that the etcd
cluster is healthy error execution phase check-etcd: etcd cluster is
not healthy: failed to dial endpoint https://10.7.54.135:2379 with
maintenance client: context deadline exceeded To see the stack trace
使用Html2Image将html转图片 在实际开发的过程,我们会接到各种奇葩的业务需求。有时候会需要将HTML页面转为图片进行一个保存。
使用Html2Image
需要的jar包。 第二个jar是工具类是用于日期转换的 第一个才是Html2Image所需要的包 <dependency> <groupId>gui.ava</groupId> <artifactId>html2image</artifactId> <version>0.9</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.0.6</version> </dependency> 转换代码
HtmlImageGenerator imageGenerator = new HtmlImageGenerator(); String htmlstr = "<table style=\"width: 700px;font-size:16px;font-family: 'Microsoft YaHei';\" cellpadding=\"0\" cellspacing=\"0\">\n" + " <tr >\n" + " <th style=\"background-color: #f2f2f2;height: 30px;width: 700px; border:1px solid #e6e6e6;border-top:none;text-align: center;color: #333333;\" colspan=\"2\">收据</th>\n" + " </tr>\n" + " <tr style=\"width: 700px;\">\n" + " <td style=\"border:1px solid #e6e6e6;border-top:none;text-align: center;color: #666666;height: 30px;\" >日期</td>\n" + " <td style=\"
JSON parse error: Cannot deserialize value of type java.util.ArrayList<xxx.entity.ReviseInfo> from Object value (token JsonToken.START_OBJECT); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type java.util.ArrayList<xxx.entity.ReviseInfo> from Object value (token JsonToken.START_OBJECT)
at [Source: (PushbackInputStream); line: 1, column: 1]
【Controller】
@PostMapping("/add") public Result<String> insert(@RequestBody List<ReviseInfo> reviseInfoList){ return reviseAdaptor.insert(reviseInfoList); } 错误传参,报错
{ "reviseInfoList": [ { "fragOri": "宁厦", "fragFixed": "宁夏", "type": 1 }, { "fragOri": "历案", "fragFixed": "立案", "type": 2 }, { "fragOri": "沈查", "
目录
vue
概述
MVVM框架
入门案例 创建HTML文件,并引入vue.js
练习
Vue的基础语法
–1,运算符&函数
–2,解析类型丰富的data
–3,data的三种写法
二,Vue的指令
–1,概述
–2,v-model & v-cloak
-3,v-if & v-show & v-for
–4,v-on & v-bind
三,Vue组件Component
–1,概述
–2,全局组件
–3,局部组件
四,Vue的Ajax
–1,Ajax的概述
–2,Ajax的原理
–3,axios(导入)
–4,测试
五,Vue路由
–1,概述
–2,使用步骤(测试)
–3,总结
扩展:
–1观察者模式
HBuilderX自定义模板
–1,自定义HTML模板
–2,vue模板.txt
–3,创建新文件调用模板
vue 概述 是一个轻量级的前端框架.封装了HTML CSS JS的代码.
特点:
1, 是一个轻量级的 渐进式的框架, 按需配置
2, 实现了数据驱动/双向绑定 和 组件化的思想(高内聚)
3, vue框架可以避免了DOM的API
4, 遵循了MVVM设计模式,实现前端代码的松耦合
M是Model,是指数据
V是View,是指视图
VM是ViewModel,是指在指定视图里渲染指定数据
官网:
https://cn.vuejs.org/ #官网
https://cdn.jsdelivr.net/npm/vue/dist/vue.js #下载最新版本
从github下载gcc 源码
https://github.com/gcc-mirror/gcc/tree/releases/gcc-4.9.0安装必要的包
yum install -y gmp-devel.x86_64 libmpc-devel.x86_64 mpfr-devel.x86_64 mpfr.x86_64 bison build-essential flex make automake gcc gcc-c++ kernel-devel glibc*.i686 libgcc*.i686 texi2html texinfo*解压缩gcc源码,cd到源码目录如有需要可以执行源码目录下contrib/download_prerequisites脚本下载必要的组件mkdir build && cd build…/configure --prefix=/opt/gcc-4.9/make -j64make install
Vue3复习和总结(base)条件与列表渲染与Key的作用 代码全部放在->github仓库:https://github.com/zyugat/vue-review-all
前言:分为base、Component、router、Vuex、组合式API。5各部分。
base和Component中的例子不使用脚手架运行,需自行浏览器运行。位置->noCli
条件与列表渲染与Key的作用 Vue3复习和总结(base)条件与列表渲染与Key的作用条件与列表渲染v-if、v-else-if、v-elsev-showv-for Key的作用 条件与列表渲染 v-if、v-else-if、v-else 用于切换频率较低的场景、不展示的DOM元素直接被移除。 v-show 切换频率较高的场景、不展示的DOM元素使用样式隐藏掉。 <div id="app"> <h2 v-if="vif">v-if测试</h2> <h2 v-if="velseif">v-else-if测试</h2> <h2 v-else>v-else测试-------</h2> <button @click="vif = !vif">v-if切换</button> <button @click="velseif = !velseif">v-else-if切换</button> <h2 v-show="vshow">v-show</h2> <br/> <button @click="vshow = !vshow">v-show切换</button> <hr/> </div> <script> const App = { data() { return { vif: true, velseif: true, vshow: true } }, } const app = Vue.createApp(App) app.component('', {}) app.mount('#app') </script> v-for 当遍历数组时—>值、索引当遍历对象时->值、键——————值、键、索引当遍历字符串时—>值、索引 <div id="app"> <ul> <h3>数组遍历,value</h3> <li v-for="
关于SubSonic3.0生成的表名自动加复数(s)的“用户代码未处理SqlException,对象名'xxxs'无效”异常处理
参考文章:
(1)关于SubSonic3.0生成的表名自动加复数(s)的“用户代码未处理SqlException,对象名'xxxs'无效”异常处理
(2)https://www.cnblogs.com/EmptyFS/p/3218995.html
备忘一下。
push to origin/master was rejected错误解决方案(IDEA)
参考文章:
(1)push to origin/master was rejected错误解决方案(IDEA)
(2)https://www.cnblogs.com/shundong106/p/10995693.html
备忘一下。
原因是mysql版本太高,datax 数据库驱动很低。
解决方案1:
1.查看 mysql当前版本 mysql -V
2.去datax安装目录/datax/plugin/writer/mysqlwriter/libs查看mysql驱动版本
3.下载mysql相同的驱动放入到/datax/plugin/writer/mysqlwriter/libs即可(reader读取同理)
解决方案2:
通过关键字:could not retrieve transation read-only status server 百度搜索得出大概有如下几种可能出错原因及解决方案:
1.当MySQL的数据库隔离级别为REPEATABLE-READ时,查询一个select语句也算是事物的开始,而且在程序里会把以select语句开头的事务标记为只读事务,此时在这个事务里再执行insert、update、delete等DML语句就会出现如上的异常信息。
解决方案为:
通过修改MySQL的事务隔离级别实现,查看当前MySQL数据库的事务隔离级别,输入命令 “ show variables like 'transaction_%'; ” 。 将隔离级别修改为 -> READ-COMMITTED 即可,输入命令 “ SET GLOBAL transaction_isolation='READ-COMMITTED'; ” 即可解决该问题了。
环境变量的配置不成功的解决方法
参考文章:
(1)环境变量的配置不成功的解决方法
(2)https://www.cnblogs.com/johnsonwei/p/5983429.html
备忘一下。
main()如果返回0,则代表程序正常退出,返回非零代表程序异常退出。
参考文章:
(1)main()如果返回0,则代表程序正常退出,返回非零代表程序异常退出。
(2)https://www.cnblogs.com/findumars/p/7235153.html
备忘一下。
文章目录 映射函数从映射函数计算查找表使用数组切片并行处理 最近的图像处理涉及到了很多重映射的算法,比如 线性对比度变换, 伽马变换, 二值化, 对数变换, 直方图均衡化等,这些算法具有以下特性: 基于每一个像素点的处理一对一或多对一的映射,不存在一对多的映射每一个像素点之间没有关联 以上特点使得这类重映射算法可以用向量化运算做并行处理。
映射函数 这里以图像的伽马变换为例子,伽马变换实际上是将颜色数据规格化到[0,1]并取幂函数的值,即以下的函数关系。
f ( x ) = ( ( x / 255 ) g a m m a ) × 255 f(x)=((x/255)^{gamma})\times255 f(x)=((x/255)gamma)×255
从映射函数计算查找表 由于颜色数据的类型是uint8,并且不存在一对多的映射,所以我们可以制作一个长度为256的查找表用来存储结果。方法很简单,只需要把range(0,256)序列作为上述函数的输入即可。
#关键代码 np.power(np.arange(0,256)/255,val)*255 #实际代码 Map = np.clip(np.round(np.power((np.arange(0,256).astype(np.float64))/255,val)*255),0,255).astype(np.uint8) 由于整型数据可能会上溢,所以这里将np.arange(0,256)转换为浮点型
输出类型是uint8,为了避免转换成短类型溢出,需要四舍五入并且钳制到[0,255]
最后转换成uint8即可。
使用数组切片并行处理 这里把img.data[:,:,:](即x坐标,y坐标,颜色通道)作为下标去索引map查找表,此时data会被替换成查找表对应的值
img.data = Map[img.data[:,:,:]].astype(np.uint8)
原创教程 / 2021-11-16 / 文章字数2300
文章简述:本文介绍使用OBS无延迟直播插件在第三方云平台,如何实现超低延时直播的完整教程(延迟约为400毫秒,通常延迟是3-15秒)。
OBS简要介绍 OBS(Open Broadcaster Software)是一款免费开源的视频录制和视频直播推流软件,功能非常强大,在做视频直播时经常会用到,支持Windows, Mac以及Linux等不同平台。基于OBS,可以很方便的实现摄像机采集卡画面、桌面、文档、多媒体等不同形式的画面采集和输出。
OBS常用于峰会论坛直播、培训直播、带货直播、展会直播、宣讲会直播等,应用非常广泛,官网下载地址是 Open Broadcaster Software | OBS (官网下载非常慢,可以考虑到国内境相站下载)。
图1 / OBS客户端操作主界面
我们常见的直播架构是 CDN + RTMP/HTTP-FLV + HLS,目前绝大部分直播都是应用的这类技术。
RTMP/HTTP-FLV的延迟:大至是3-10秒左右,延迟的原因主要来自编码延迟、网络延迟、缓冲延迟等;
HLS的延迟:通常会在5-15秒左右,延迟主要自编码延迟、网络延迟、切片延迟等;
对于不涉及直播互动的场景,这种延迟对于观看者来说,感知不会特别明显;对于一些像视频连麦、答题场景、在线课堂、带货直播这类高互动性的场景,对延迟几秒就会有明显的感知。那么如何通过OBS做到无延迟直播、超低延迟直播呢?现在可以通过保利威无延迟直播(PRTC)来实现,基于WebRTC开发的PRTC无延迟直播,可以打通直播体验的「最后一公里」,将直播延迟降至1秒以内,下面来介绍一下如何操作吧。
OBS实现无延迟直播 1. 下载“obs-rtc-output插件” 打开CSDN,进入下载页 https://download.csdn.net/download/suny2020/40278486,进行插件下载。
2. 安装插件 第1步:分别打开obs-studio客户端安装目录和插件目录,如下,将插件目录下的“bin”、“obs-plugins”目录复制到obs-studio目录中。
图2 / OBS安装目录和插件目录截图
第2步:设置自定义服务。
方式1:用插件包中的文件services.json替换obs的配置目录(C:\Users\用户名\AppData\Roaming\obs-studio \plugin_config\rtmp-services)下的services.json
方式2:修改obs的配置目录下的services.json文件,如下:
{"name":"保利威无延迟","common":false,"servers":[{"name":"全球节点","url":"https://prtc.com/api/v1/"}],"recommended":{"keyint":1,"output":"rtc_output","max audio bitrate":160,"max video bitrate":2000,"profile":"main","bframes":0}}
图3 / OBS配置文件services.json截图
3. 创建频道 第1步:登录保利威管理平台(如果没有账号,可以点击此处直接注册试用账号https://my.polyv.net/v3/register/),选择进入云直播;
第2步:新建直播频道,在“直播延迟”选项中选择“无延迟”,然后点击“保存并创建直播”;
图4 / 云直播管理平台新建直播频道截图
第3步:创建后,平台会自动分配一个频道号和密码,如下标红处,记下这个频道和密码,在之后的“串流密钥”中,需要用到。
本次创建的这个无延迟直播道号是2662663,密码是123456,对应的“串流密钥”就是:{"channelId":"2662663","password":"123456","name":"test"} 。
图5 / 云直播管理平台获取频道号和密码
4.发起直播 第1步:打开OBS客户端,添加好场景和视频源,点击右下角的“设置”,如下图:
图6 / OBS客户端操作界面
1.
文字描述;
1.定义一个标识符N等于8;
2.声明两个整数类型常量x=2,z=1;
3.声明一个double类型的常量y=1.2;
4.用Switch判断x
5.x等于2 执行y++;x等于字符0 y=3 都不符合 y=1.2;
6.输出y的值;
流程图
代码:
#include<stdio.h>
int main()
#define N 8
{
int x = 2, z = 1;
double y = 1.2;
switch (x)
{
case 2:
y++;
break;
case '0':
y = 3;
}
printf("%.2f\n", y);
}
截图:
2.
文字描述;
1.声明两个整型变量x,y;
2.输入x,y的值;
3.用switch语句判断(x - abs(x))
4.等于0 y=1 ;否则y=-1
5.输出y的值;
流程图:
代码:
#include<stdio.h>
int main()
{
int x, y;
上周弄完服务器安装了个宝塔,本来准备根据之前得日志将环境简单不是一下,然后发现还是挺麻烦得,反正是个人服务器,就用宝塔进行环境搭建,顺便看下这款工具的使用
不用不知道,这块工具还是极度方便得,跟之前工作做的一款一键部署得基本上差不多,该有的功能都有,而且及其方便,最最最关键得是大部分功能都是免费得,基本运维免费得功能已经能够满足,一般小微企业完成可以用这款工具节省大量人力成本。
首先首页得可视化界面显示了当前linux服务器得基本使用情况,我买的是二核2G 80G存储得服务器,简单的部署了一些环境之后cup和存储都还好,运行内存已经过了一半了,下次再续费得搞个8G得运行内存得了。
数据库得安装 软件商店 首页得软件商店,找到mysql数据库,直接安装即可。
完全自动安装,不需要手动修改配置文件
在已购买就能看到已经安装完成得mysql数据库,可以将在首页显示点击勾选,在首页就能直接进入msql得相关配置界面了
点击设置就能对mysql进行配置,这点是我最喜欢得地方,进入之后对于mysql得启动,停止和重载配置都有按钮,完全不需要再去远程连接linux系统
配置得修改,也不需要再去修改mysql.conf文件,直接在页面就可以修改配置文件(端口,登录密码等),这点也是大赞。当然改完需要重新载入配置文件
后面还有一些其他功能暂时没用就不说了,自己随便点点就能感受到可视化得亲切感,当然老鸟喜欢敲命令当我没说。
文件和终端 之前一台服务器得运维是极度麻烦得一件事,公司规范文档清楚的还好,大部分公司人员流动加上没规范,,想要修改个数据库的配置都得改半天,因为不知道软件安装位置,每个人安装的位置都不一样,还会把安装后得启动文件,配置文件等放在不同得自己命名得文件夹下面,只能 ps -ef|grep mysql 或者where等命令一个一个查找
宝塔得软件管理页面,可以直接点击图标跳转到文件页面,就是当前软件得安装目录。
这个页面就相当于集成了FTP工具,想要上传文件或者看文件列表结构完全不需要再额外得下载linux连接工具,在这里就可以完成文件得上传,远程下载,新建目录,删除目录。
文件功能下面就是终端功能,就相当于取代XShell工具,完成可以在这个平台上完成日常运维。
安全 按道理完成上面得一键安装,设置完密码之后,就可以用navicat连接,但是还是连接不成功。
首先可能是外网访问不到端口,我们得去阿里云得安全组开放3306端口。当然我之前已经把所有端口都开放了,现在还是连接不上。
这就是宝塔得好处和不好得地方,通过宝塔安装的软件,除了在阿里云开放端口之外还需要在宝塔面板得安全,手动得将端口通行,不然还是无法访问。
一般来说,按照以上得操作基本上就可以连接成功了,之前安装得禅道禅道安装就是访问不了,最后在安全->19000放行就可以正常访问了,但是宝塔安装得数据库还是无法通过navicat访问。
这个和自己安装得mysql不一样,安装完成navicat连接新增数据库,这块必须在宝塔面板新增自己得数据库,数据库命名还必须和用户名一致,然后还需要设置权限,改成所有人即可。
这也好处就是数据库得一件监控和简单功能可通过这个功能实现,不好得地方就是数据库名和用户名必须一致,这块无法理解。
redis安装 通过mysql得安装,基本上踩过的坑其他软件都能正常安装了
这块禅道部署完只要安全那块端口放行就可以访问。
jdk这块建议安装java一件部署,选择tomcat8,jdk版本就是jdk1.8
redis也是一键安装,但是安装后端口方向也是无法直接访问得。
需要将bind不设置才能通过可视化测试工具连接,但是这块又做了非空得限制。
我们需要手动得去配置文件将bind属性注释即可。
Python 爬虫爬取学校官网新闻标题与链接(进阶) 前言一、拼接路径二、存储三、读取翻页数据四、完整代码展示五、小结 前言 ⭐ 本文基于学校的课程内容进行总结,所爬取的数据均为学习使用,请勿用于其他用途
准备工作: 爬取地址:https://www.hist.edu.cn/index/sy/kyyw.htm爬取目的:爬取全部新闻的标题与链接(绝对路径)并存储了解前导文章 Python 数据采集-爬取学校官网新闻标题与链接(基础) 环境需求:安装扩展库 BeautifulSoup、urllib(⭐不会安装点这里 Python 下载安装第三方库)基本知识: 了解网页的基本知识掌握 python 基础语法掌握 python 文件写入的语法 一、拼接路径 上一篇文章中,我们获得的网页链接是网页的相对路径,不是可以即时使用的链接,如下所示:
而我们常见的链接都是形如以下:
https://blog.csdn.net/Pola_/article/details/121316947?spm=1001.2014.3001.5501
这种链接都是可以即时使用的链接,那么能不能把上面的链接也换成可以即时使用的形式呢?我们需要用到 urllib 库的 urljoin() 去拼接地址,urljoin() 的第一个参数是基础母站的 url, 第二个是需要拼接成绝对路径的 url,利用 urljoin,我们可以将之前爬取到的 url 的相对路径拼接成绝对路径。
首先我们需要知道之前爬取到的 url 的基础母站是谁?很简单,将新闻的链接与我们爬取到的链接对比一下就可以知道基础母站,如下所示,基础母站即为 https:www.hist.edu.cn/:
其次是知道需要拼接成绝对路径的 url,也就是我们之前爬取到的 url
两个参数具备之后,我们就可以使用 urljoin() 进行拼接路径了,具体如下:
import urllib.request from urllib.parse import urljoin from bs4 import BeautifulSoup # 读取给定 url 的 html 代码 response = urllib.request.urlopen('https://www.hist.edu.cn/index/sy/kyyw.htm') content = response.read().decode('utf-8') # 转换读取到的 html 文档 soup = BeautifulSoup(content, 'html.
问题:idea有的弹框没有close或cancel按钮,如下:
解决方案:鼠标点击弹框区域,然后按键盘esc键,即可关闭
请求和响应 发送HTTP请求
在现实使用场景中,如果需要考虑与HTTP服务交互,一种常见的思考方式是:“我想构建一个URL,然后调用它”。Flurl.Http允许您非常简洁地表达这一点,比如:
using Flurl; using Flurl.Http; var result = await baseUrl.AppendPathSegment("endpoint").GetAsync(); 上面的代码示例为:发送一个HTTP GET请求并返回一个IFlurlResponse,从这个IFlurlResponse中,你可以通过GetStringAsync和GetJsonAsync等方法获得如:状态码(StatusCode)、请求头和主体等内容。
但通常情况下你只是想直接获取请求主体的内容和信息,Flurl提供了各种快捷方式来实现这一点,比如:
T poco = await "http://api.foo.com".GetJsonAsync<T>(); string text = await "http://site.com/readme.txt".GetStringAsync(); byte[] bytes = await "http://site.com/image.jpg".GetBytesAsync(); Stream stream = await "http://site.com/music.mp3".GetStreamAsync(); 对于JSON API,通常最好定义一个与预期JSON响应数据类型匹配的类(T)。但如果你不想创建这个匹配的类,也可以换动态(dynamic)的对象,比如:
dynamic d = await "http://api.foo.com".GetJsonAsync(); 或者,从返回JSON数组的API中获取一个动态列表,比如:
var list = await "http://api.foo.com".GetJsonListAsync(); 下载文件
你也可以使用Flurl从指定URL下载文件,比如:
// 这里的filename是可选的;如果不指定,默认会使用远程文件的文件名 var path = await "http://files.foo.com/image.jpg".DownloadFileAsync("c:\\downloads", filename); 读取其他信息
从请求中读取其他(如:头部信息等):
var headResponse = await "http://api.foo.com".HeadAsync(); var optionsResponse = await "
github:https://github.com/SPECTRELWF/pytorch-GAN-study
网络结构 最近在疯狂补深度学习一些基本架构的基础,看了一下大佬的GAN的原始论文,说实话一头雾水,不是能看的很懂。推荐B站李宏毅老师的机器学习2021的课程,听完以后明白多了。原始论文中就说了一个generator和一个discriminator的结构,并没有细节的说具体是怎么去定义的,对新手不太友好,参考了Github的Pytorch-Gan-master仓库的代码,做了一下照搬吧,照着敲一边代码就明白了GAN的思想了。网上找了一张稍微好点的网络结构图:
因为生成对抗网络需要去度量两个分布之间的距离,原始的GAN并没有一个很好的度量,具体细节可以看李宏毅老师的课。导致GAN的训练会比较困难,而且整个LOSS是基本无变化的,但从肉眼上还是能清楚的看到生成的结果在变好。
数据集介绍 使用的是网络上的二次元人脸数据集,数据集链接:
网盘链接:https://pan.baidu.com/s/1MFulwMQJ78U2MCqRUYjkMg
提取码:58v6
其中包含16412张二次元人脸图像,每张图片的分辨率为96*96,
只需要在我上一篇文章MNIST手写数字生成的基础上修改一下dataload就行,完整代码可以去github下载
generator # 定义生成器 class Generator(nn.Module): def __init__(self): super(Generator, self).__init__() def block(in_feat, out_feat, normalize=True): layers = [nn.Linear(in_feat, out_feat)] if normalize: layers.append(nn.BatchNorm1d(out_feat, 0.8)) layers.append(nn.LeakyReLU(0.2, inplace=True)) return layers self.model = nn.Sequential( * block(opt.latent_dim,128,normalize=False), * block(128,256), * block(256,512), * block(512,1024), nn.Linear(1024,int(np.prod(image_shape))), nn.Tanh() ) def forward(self,z): img = self.model(z) img = img.view(img.size(0),*image_shape) return img discriminator class Discriminator(nn.Module): def __init__(self): super(Discriminator,self).__init__() self.model = nn.Sequential( nn.Linear(int(np.prod(image_shape)),512), nn.
为了避免直接进入项目中存在的页面,使用filter过滤器
新建一个类loginFilter:
package com.tjcu.filter; import com.tjcu.entity.User; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; public class loginFilter implements Filter{ @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpSession session = request.getSession(); User user = (User) session.getAttribute("user"); HttpServletResponse response = (HttpServletResponse) servletResponse; if (user!=null) { filterChain.doFilter(request,response); }else { response.sendRedirect(request.getContextPath()+"/login.jsp"); } } @Override public void destroy() { } } 在web文件中通知服务器开发了这个过滤器
目录
一、数组中涉及的常见算法
二、数组算法练习
T1:创建一个长度为6的int型数组,要求取值为1-30,同时元素值各不相同。
T2:回形数格式方阵的实现
T3:求数组中的最大值、最小值、平均数、总数
T4:数组复制
T5:数组的反转
T6:数组的线性查找
T7:数组的二分查找
三、排序算法
四、算法的五大特征 一、数组中涉及的常见算法 1、数组元素的赋值(杨辉三角、回形数等);
2、求数值型数组中元素的最大值、最小值、平均数、总和等;
3、数组的复制、反转、查找(线性查找、二分法查找);
4、数组元素的排序算法;
二、数组算法练习 T1:创建一个长度为6的int型数组,要求取值为1-30,同时元素值各不相同。 方式一:
public class TestProject { public static void main(String[] args) { int[] arr = new int[6]; for (int i = 0; i < arr.length; i++) { arr[i] = (int) (Math.random() * 30) + 1;//随机生成第i+1个数 boolean flag = false; while (true) { for (int j = 0; j < i; j++) {//将第i+1个数前面的数分别与第i+1个数比较,相同则 //重新生成。 if (arr[i] == arr[j]) { flag = true; break; } } if (flag) { arr[i] = (int) Math.
文章目录 #!/bin/bash #在/opt/目录下创建“ip.txt”文本,并放入需要测试的ip以作后续测试 a=`cat /opt/ip.txt` #在/opt目录下创建这三个txt文本 cd /opt >./result.txt >./result1.txt >./result2.txt #for循环,ping“ip.txt”内的ip,一共5次,间隔0.5s,结果输入至“result.log” for i in $a do ping -c 5 -i 0.5 $i >./result.log #首先,总体判断一下有无丢包情况 loss=`cat ./result.log | grep loss | grep -v grep | awk -F , '{print $3}' | awk -F % '{print $1}' | sed s/[[:space:]]//g` if [ "$loss" -ge 1 ];then echo $i >>./result1.txt continue fi #如果没有丢包,则判断延时情况 cat ./result.log | grep from | grep -v grep | while read line do #获取ping命令的延时 delay=`echo $line | awk -F = '{print $4}' | awk '{print $1}'` if [ `echo "
一、
1.
文字描述:
1. 声明两个整型变量m=23,n=5;
2.输出 (!m + m % n)的值;
流程图:
代码:
#include<stdio.h>
int main()
{
int m = 23, n = 5;
printf("%d\n", !m + m % n);
return 0;
}
截图;
6.
文字描述:
1.声明两个整型变量x=1,y=2;
2.输出 (x > y) && (--x > 0)的值;
流程图:
代码:
#include<stdio.h>
int main()
{
int x = 1, y = 2;
printf("%d\n", (x > y) && (--x > 0));
return 0;
}
网上MMDetection的教程看似有很多,但感觉都不成系统,看完一圈下来还是不知道MMDetection要怎么用。这里还是推荐直接跟着官方教程,结合源码学习MMDetection,相关链接汇总如下:
官方教程 - MMCV官方教程 - MMDetection官方教程 - 不得不知的 MMDetection 学习路线(个人经验版)西安交大课件 - mmdetection教程(使用篇) 本文会介绍如何在MMDetection中从头开始搭建一套属于自己的算法。前几篇博客算是本人学习过程中的笔记,从源码本身分析了MMDetection的原理,比较细碎,本篇博客会从宏观的角度重新梳理一下MMDetection的使用方法以及流程原理,算是对之前一个月学习过程的总结。
MMDetection框架入门教程(一):Anaconda3下的安装教程(mmdet+mmdet3d)MMDetection框架入门教程(二):快速上手教程MMDetection框架入门教程(三):配置文件详细解析MMDetection框架入门教程(四):注册机制详解MMDetection框架入门教程(五):Runner和Hook详细解析 1. 框架概述 MMDetection是商汤和港中文大学针对目标检测任务推出的一个开源项目,它基于Pytorch实现了大量的目标检测算法,把数据集构建、模型搭建、训练策略等过程都封装成了一个个模块,通过模块调用的方式,我们能够以很少的代码量实现一个新算法,大大提高了代码复用率。
整个MMLab家族除了MMDetection,还包含针对目标跟踪任务的MMTracking,针对3D目标检测任务的MMDetection3D等开源项目,他们都是以Pytorch和MMCV以基础。Pytorch不需要过多介绍,MMCV是一个面向计算机视觉的基础库,最主要作用是提供了基于Pytorch的通用训练框架,比如我们常提到的Registry、Runner、Hook等功能都是在MMCV中支持的。另外,MMCV还提供了通用IO接口、多种CNN网络结构、高质量实现的常见CUDA算子,这里就不进一步展开了。
2. 框架整体流程 2.1 Pytorch 我们使用Pytorch构建一个新算法时,通常包含如下几步:
构建数据集:新建一个类,并继承Dataset类,重写__getitem__()方法实现数据和标签的加载和遍历功能,并以pipeline的方式定义数据预处理流程构建数据加载器:传入相应的参数实例化DataLoader构建模型:新建一个类,并继承Module类,重写forward()函数定义模型的前向过程定义损失函数和优化器:根据算法选择合适和损失函数和优化器训练和验证:循环从DataLoader中获取数据和标签,送入网络模型,计算loss,根据反传的梯度使用优化器进行迭代优化其他操作:在主调函数里可以任意穿插训练Tricks、日志打印、检查点保存等操作 2.2 MMDetection 使用Pytorch构建一个新算法时,通常包含如下几步:
注册数据集:CustomDataset是MMDetection在原始的Dataset基础上的再次封装,其__getitem__()方法会根据训练和测试模式分别重定向到prepare_train_img()和prepare_test_img()函数。用户以继承CustomDataset类的方式构建自己的数据集时,需要重写load_annotations()和get_ann_info()函数,定义数据和标签的加载及遍历方式。完成数据集类的定义后,还需要使用DATASETS.register_module()进行模块注册。注册模型:模型构建的方式和Pytorch类似,都是新建一个Module的子类然后重写forward()函数。唯一的区别在于MMDetection中需要继承BaseModule而不是Module,BaseModule是Module的子类,MMLab中的任何模型都必须继承此类。另外,MMDetection将一个完整的模型拆分为backbone、neck和head三部分进行管理,所以用户需要按照这种方式,将算法模型拆解成3个类,分别使用BACKBONES.register_module()、NECKS.register_module()和HEADS.register_module()完成模块注册。构建配置文件:配置文件用于配置算法各个组件的运行参数,大体上可以包含四个部分:datasets、models、schedules和runtime。完成相应模块的定义和注册后,在配置文件中配置好相应的运行参数,然后MMDetection就会通过Registry类读取并解析配置文件,完成模块的实例化。另外,配置文件可以通过_base_字段实现继承功能,以提高代码复用率。训练和验证:在完成各模块的代码实现、模块的注册、配置文件的编写后,就可以使用./tools/train.py和./tools/test.py对模型进行训练和验证,不需要用户编写额外的代码。 2.3 流程对比 虽然从步骤上看MMDetection相比Pytorch的算法实现步骤存在挺大差异,但底层的逻辑实现和Pytorch本质上还是一样的,可以参考下图对照着进行理解,其中蓝色部分表示Pytorch流程,橙色部分表示MMDetection流程,绿色部分表示和算法框架无关的通用流程。
在开始接触MMDetection的算法实现流程之前,必须要先对注册机制和Hook机制有一个大致的了解,推荐先快速阅读,对注册机制和Hook机制先有一个大体上的了解,看完第五章后再回过头来看注册机制和Hook机制的细节部分会有更深的体会。
3. 注册机制 3.1 Registry类 MMDetection作为MMCV的下游项目,继承了MMCV的模块管理方式——注册机制。简单来说,注册机制就是维护几张查询表,key是模块的名称,value是模块的句柄,每张查询表都管理一批功能相似的不同模块。我们每新建一个模块,都要根据模块实现的功能将对应的key-value查询对保存到对应的查询表中,这个保存的过程就称为“注册”。当我们想要调用某个模块时,只需要根据模块名称从查询表中找到对应的模块句柄,然后就能完成模块初始化或方法调用等操作。MMCV通过Registry类来实现字符串(key)到类(value)的映射。
Registry的构造函数如下所示,变量self._module_dict就是上面提到的“查询表”,注册的模块都会存到这个字典类型的变量里,新建一个Registry实例就是新建一张查询表。另外,Registry还支持继承机制。
from mmcv.utils import Registry class Registry: # 构造函数 def __init__(self, name, build_func=None, parent=None, scope=None): # 注册器的名称 self._name = name # 使用module_dict管理字符串到类的映射 self._module_dict = dict() # 使用children管理注册器的子类 self._children = dict() # build_func按照如下优先级初始化: # 1.
Java SE 1.6 为了减少获得锁和释放锁带来的性能消耗,引入了偏向锁和轻量级锁;在Java SE 1.6 中,锁共有4种状态,级别从底到高依次是:无锁状态、偏向锁状态、轻量级锁和重量级锁状态,这几种状态会随着竞争情况加剧逐渐升级。锁可以升级但不能降级。
1.偏向锁 HotSpot的作者经过研究发现,大多数情况下,锁不仅存在多线程竞争,而且总是由同一线程多次获得,为了让线程获得锁的代价更低而引入了偏向锁。
(1)偏向锁的获取 注意:当JVM启动了偏向锁模式(Java 6和Java 7里是默认启动的),新创建对象的Mark Word中的ThreadID为0,说明此对象处于偏向锁状态(但未偏向任何线程),也叫作匿名偏向锁状态。
线程A第一次访问同步代码块时,先检查对象头Mark Word中锁标志位是否为01,依此判断此时对象是否处于无锁状态或者偏向锁状态;
若锁标志位是为01,然后判断偏向锁的标识是否为1:
2.1 如果不是,则进入轻量级锁逻辑(使用CAS竞争锁)(注意:此时不是使用CAS尝试获取偏向锁,而是直接升级为轻量级锁;原因是:当偏向锁的标识为0时,表明偏向锁在此对象上被禁用,禁用原因可能是JVM关闭了偏向锁模式,或该类刚经历过bulk revocation,等等。所以应该入轻量级锁逻辑);
2.2 如果是1,表明此对象是偏向锁状态,则进行下一步流程。
判断是偏向锁时,检查对象头Mark Word中记录的ThreadID是否是当前线程A的ID:
3.1 如果是,则表明当前线程A已经获得过该对象锁,以后线程A进入同步代码块时,不需要CAS进行加锁,只会往当前线程A的栈中添加一条Displaced Mark Word为空的Lock Record,用来统计重入的次数。如下图。
3.2 如果不是,则进行CAS操作,尝试将当前线程A的ID替换进Mark Word;
3.2.1 .如果当前对象锁的ThreadID为0(匿名偏向锁状态),则会替换成功(将Mark Word中的Thread id由匿名0改成当前线程A的ID,在当前线程A栈中找到内存地址最高的可用Lock Record,将线程A的ID存入),获得到锁,执行同步代码块。
3.2.2 .如果当前对象锁的ThreadID不为0,即该对象锁已经被其他线程B占用了,则会替换失败,开始进行偏向锁撤销。这也是偏向锁的特点,一旦出现线程竞争,就会撤销偏向锁。
(2)偏向锁的撤销 偏向锁的撤销需要等待全局安全点(safe point,代表了一个状态,在该状态下所有线程都是暂停的,stop-the-world),到达全局安全点后,持有偏向锁的线程B也被暂停了。检查持有偏向锁的线程B的状态(会遍历当前JVM的所有线程,如果能找到线程B,则说明偏向的线程B还存活着):
5.1 如果线程还存活,则检查线程是否还在执行同步代码块中的代码:
5.1.1 如果是,则把该偏向锁升级为轻量级锁,且原持有偏向锁的线程B继续获得该轻量级锁。
5.2 如果线程未存活,或线程未在执行同步代码块中的代码,则进行校验是否允许重偏向:
5.2.1 如果不允许重偏向,则将Mark Word设置为无锁状态(未锁定不可偏向状态),然后升级为轻量级锁,进行CAS竞争锁。
5.2.2 如果允许重偏向,设置为匿名偏向锁状态(即线程B释放偏向锁)。当唤醒线程后,进行CAS将偏向锁重新指向线程A(在对象头和线程栈帧的锁记录中存储当前线程ID)。唤醒暂停的线程,从安全点继续执行代码。 补充: 每次进入同步块(即执行monitorenter)的时候都会以从高往低的顺序在栈中找到第一个可用的Lock Record,并设置偏向线程ID;每次解锁(即执行monitorexit)的时候都会从最低的一个Lock Record移除。所以如果能找到对应的Lock Record说明偏向的线程还在执行同步代码块中的代码。
下图为当对象所处于偏向锁时,当前线程重入3次,线程栈帧中Lock Record记录:
偏向锁的撤销
偏向锁
synchronized原理和偏向锁、轻量级锁、重量级锁的升级过程
Docker的基础知识 前提:有Linux的基础知识
1. Docker概述
问题:
一套产品会经历从开发到上线,但在这个过程会有两套以上的环境,经常会遇到一个问题:在不同环境下会出现不一样的bug,或者是生成环境遇到的bug,在开发环境上却没遇到等等;环境配置十分麻烦:发布项目=jar+环境(Redis+MySQL+jdk+ES等等; Docker解决方案 开发发布项目jar包时带上环境(docker将其打包成镜像),发布到docker仓库,测试或用户只需要下载镜像运行即可。
一个jre上可能运行多个应用造成冲突(例如端口),所以docker采用集装箱的思想,将各个应用隔开。Docker通过隔离机制将服务器利用到极致。
2.Docker作用
在说作用之前,先说说虚拟机技术
一个虚拟机包含一个内核,安装所有应用所需要的库,再安装不同的应用。
缺点:
1、资源占用多
2、冗余步骤多
3、启动慢 容器化技术
容器内的应用直接运行在宿主机内,容器没有自己的内核,相对轻便
并且容器间相互隔离,拥有自己的文件系统,互不影响
优点:
1、应用更快速地交付和部署
2、更便捷地进行升级和扩容
3、更简单进行系统运维(开发与测试环境高度一致)
4、更高效地利用计算资源(一台服务器使用多个容器,性能压榨到极致)
Docker的基本组成
镜像(image):
docker镜像相当于一个模板,通过镜像来创建容器服务,镜像AAA运行后可以提供AAA01(02、03)服务,通过镜像可创建多个服务
容器(container):
Docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建。
基本命令包含启动、停止、删除;
目前可简单地把容器理解为一个小的Linux
仓库(repository):
仓库就是存放镜像的地方,分私有仓库与共有仓库(Docker hub),国外的仓库可通过阿里云的容器服务器下载(配置镜像加速)
学习来源:https://www.bilibili.com/video/BV1og4y1q7M4?p=1
文章目录 11-13单值二叉树问题描述思路分析代码实现 相同的树问题描述思路分析代码实现 对称二叉树问题描述思路分析代码实现 另一颗树的子树问题描述思路分析代码实现 二叉树的前序遍历问题描述思路分析代码实现 二叉树构建及遍历问题描述思路分析代码实现 11-14翻转二叉树问题描述思路分析代码实现 二叉树的最大深度问题描述思路分析代码实现 平衡二叉树问题描述思路分析代码实现 分享一下着两天做的二叉树相关OJ题 11-13 单值二叉树 问题描述 https://leetcode-cn.com/problems/univalued-binary-tree/
思路分析 判断每个结点是否与孩子节点相等即可,每次比较该节点与某一孩子结点,然后再比较另一个结点,根据传递性可知,只要有一个不成立就返回失败,否则就递归往下比较。
代码实现 bool isUnivalTree(struct TreeNode* root) { //空树成功 if(root==NULL) return true; if(root->left!=NULL&&root->val!=root->left->val) return false; if(root->right!=NULL&&root->val!=root->right->val) return false; return isUnivalTree(root->left)&&isUnivalTree(root->right); } 相同的树 问题描述 https://leetcode-cn.com/problems/same-tree/submissions/
思路分析 逐个结点比较即可。
代码实现 bool isSameTree(struct TreeNode* p, struct TreeNode* q) { if(p==NULL&&q==NULL) return true; if(p==NULL||q==NULL) return false; if(p->val!=q->val) return false; return isSameTree(p->left,q->left)&&isSameTree(p->right,q->right); } 对称二叉树 问题描述 https://leetcode-cn.com/problems/symmetric-tree/
思路分析 是否关于中心对称,需要比较左右子树是否对称,左子树的左子树与右子树的右子树比较是否相等,左子树的右子树与右子树的左子树比较是否相等。比较相等代码类似上题。
代码实现 bool _isSymmetricTree(struct TreeNode* p, struct TreeNode* q) { if(p==NULL&&q==NULL) return true; if(p==NULL||q==NULL) return false; if(p->val!
Pycharm-Python 下载安装第三方库 一、安装第三方库00 新建项目02 两种安装方式① 通过代码提示安装② pip install 安装 二、小结 最近我使用 pip install 安装第三方库时出现了一些问题,不知道为什么,和我记忆中的安装方式不一样了,所以写篇文章记录一下,不知道有没有人和我一样的感觉。
关于问题的来源,我们从头开始说起吧:
一、安装第三方库 00 新建项目 ⭐① 新建一个 Python 项目,这里面需要注意一定要勾选 New environment using -> Vitualenv,这涉及了一个虚拟的 Python 环境搭建,我还没搞懂这个,但是不勾选的话,后期项目环境使用会出很多问题,所以一定要勾选!!!
02 两种安装方式 Pycharm 里我经常用的有两种安装方式:
① 通过代码提示安装 这种方式比较麻烦的在于你需要自己敲出导库的路径,然后将光标放在上面,Pycharm 会提示你进行安装,如下图所示,点击安装后,Pycharm 会自动帮你下载好,但偶尔也会有下载失败的情况,这里面有各种原因,例如网络不好之类的,所以并不是万分保险
② pip install 安装 这里就是我问题所在的根源,我印象里是直接在 terminal 里输入pip install 库名就能安装了,但是我现在用都会报错,后来我解决了问题,关键在于开头创建项目时勾选的虚拟环境,勾选后,新建项目下会有一个 venv 文件夹,里面存储的是 python 环境的所有配置,如下所示: 此时我们打开 terminal,如下所示:
然后按照以下步骤输入命令:
① 第一步,输入命令cd venv进入 venv 文件夹下,如下所示:
② 第二步,输入命令cd .\Scripts\进入 Scripts 文件夹下,如下所示:
此时,你可以输入命令ls检验一下,就可以看到其下有 pip3.exe,即我们可以使用 pip install,如下所示:
③ 第三步,输入命令pip install 库名 -i https://pypi.
使用pip install requests命令安装requests模块后,通过import requests命令无法调用,pycharm报:
import requests
ModuleNotFoundError: No module named 'requests'
主要原因是Pycharm中未安装requests
解决方法:在Pycharm中文件——设置(Ctrl+Alt+S)——项目——Python解释器——右侧有个‘+’,点击——搜索requests——安装软件包
完成后,即可进行调用requests
5.SSM框架整合 ssm:spring+spring mvc+mybatis
5.1 整合的场所:web.xml 通过监听器配置mybatis,通过servlet配置mvc。
web.xml: <?xml version="1.0" encoding="UTF-8" ?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <display-name>Archetype Created Web Application</display-name> <!--这是对mybatis的整合配置--> <!--上下文配置路径--> <context-param> <param-name>contextConfigLocation</param-name> <!--mybatis的配置文件--> <param-value>classpath:spring-mybatis.xml</param-value> </context-param> <!--配置上下文加载监听器,用来监听mybatis的配置文件--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--这是对spring mvc的整合配置--> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <!--mvc的配置文件--> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!--设置过滤器进行字符编码--> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <!--编码格式--> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <!--强制编码--> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app> 5.2 mvc和mybatis的配置文件: 5.
一.如何修改jz2440开发板IP 开头注意:在进行以下操作前必须已经跟着u-boot内核到开发板上,此外还要移植根文件系统到开发板上。
修改开发板IP有两种方式:
1.临时修改IP
2.永久修改IP
第一种是临时IP(即下次开发板上电IP变化)。在启动开发板后,输入语句:ifconfig eth0 IP(想要修改成的IP)。我这里用的是mobaxterm串口调试软件,我通过此软件使开发板与电脑连接,语句也是在此软件中输入
第二种是永久修改IP(即下次上电IP不变)。(这里重新说明下,我后来拔了网线后重插ip还是会变化,不是永久,有错误。)
首先,开发板设置为nor启动,启动开发板,倒数3秒按任意键进入boot菜单界面。按q推出。
其次,输入命令print可以看到开发板信息。如我这有一栏是 ipaddr :192.168.1.17
然后使用 set ipaddr 192.168.1.18 命令将IP地址修改成了192.168.1.18
使用 save 语句保存
最后, 重启开发板,按照前三步,重新print就可以看到修改后的开发板IP
上面那种重插网线后会恢复,如果想一劳永逸试试在脚本中修改:
二.开发板与Windows互ping问题 本来这个问题不应该是问题,韦东山老师的视频中讲解的都是通过路由器或者有线网卡与无线网卡同时有的情况下将开发板与pc机互通。但问题是我的电脑只有有线网卡,更为难的是我的网口只有一个,还没有路由器。
那么在这种情况下,如何操作才能让开发板与pc机互通呢?
买张无线网卡,给自己的电脑装上,并且能让自己的电脑连接稳定wifi或热点
买个路由器,或者网口扩展器,我上淘宝查了还真有usb转网线转换器。这种方式应该也可以,因为我认为能互相ping通的本质在于网络IP在同一频段下即可。因为上述方案都要花钱,我陷入了为难境地,但皇天不负有心人,我转头发现旁边座位也是有网口的。按捺心中欣喜,我查了一下连接旁边网线的电脑的ip,果然,与我的电脑在同一频段(实验室电脑都在同一频段)。于是我进行如下连接:
当然,在连线后为了以防万一,我依旧手动将我的开发板IP改成与我电脑同一频段的IP,最终pc机与开发板能互相ping通。 补充 在我执行开发板与pc机互通方法3之前,我试过将pc机网线拔下与开发板连接的操作,但是我拔下网线后,因为没有无线网卡的原因,我的电脑就不具备公网IP 了,故也无法与开发板互通。
总结 本文的重点在于如何操作才能让开发板与PC机互通,这里我认为一定要把握“同一网段”这四个字,其他的问题可以围绕着这个来进行试验解决。
我虚拟机设置的是NAT模式,与pc机可以互相ping通,故不在这演示开发板与虚拟机的互通。
对于本文有错误的地方,欢迎留言指正哈。
首先进行数据导入,这里我是导入从问卷星下载的数据
在变量视图中对1,2,3,4,5这样的数据,进行了值标签,方便于观察频率图
选择计数的降序排序相当于选择频数的降序排序
交叉组分析:
交叉组分析可以同时分析两个或两个以上的多变量的分布情况和相关分析,在列联表中输出各种百分比,期望频数,剩余,标准化剩余,同时显示交叉分组的频数条形图
简单的频数分布一次只分析一组变量,而交叉组分析可以同时分析两组变量及以上
将2.所在大学年级中导入【行】中,将6花费的时间导入【列】中,点击条形图作图
根据图表,大一学生人群中在网络上花费的时间是比较平均的,呈现两边低,中间高的现象,花费的时间程度是一般是最多的;大二学生人群在花费时间少的程度是最多的,大二的课程逐渐多了,导致学生上网的时间趋向少的程度,但是不凡存在上课上网;大三学生人群花费时间程度是一般是最多的,其次是多的程度;大四学生人群花费时间程度是多的是最多的;从大一到大四,学生在花费网络上的时间是逐渐增多的,而大四的空闲时间是最多的,学生花费在网络的时间可能也在增加
持续更新中…
关于re方法的补充 1、查找
如果遇到需要从一段字符串中取某类型的字符的话,往往采用re.search()和re.findall()方法
例如:我们需要取一段字符串“abcsdjkjj”中的最后一个字母 import re s1='abcsdjkjj' result=re.findall(r"[A-Za-z]",s1)[-1] print(result) 这里用了一个巧方法,把取最后一个字符放到了列表中,并没有用正则表达式来进行抓取,降低了难度。
把一个字符串中的所有字母找出来并拼成一个字符串
这时我们需要先用findall方法来找出所有字母,然后利用拼接的方法,即join()方法来进行连接即可。 import re pattern = re.compile(r"[A-Za-z]") result="".join(pattern.findall("a231afcr2f34feedf")) print(result) 学会了找字符串中的单个字母,我们还会遇到需要找单词的。这时只需要一个小变化,上面的r"[A-Za-z]“换成r”[A-Za-z]+" import re s="I am 13 years old" pattern = re.compile(r"[A-Za-z]+") result = pattern.findall(s) print(result) 2、特殊字符的使用
我们需要匹配出一行字符串中的所有开头的字母内容时,这时就需要靠字符规则了,首先想到的是’^’,但是肩号并不能匹配出所有的字母开头,而是匹配出一个字符串的第一个字母。
那么我们可以使用\b,这个代表着单词的开头或者结尾或者是单词的分界处的符号。
关于\b,在python02-正则表达式中我总结的比较浅,这里详解一下,\b就是隐式位置,隐式位置的含义为:前后必不全是\w。
例如:I have a nice girl。 其中的a表示为:
空格\ba\b空格,也就是说第一个\b隐式位置,前面是空格,后面是字符\w。代表的是单词开头,另一个\b,后面是空格,前面是字符,所以它代表的是单词的结尾。
记住:字符,空格均是显式位置,\b代表的是隐式位置,是不可见的。
那么我们要提取出一行字符串的所有开头字母,就可以用下面这种方法:
import re s="i love you not because of who you are!" print(re.findall(r"\b\w",s)) 3、字符集的使用
我们还会遇到需要匹配度比较高的字符串,比如需要匹配2,3,4或者多个按指定位置排列的字符串,那么我们可以采用python02中的‘[字符集]’方法:
写一个正则表达式,使其能同时识别下面所有的字符串:‘bat’,‘bit’, ‘but’, ‘hat’, ‘hit’, 'hut‘ import re s="
这里的filename是查询文档的名字
查看 1.文件最近内容修改的时间--mtime(默认)
命令:ls -l filename
2.文件最近被访问的时间 --atime
命令:ls -l --time=atime filename
3.文件最近权限和属性修改的时间--ctime
命令: ls -l --time=ctime filename
修改 touch [-acmt] filename
基本功能为将指定文件filename 的atime和mtime设置为当前时间
-a: 只重置访问时间atime
-m:只重置修改时间mtime
-c:只更新时间,不创建文件(三种时间都重置为当前时间)
-t:YYMMDDhhmm: 将文件的atime和mtime设置为指定时间,而非当前时间。
需要注意的是,
cat读文件时,mtime不变,atime和ctime重置。
vim读文件时,mtime和ctime不变,atime重置。
vim改文件内容时,mtime,ctime,atime都重置。
chmod改权限时,mtime和atime不变,ctime重置。
“21天好习惯”第一期-21 今天又巩固了一下循环语句,下面是小编我今天的学习成果;
#include<stdio.h>
int main()
{
int a=1,b=5,c,d;
int N;
printf("please enter d c N:");
scanf("%d%d%d",&d,&c,&N);
for(;d<N;)
{
a=a+1;
b=b*a;
c=a+1;
printf("%d\n",b+a);
d*=a;
}
printf("over");
return 0;
}
运行结果:
上一篇文章讲了如何用keras搭建我们自己的网络,并且讲解了里面的一些常用参数,本篇文章将简短的介绍如何用上一篇文章中的框架识别MNIST数据集。
MNIST 数据集已经是一个被”嚼烂”了的数据集, 很多教程都会对它”下手”, 几乎成为一个 “典范”
这里我们不太需要去官网下载,我们在第一次使用这个数据集的时候,会自动从官网下载,各位看官先继续往下看。
MNIST数据集: 提供6万张28*28像素点的0-9手写数字图片和标签,用于训练 提供1万张28*28像素点的0-9手写数字图片和标签,用于测试 导入MNIST mnist = tf.keras.datasets.mnist (x_train,y_train),(x_test,y_test) = mnist.load_data() 作为输入特征,输入神经网络时,将数据拉伸为一维数组 tf.keras.layers.Flatten() 首先咱们看看这个数据集里都是个什么东西
import tensorflow as tf from tensorflow import keras import matplotlib.pyplot as plt mnist = keras.datasets.mnist (x_train,y_train),(x_test,y_test) = mnist.load_data() print(x_train[0]) print(y_train[0]) for i in range(10): plt.imshow(x_train[i]) plt.show() 图片显示出来之后吧,它就是一个个的手写数字体图片,然后就想办法对这个玩意进行处理呗
通过第一张截图大家伙也看到了,图片值是从0-255的,但是吧,这个值在计算的时候有点大,所以咱就稍微做一下处理,变小点
x_train,x_test = x_train/255.0,x_test/255.0 哎,现在舒服了,x_train和x_test中每一个值都是0-1之间的了,做完预处理之后咱们就开始整网络结构呗,上篇咱咋说的来着?先把多维数组展平,然后再处理,所以需要
keras.layers.Flatten()这个东西放在第一层 然后吧,隐藏层是128神经元,输出层是10个神经元,因为数据集最后识别出来不是0-9这一共10个数字嘛,所以输出层神经元个数为10,中间那层,emmmmm,128是常用的可能,先按着来呗,具体为啥俺也不太清楚,有大佬(或者巨佬)明白的话可以评论区留下您的答案。
下面是网络构建的代码
model = keras.models.Sequential([ keras.layers.Flatten(), keras.layers.Dense(128,activation='relu'), keras.layers.Dense(10,activation='softmax') ]) 对了,这个最后一层如果是二分类的话,用sigmoid,如果是多分类,比如输出的结果有好多的话,就用softmax,小知识点,get了嘛-.-
然后就是compile,优化器选adam,损失函数选losses.SparseCategoricalCrossentropy,这些参数选取可以自己看着改,哪个效果好用哪个,如果不知道其他函数的话就先用我这个凑合凑合
配置完了就是fit训练,没啥好说的,下面放完整代码吧
import tensorflow as tf from tensorflow import keras import matplotlib.
报错 org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userMapper' defined in file [D:\code\community\target\classes\com\nowcoder\community\dao\UserMapper.class]: Unsatisfied dependency expressed through bean property 'sqlSessionFactory'; 原因 搜了一下是因为我写的user-mapper.xml写错了三个地方🤦
1 mapper.xml中有个id重复了 粘过来太粗心了没有修改,修改过来就好了
2 在select里多写了一个属性 我看官网这么写的,以为parameterType是方法的输入数据类型?
结果报错
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.type.TypeException: Could not set parameters for mapping 把这个属性删掉就好了
3 mapper.xml第一行 参考:https://blog.csdn.net/weixin_42847351/article/details/117263492
必须是<?xml version="1.0" encoding="UTF-8" ?>且最前面不能有空格,不然就报错
完整报错信息:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userMapper' defined in file [D:\code\community\target\classes\com\nowcoder\community\dao\UserMapper.class]: Unsatisfied dependency expressed through bean property 'sqlSessionFactory'; nested exception is org.