一、下载汉化包(链接如下) 链接:https://pan.baidu.com/s/1U_FMZuFvFQ9-_70whXcIwQ
提取码:2333
二、选择路径 将汉化包中的文件( CodeBlocks.mo、zh_CN.mo、zh_CN.po)放到CodeBlocks安装路径下的 CodeBlocks/share/CodeBlocks/locale/zh_CN 文件夹中,路径中的文件夹没有就新建。
注:此处需严格按照要求来,切勿自定义文件夹名
三、内部调试 打开CodeBlocks,依次选择Settings、Environment、View、勾选Internationalization、Chinese Simplified、OK。
重启CodeBlocks即可
一、关中断 处理器响应中断后,首先要保护 程序的现场状态,在保护现场过程中, CPU 不应该响应更高级中断源的中断请求 。否则 ,如果现场保 存不完整,在中断服务程序结束后,也就不能正确 地恢 复并继续执行 现行程序。 二、保存断点 为了保证中断服务程序执行完 毕后能 正确 地返回到原来的程序,必须将原来程序的断点保存起来。断点可以压入堆栈,也可以存入 主存 的特 定单元中。 三、引出中断服务程序 引出中 断服务程序的 实质就是取出中断服务程序的入口地址送入程序计数器( PC) 。 通常有两种方法寻址中断服务程序的入口地 址: 硬件向量法和 软件 查询法。 1.硬件向量法是通过硬件产生中断向量地址,再由中断向量地址找到中断服务程序的入口地址 。 2.软 件查询法是用软件编程的办法寻找入口地址。 四、保存现场和屏蔽字 进入中断服务程序后首先要保存现场,现场信息一般指的是程序状态字、中断屏蔽寄存器和CPU中某些寄存器的内容。
五、开中断 这将允许更高级中断请求得到响应, 实现中断嵌套。
六、执行中断服务程序 这是中断系统的核心。不同的中断请求会有不同的中断服务程序。
七、关中断 保 证在恢复 现场和 屏蔽字时不被 中断。 八、恢复现场和屏蔽字 将现场和屏蔽字恢复到原来的状态。 九、开中断及中断返回 中断服务程序的最后一条指令提交通常是一条中断返回指令 ,使其返回到原 程序的 断点处,以便 继续 执行原程序。 十、总结 知识拓展:
中断嵌套是指中断系统正在执⾏⼀个中断服务时,有另⼀个优先级更⾼的中断提出中断请求,这时会暂时终⽌当前正在执⾏的级别较低的中断源的服务程序,去处理级别更⾼的中断源,待处理完毕,再返回到被中断了的中断服务程序继续执⾏,这个过程就是中断嵌套。
RFID防碰撞算法算法复习 书本上的: 1:基于ALOHA的防冲突算法 纯ALOHA算法
阅读器广播识别命令给标签,标签收到阅读器发送命令后,立即以定长的信息包形式向阅读器发送其标识符号。
没有冲突:阅读器正确识别标签识别符并发送确认信息
发生冲突:阅读器向标签发送冲突确认
标签收到成功识别的确认信息,则不再发送标识符
未收到则将会随即独立的等待一段时间后再重新发送标识符,直到成功发送为止
信道利用率:18.4%
时隙ALOHA算法(S-ALOHA)
控制时隙的同步
将纯ALOHA算法的时间分为若干个时隙,每个时隙大于或等于标签识别符发送的时间长度,每个标签只能在时隙开始时刻发送标识符
信道利用率:36.8%
基于帧的时隙ALOHA算法(FSA)
三种类型的时隙:空闲时隙 单时隙 冲突时隙
在S-ALOHA算法的基础上,将若干个时隙组成为一帧,阅读器按帧为单元进行识别。
每一帧开始时,阅读器广播帧的长度f,指明下一个帧包含的时隙个数,并激活其识别区域中的所有标签。每个标签在接受到帧长f之后随机独立地在0--(f-1)中选择一个整数作为自己发送标识符的时隙序列号,并将这个时隙序列号寄存在SN中。在下一帧的每一个时隙中,阅读器通过时隙开始命令启动一个新的时隙,如果标签SN的值等于0则立即发送标识符号,如果不等于0则将其SN值减1而不发送标识符。
对标签而言:
标识符发送成功:标签进入休眠状态
冲突:进入等待状态,在下一帧中重新选择一个时隙发送标签符
信道利用率:当帧长的长度等于阅读器场内未识别标签的数目时,36.8%
动态帧时隙ALOHA算法(DFSA)
动态帧时隙ALOHA算法动态地调整帧长度,在每帧结束后,根据上一帧的反馈情况检测碰撞时隙数,单时隙数和空闲时隙数来估计当前未被正确识别的电子标签数目,然后选择最佳的下一帧的长度,把它的帧长作为下一轮识别的帧长。
2:基于二进制树的防冲突算法 按照递归的方式将冲突的标签集合划分为两个子集,直到集合中只剩下一个标签为止
划分子集合的算法:
随机二进制树算法:标签随机选择所属的集合
查询二进制树算法:按照标签的标识符划分子集
基于随机二进制树的防冲突算法
每个标签需要维持一个计数器,计数器初始值为0。在每个时隙开始时,如果标签的计数器为0则立即发送自己的标识符号,否则该时隙不响应。标签识别成功,进入沉默状态,每个时隙结束时阅读器会将接收到的时隙状态反馈给标签,场内的标签根据结束时阅读器反的结果对自己维持的计数器进行调整。
(1):冲突时隙:参与响应的标签从0/1中随机选择一个,将其加到自己的计数器上;没有参与的标签计数器加1。由此可以将冲突的标签分为两个集合。
(2):没有冲突:
单时隙,成功识别,进入沉默状态
没有被识别的标签自己减1
基于查询二进制树的防冲突算法
无状态协议,标签只需要根据阅读器广播的标识符前缀作比较,标签内部不需要标签维持任何状态。阅读器维持一个二进制前缀,初始值为0。每个时隙开始时,阅读器广播二进制前缀,标签将自己的标识符号前几位与此二进制前缀进行比较,相同则发送标识符号。否则,保持沉默。阅读器检测到冲突则在下次查询中将原来的二进制前缀后面增加0/1,重新查询。
3:轮训机制(看标签是否丢失) 基本的轮训机制:
阅读器根据查询列表逐个广播每一个标签的标识符号来检查此标签是否存在与阅读器的阅读范围内。阅读器每广播一个标识符号后就会等待一段时间,如果收到目标标签的确认则证明此标签存在,否则则认为该标签丢失。
这个基本轮训机制存在很大的缺陷:首先就是此机制与EPC C1G2标准中的时隙ALOHA协议不兼容,难以被目前的商用阅读器采用。其次就是当标签规模较大时,标签识别号的位数就会增加,则会导致整体的扫描时间急剧上升,降低了系统轮询的效率。
基于时隙ALOHA协议的轮询机制:
在每一轮中阅读器广播一个随机数r,每个被激活的标签接收到r后随即结合本地的标识符ID进行散列操作,计算出伪随机数s作为选定的时隙序列号。上述的“伪随机性”意味着,对于任一标签,一旦阅读器广播的数值r以及帧的长度f确定下来,该标签在帧中选择的时隙位置被即被确定,那么在这中情况下,阅读器在实施扫描前,可以根据指定的标签集合中的标签ID计算在下一帧中每个时隙的期望状态,那么期望状态和实际状态会存在不一致的情况:(1)期望为单时隙但实际为空时隙,则表明对应于该单时隙的标签丢失;(2)期望为冲突时隙但是实际为空时隙,则表明碰撞时隙全部丢失;(3)若观察到的时隙状态和预期的时隙状态一致,均为冲突时隙,则阅读器无法判断是否有标签丢失。(导致假阳性误判)
1:基准协议
基准协议排除传输过程中标签之间的冲突,并减少标签返回时发送的比特数。阅读器发送一个标签的标识符号,对应标签如果存在则返回一个较短的响应。
2:两阶段协议(TPP)
两段协议极大地减少了需要传输的标签的ID数目。它被分为两个阶段:帧阶段和轮询阶段。
在帧阶段,利用基于帧的时隙ALOHA协议来获得标签的响应。但是只能利用单时隙来判断是否丢失。、
在轮询阶段,执行基准协议进行确认是否丢失标签,自然存在假阳性误判。
3:带标签移除机制的两段协议(TPP/TR)
分为帧阶段和轮询阶段。
帧阶段,阅读器首先像TPP协议那样计算标签映射到对应时隙的情况,对于碰撞时隙(k个碰撞),阅读器随机的移除k-1个标签,让当前的碰撞时隙变为单时隙。对于被移除的标签将会在下一阶段来确认其是否存在。
4:冲突敏感的标签移除三段协议(TPP/CSTR)
此协议分为三个阶段:第一个轮询阶段、帧阶段和第二个轮询阶段。
第一个轮询阶段,阅读器根据标签的标识符号计算标签对应的时隙,对于碰撞时隙k(k>=2),阅读器随机地移除其中的k-2个标签,留下两个标签,对于被移除的标签将在改轮询阶段被确认是否存在,存在的标签给阅读器发送一个短响应。
在帧阶段,标签发送长的响应(区分于单时隙和碰撞时隙)。如果期望为单时隙但是实际为空时隙就丢失,但如果期望为冲突但是实际为空闲时隙就两个都丢失。如果冲突时隙中阅读器只接收到一个标签的响应,则进入第二轮询阶段。
第二轮询阶段,阅读器依次广播这两个ID确认其对应的标签是否存在。
论文上的: 李晓武: 比特时隙ALOHA算法(BSA)
在正式传输标签ID号前需要标签先发送一个时隙预定序列,通过阅读器接收到的预定序列,阅读器可一直打哪些时隙是空闲的或者被预定的,碰撞时隙会被记为“x”
算法步骤:
(1):阅读器发送查询命令,信号区里的所有标签先生成一个随机数,根据该随机数生成一个随机预定序列,并发送给阅读器
(2):阅读器收到一个时隙预定序列,根据该序列的碰撞比特
随机后识别现象(RLI):标签选择了靠后的时隙进行通讯,但是等不到此通讯时隙就要离开阅读区域了,解决需要先来先服务策略,但是标签识别有随机性,这种特性是在共享信道的时分多路访问控制的无线通信网络中是不能改变的,所以实际上标签本质上是不能够实现先来先服务的,但是我们可以考虑对信号区的标签进行顺序化分组(分组操作),然后在标签组顺序化分组的基础上实现标签组的先来先服务机制
标签移动RFID系统---TMRS(Tag Movement RFID Systems)
小猫爪:S32K3学习笔记13-S32K3之CMU 1 前言2 CMU介绍2.1 CMU_FC2.1 CMU_FM2.3 总结 3 MCAL配置END 1 前言 这一节来看看S32K3在时钟方面的安全监测,那就是CMU(Clock Monitor Unit),这个模块就是专门来监测时钟的。
2 CMU介绍 S32K3总共有6个CMU通道,按照功能分为CMU_FC(Frequency Check)通道和CMU_FM(Frequency Meter)通道,而这6个通道则分为了CMU_FC_0,CMU_FM_1,CMU_FM_2,CMU_FC_3,CMU_FC_4,CMU_FC_5这6个通道,所以S32K3有4个监测通道和2个测量通道。另外还有一点就是这6个通道所监测的时钟对象也是一开始就定死了,如下图:
2.1 CMU_FC 下图为CMU_FU的功能框图:
CMU_FU的功能非常简单,就是用一个参考时钟去监控一个被检测时钟,如果两者的频率相差超过最高High阈值或超过最低Low阈值(两个阈值皆可配置),那么就会触发中断或者破坏性复位(同一时间二选一)。在这里需要注意一点的就是,只有CMU_FC_0才能触发中断或者破坏性复位,而CMU_FC_3, CMU_FC_4, CMU_FC_5只能触发破坏性复位,所以在中断向量表中找不到CMU_FC_3, CMU_FC_4, CMU_FC_5的中断号,只有CMU_FC_0的中断号CMU0_IRQn。
2.1 CMU_FM 下图为CMU_FM的功能框图:
CMU_FU的功能也是非常简单,就是用一个参考时钟去测量另外一个时钟,简单至极,这里就不用多说什么,当完成一次测量后就会触发一个测量完成中断,CMU_FM_1和CMU_FM_2分别对应中断向量的CMU1_IRQn,CMU2_IRQn。
2.3 总结 下面列出一个表格总结一下6个CMU通道的特征:
通道名功能被监测时钟参考时钟特征CMU_FC_0检测FXOSC(8~40MHz)FIRC异常时触发中断或者破坏性复位CMU_FM_1测量FIRC (48MHz)FXOSC测量完成后触发中断CMU_FM_2测量SIRC (32KHz)FXOSC测量完成后触发中断CMU_FM_3检测CORE_CLKFXOSC异常时触发破坏性复位CMU_FM_3检测AIPS_PLAT_CLKFIRC异常时触发破坏性复位CMU_FM_3检测HSE_CLKFIRC异常时触发破坏性复位 3 MCAL配置 CMU的MCAL配置被集成到了Mcu模块中,首先第一步使能CMU的时钟:
接下来先完成CMU_FC的配置,先在McuClockSettingConfi->McuCLKMonitor中添加CMU_FC通道,之前说过,CMU最大支持4个FC通道,如下:
随后对每个通道进行配置,我以一条为例,如下:‘
前面提到了CMU_FC_0是可以支持异常时是触发中断还是触发破坏性复位,在这里的表现就是Enable FHH/FLL Asynchronous Event即发生异常时触发破坏性复位,而Enable FHH/FLL interrupt为发生异常时触发中断,同一时间这两者只能选择一个。
随后还需要在Mcu->Generate中配置一些关于CMU的选项,首先使能错误报告回调函数,如下:
在这里需要注意的是这里的McuCmuNotification并不是单单为CMU_FM_0的错误中断服务的,而是给整个时钟初始化使用的,如果在时钟初始化过程中,发现时钟初始化错误或者失败MCAL都会调用这个错误回调函数,这个通知函数是需要用户自己去实现的,可以添加一些适当的处理方法,这个通知函数会传递一个参数,为出现错误的时钟名,如下:
void McuCmuNotification(Clock_Ip_NameType clockName) { Clock_Ip_NameType tempclockName; tempclockName = clockName; switch(tempclockName) { case FXOSC_CLK: break; case SIRC_CLK: break; case FIRC_CLK: break; //.
一、如何快速选取区域或单元格 ctrl+A
框选连续区域
表格的两个极端,用shift连接
点击该列/该行
去到该单元格的任意其他地方 ctrl+方向键/双击单元格
框选:ctrl+shift+方向键
选中不连续的区域 shift+F8 (退出用 Esc) / ctrl+点击
点击表格三角(会保留列宽、格式、内容)
【注】空列可以隔开的一个个表格
二、表格中行与列的设置 表格内容被隐藏: 选中整列
出现黑色十字形,双击,即可自动调整。
2. 加减列
ctrl+ -,ctrl + +
3. 移动列:
shift,出现十字光标之后,拖拽移动即可
4. 复制列:
ctrl+shift拖拽
三、如何冻结行和列 【视图】---->【冻结窗格】
单行单列
直接选择即可多行多列
填充相同的颜色,然后光标定位在行列交叉的第一个单元格 四、如何高效填充 出现十字填充柄时,
拖拽双击(当有表格的时候,双击就可以自动填充)自动查看其他数据中是否有该值,并进行自动填充【开始】—【填充】填充序列 ctrl+拖拽 1,2,3,4,5…问题:删除某一行之后序号不连续了——使用 row函数(实时更新) 定义:ROW函数,返回一个引用的行号。如果省略 reference,则假定是对函数 ROW 单元格的引用
返回行号
没有参数时:当前行所在的行号
有参数时:指定的行号
中括号的参数代表可以省略 五、设置单元格 合并单元格的讲究:
如果合并之前就有数据,就可以做筛选功能,
如果没有数据,筛选数据只能筛选出之前就有数据的哪些单元格。
批量合并单元格 单元格的跨越合并
让很多行同时实现合并 六、格式刷 点击使用一次双击使用无限次,按Esc退出 七、数字格式的设置 普通格式 ctrl + 1 调用当前数字格式
ctrl+shift+4 改为货币形式
excel 中,日期以1900年1月1日为起点
数字类型(整数,浮点数,定点数)字符串类型文本类型日期类型二进制类型 使用MySQL数据库存储数据时,不同的数据类型决定了MySQL存储方式的不同。为此,MySQL数据库提供了多种数据类型,其中包括整数类型,浮点数类型,定点数类型,字符串类型,二进制等。 数字类型(整数,浮点数,定点数) 整数类型最常用的为INT型。
浮点数的类型有两种:单精度浮点数类型(FLOAT)和双精度浮点数类型(DOUBLE)。
定点数类型只有一种即DECIMAL类型。
从上图可以看出:DECIMAL类型的取值范围与DOUBLE类型相同。
但是,DECIMAL类型的有效取值范围是由M和D决定的。其中,M表示数据的长度,D表示小数点后的长度。
字符串类型 在MySQL中常用CHAR和VARCHAR表示字符串。两者不同的是:VARCHAR存储可变长度的字符串。
举例:
当数据为CHAR(M)类型时,不管插入值的实际长度是多少,它所占用的存储空间都是M个字节当数据为VARCHAR(M)类型时,其所占用的字节数为插入值的实际长度加1
文本类型 用于表示大文本数据,例如,文章内容,评论,详情等。
日期类型 MySQL提供的表示日期和时间的数据类型分别是:YEAR,DATE,TIME,DATETIME和TIMESTAMP。
使用CURREBNT_TIME() 或者 NOW() 输入当前系统时间。
二进制类型 在MySQL中常用BLOB存储二进制类型的数据,例如:图片,PDF文档等。BLOB类型有如下四种:
一、Jmeter介绍
二、Jmeter安装教程
1、下载地址(安装之前首先配置Java环境变量)
Apache JMeter - Download Apache JMeter
根据自己电脑系统来选择合适的安装包即可。 2、环境变量配置
配置Jmeter的环境变量:
新建变量名 JMETER_HOME;
值为:D:\softwore\jmeter\apache-jmeter-5.3\bin(这是解压后的目录位置)
3、启动
到解压后的目录,进入bin目录,双击 jmeter.bat 即可运行
启动成功:
到此位置,Jmeter就安装成功并启动成功啦,恭喜你。
三、Jmeter接口测试
1、新建一个线程组,该软件是Java编写的,可以用一个Java请求模拟一个用户,因此一个线程组就标识一组虚拟用户信息;
参数说明:
1、线程数:模拟请求的次数;
2、Ramp-Up时间(秒):所有线程执行的时间,比如:配置了 2 秒,线程数配置了 100,要在 2 秒内执行 100 次请求;
3、循环次数:要轮询执行几次;
4、调度器
(1)持续时间(秒):就是本次执行的线程持续多长时间;
(2)启动延迟(秒):本次执行的线程启动要延迟多长时间执行;
2、添加好线程组之后,需要添加 HTTP请求 (在开发过程中,一般接口都以HTTP协议为主)
3、配置接口请求的服务器地址和接口路径以及请求方式,可以设置参数列表;
这说明一下:参数可以一个一个添加,也可以导入JSON文件,还可以上传文件之类的。
4、设置配件元件 ,可以设置HTTP请求的基本信息,比如HTTP信息头管理器、HTTP Cookie 管理器、 HTTP缓存管理器、HTTP请求默认值,可以根据自己的接口请求设置不同的参数即可。
5、配置监听器,可以添加 汇总报告、聚合报告、察看结果树
汇总报告:可以查看接口的最大、最小、平均请求值,可以看接口的异常率、吞吐量、接口、发送、平均字节数等信息;
聚合报告:可以查看接口请求最大、最小、平均值、异常率、吞吐量等信息;
察看结果树:查看每个请求成功与否,这里可以配置每个请求的日志输出路径,以什么格式的文件输出。
以上就是JMeter的安装使用教程,供大家参考!
Cookie 与 Session 一、Cookie 详解1.Cookie 是什么?2.为什么使用Cookie?3.Cookie 产生时间4.Cookie 生存周期5.Cookie 缺陷6.Cookie 使用场景 二、Session 详解1.什么是 Session2.Session 生命周期 三、涉及核心方法四、代码示例(用户登陆)五、小结 一、Cookie 详解 1.Cookie 是什么? Cookie,是某些网站为了辨别用户身份,进行session跟踪而储存在用户本地终端上的数据,由用户客户端计算机暂时或永久保存的信息;
2.为什么使用Cookie? 由于 web 程序是使用HTTP传输协议的,而HTTP协议属于无状态的协议,对于事务处理没有记忆能力;因此当后续处理需要前面的信息时就需要重新上传,这样就会导致每次连接传送的数据量增大了;
Cookie的出现就可以解决这一问题:
原理:
第一次登录后服务器返回一些数据(cookie)给浏览器,然后浏览器将其保存在本地,当该用户发送第二次请求时 就会把上次请求存储的cookie数据自动的携带给服务器,服务器通过浏览器携带的数据就能判断当前用户是那个了;
简单来讲cookie的工作原理就是:
给每个用户发放一个通行证,这样服务器就能通过通行证确认用户身份了;
3.Cookie 产生时间 Cookie 的使用首先取决于用户(原因:浏览器可以禁用Cookie,同时服务端也可以不set-cookie;Cookie的两种保存方式:其1为浏览器将Cookie保存在内存中,其2为保存在客户端的硬盘上,之后每次HTTP请求浏览器都会将Cookie 发送给服务端; 4.Cookie 生存周期 Cookie 在生成时就会被指定一个Expire值,这就是Cookie的生存周期,在这个周期内Cookie有效,超出周期就会被清除;
5.Cookie 缺陷 数量受限制 表现在:
一个浏览器能创建的 Cookie 数量最多不超过300个,且每个不能超过4KB,每个web站点能设置的Cookie 总数不能超过20个;
安全性得不到保障: 表现在:存在跨站点脚本攻击
浏览器可以设置禁用Cookie: 6.Cookie 使用场景 基于Cookie 的缺陷,因此一般使用在:
对安全性要求不高;不需要存储大量的数据;主要用于客户端与服务器之间的状态保持; 二、Session 详解 1.什么是 Session Session 也称为会话机制,那什么是会话呢?
会话的本质:就是一个"哈希表", 存储了一些键值对结构,其中 key 就是令牌的 ID(token/sessionId), value 就是用户信息(用户信息可以根据需求灵活设计);
sessionId 和 token 就可以理解成是同一个东西的不同叫法;
第一章 Maven 基础 网页地址 视频地址:黑马程序员Maven全套教程,maven项目管理从基础到高级,Java项目开发必会管理工具maven_哔哩哔哩_bilibili依赖查询:https://mvnrepository.com/ Maven :Maven – Available Plugins
Nexus :Download
有道云笔记:https://note.youdao.com/s/avkgonCe
Maven 标签 resources: 资源文件配置信息
resource: 资源文件配置信息
testResources: test 资源文件配置信息
testResource: test 资源文件配置信息
以下内容属于 dependencies groupId: 【组织 ID】定义当前 Maven 项目隶属组织名称(通常是域名反写,例如 org.mybaits)
artifactId: 【项目 ID】定义当前 Maven 项目名称(通常是模块名称,例如 CRM、SMS)
version: 【版本号】定义当前项目的版本号
packaging: 【jar/war】定义该项目的打包方式
optional: 是否对上级隐藏 true / false
exclusions: 排除掉某些
exclusion: 具体排除掉哪一个 ()
注意:不写版本 见代码片段 1.2 scope: 范围
在主程序范围能不能用 【compile 文件夹范围内 】在测试范围能不能用【 test 】是否参与打包【 package 】 dependencyManagement:【依赖管理】 在 父pom 中做依赖管理
按照百度的新建common.d.ts文件并输入declare module '*.js'; 依然会报错common.d.tsis not a module.
正确解决办法是: src下的shims-vue.d.ts中添加 declare module '*.js';
// 目录文件: src/shims-vue.d.ts declare module '*.vue' { import Vue from 'vue' export default Vue } declare module '*.js';// 添加这个
[MSDN]
By default, MFC uses the resource handle of the main application to load the resource template. If you have an exported function in a DLL, such as one that launches a dialog box in the DLL, this template is actually stored in the DLL module. You need to switch the module state for the correct handle to be used. You can do this by adding the following code to the beginning of the function:
今天逛知乎日常搜索了几个关于前端面试的问题,本以为学了react之类的框架就可以放弃css,现在想想自己真是太天真了。老前辈们说过:“Css你可以不把每一个属性全都记住,但是你一定要在你需要的时候知道去哪里找。”不过这句话有迷惑性,我再来改一下,常见的属性你一定要记住,不常见,不经常使用的你需要记住有这个属性,在你看到这个属性的时候,你要知道你见过,不要一头雾水一脸懵逼。
圣杯布局有好几种方法实现,它并不是只有一种固定格式. 最常见的圣杯布局MDN官方文档,基本上就是圣杯布局的大概思路.
页面nav占据最大的宽度,然后两边固定宽度,中间内容可以根据用户使用自动缩放。
1.flex 实现 如果要用flex实现的话 需要把<nav >和footer拿出来,给中间三个内容一个单独的父容器,给父容器一个display:flex (或许有更好的方法不用分离,但是目前我只想到了分离出来nav和footer)
我们要求的大概思路就是,nav和footer占据用户屏幕的百分百宽度,中间内容分为三列,脑子里一定要有一个清晰的网页轮廓。
给左右两边定宽,然后给中间内容一个flex:1,这里左右两边的宽度也可以用flex-basis表示,这里需要理解的点上flex:1这个地方,flex:number (代表着这个元素可以如何分配剩下的空间,因为左右默认值为0,我单独给center设置了1,那么代表着center将独自享有剩下的所有空间,那么就实现了我们想要的效果。)要注意的是flex:1是flex的简写模式,它的简写值可以有三个,在这里就不过多赘述.自行查阅mdn。 2.负margin 加浮动(这个太经典了,建议熟读百遍) 同样是这样的布局模式;
通过上面简单的样式布局,呈现出页面效果如下(左右两边的空白是content的padding,准备放入left和right 的div的,通常情况padding的值就是左右两边sider的宽度,一般是固定宽度,你也可以设置margin来等效替换padding,得到的布局效果是一样的)
这时候我们需要用到浮动来将我们的左右元素移动到相应的位置,
这里为什么要margin-100%呢?你可以想象本来这三个元素应该是在同一行的,但是由于center盒子宽度满了,强行把left和right挤到下一行了,但是其实他们应该排在center盒子的最右边,因为div盒子是center left right这个上下文顺序在html文档里写,
我们给左边盒子一个-margin,注意margin是相对于父亲元素来说的,我的-100%,也就是紧挨着父亲元素的最左边,此时left盒子和center盒子的左边重合。这时候我需要左边盒子再往左移动300px,也就是父亲盒子为它空出去的宽度。
!!!!注意float是沿容器,容器,容器,并没有脱离父元素的限制!!! (到这你应该也就知道下一步要干什么了,对,我们要让他脱离父亲元素的限制)
ok,第一时间就应该想到使用position这个方法,那么positon的relative是最合适的,(如果你想达成用户滑动屏幕,左右栏固定的效果也可以用absolute。absolute的定位方式会去找上一层非static模式的盒子,一直找到浏览器窗口为止。)那么该右边盒子紧挨着center了(一定要注意这里的意思,本来右边盒子也是和center盒子紧挨着在同一行的)这时候给了一个负的自身的宽度,那么他就会向左边移动,覆盖住center200px也就是自身宽度的值 ,但是这时候它还是没有摆脱父元素的限制,所以也要用定位,让他向右偏移自身宽度的长度
最终全部css代码和结果如下 3.双飞翼布局(广购平台页面经典布局) 圣杯布局和双飞翼布局实现的样式是大致基本相同的,只不过双飞翼布局的内容区用单独的div包裹,让这个div来承担浮动的角色。
1.touchstart,touchend,touchmove可以实现拖曳
2.拖动元素当前手指的坐标值可以使用targetTouches[0]中的pageX pageY
3.移动端拖曳原理:手指移动过程中计算出手指移动的距离
盒子原来的位置+手指移动的距离
4.手指移动距离: 手指滑动中的位置减去手指刚开始触摸的位置
拖曳元素三步走:
(1)触摸元素touchstart:获取手指的初始坐标 即盒子刚开始的位置
(2)移动手指touchmove:计算手指的滑动距离,并且移动盒子
(3)离开手指touchend
注意阻止屏幕的默认滚动
uni小程序拖曳代码实现
https://juejin.cn/post/7003652210861015077
1、Java程序如何运行 1.1 创建java文件,编写程序 注意:此处类名需要与文件名相同
1.2 选中所在目录,输入cmd+回车,出现黑框命令行 全选路径输入cmd+enter,或者win+r输入cmd进入,后者需要再cd 到文件路径下
1.3 在命令框里输入javac Test_0001.java 编译生成.class文件 1.4 输入java Test_0001可以成功运行 拓展: 编译后产生的java.class 文件在java虚拟机(jvm)的帮助下,可以在不同的操作系统运行,实现了java程序的跨平台性,通常jdk里包含jvm,所以学习java之前先在电脑中安装jdk.
文章目录 CentOS k8s集群 KubesPhere安装一、k8s集群1、基础环境准备2、安装docker3、安装kubelete、kubeadm、kubectl4、部署master节点(171)5、安装网络组件(flannel):6、节点加入 二、KubeSphere1、准备helm 和 tiller(helm v3的版本不需要再安装tiller)2、安装OpenEBS3、开始kubesphere最小安装 CentOS k8s集群 KubesPhere安装 各组件版本表:
组件名称组件版本docker20.10.7k8s1.20.9helm3.7.1KubesPhere3.1.1 一、k8s集群 1、基础环境准备 由于我的centos7.5是最小安装,所以先安装一下工具集
yum install -y conntrack ntpdate ntp ipvsadm ipset jq iptables curl sysstat libseccomp wget vim net-tools git iproute lrzsz bash-completion tree bridge-utils unzip bind-utils gcc
然后进行关闭防火墙等操作
# 1.关闭防火墙 systemctl stop firewalld && systemctl disable firewalld # 2.置空iptables yum -y install iptables-services && systemctl start iptables && systemctl enable iptables && iptables -F && service iptables save # 3.
Flv解复用代码解析 目录 总体流程 main函数处理函数process解析函数 解析Flv header和Flv Tag 解析Flv header解析Flv Tag解析MetaData Tag dump H264、AAC和FLV GitHub源码地址:flv-parser
Flv格式分析:Flv格式分析
1. 总体流程 flv-parser项目能够解析flv格式文件,分离出H264和AAC数据,最后组装回flv格式文件并输出。 1. main函数 流程: 读取输⼊⽂件(flv类型的视频⽂件)调⽤Process进⾏处理退出 int main(int argc, char *argv[]) { //argv[1]是开始的第一个输入参数 cout << "this is FLV parser test program!\ninput: flv, output:flv\n"; if (argc != 3) { cout << "FlvParser.exe [input flv] [output flv]" << endl; return 0; } fstream fin; //fstream包含读写操作,对打开的文件可进行读写操作 fin.open(argv[1], ios_base::in | ios_base::binary); //以二进制文件格式进行输入 if (!fin) return 0; process(fin, argv[2]); //argv[2],输出flv文件 fin.
问题描述: 在Ubuntu20.04LTS环境下(是物理机,不是虚拟机)打开gazebo,点ctrl+B进入building editor时,在二维地图创建世界环境时,添加窗户或者门时,Gazebo出现了闪退的情况。github上gazebo项目的issue也有人提这个问题,具体情况如下面这个GIF。
解决方案: 先卸载掉当前的Gazebo,具体命令如下:
sudo apt-get remove ros-noetic-gazebo* sudo apt-get remove libgazebo* sudo apt-get remove gazebo*或者(sudo apt-get remove gazebo11-common ) 卸载之后可以安装gazebo的支持版本使用如下命令
curl -sSL http://get.gazebosim.org | sh 如果显示没有curl,可以安装该命令
sudo apt-get install curl 完成上述稳定版本安装后,就解决了该问题。
select score,dense_rank() over(order by score desc) as 'rank' from Scores row_number():依次递增排名,无重复排名
rank():相同分数有重复排名,但是重复后下一个人按照实际排名
dense_rank():分数一致排名一致,分数不一致排名+1
NTILE(4):分组排名,里面的数字是几,最多排名就是几,里面的数字是4,最多的排名就是4
1.rank() over:排名相同的两名是并列,但是占两个名次,1 1 3 4 4 6这种
2.dense_rank() over:排名相同的两名是并列,共占一个名词,1 1 2 3 3 4这种
3.row_number() over这个函数不需要考虑是否并列,哪怕根据条件查询出来的数值相同也会进行连续排名 1 2 3 4 5
目录 sklearn中的支持向量机SVM(下)1 二分类SVC的进阶1.1 SVC用于二分类的原理复习1.2 参数C的理解进阶1.3 二分类SVC中的样本不均衡问题 2 SVC的模型评估指标2.1 混淆矩阵(Confusion Matrix)2.1.1 模型整体效果:准确率2.1.2 捕捉少数类的艺术:精确度,召回率和F1 score2.1.3 判错多数类的考量:特异度与假正率2.1.4 sklearn中的混淆矩阵 2.2 ROC曲线以及其相关问题2.2.1 概率(probability)与阈值(threshold)2.2.2 SVM实现概率预测2.2.3 绘制SVM的ROC曲线2.2.4 sklearn中的ROC曲线和AUC面积2.2.5 利用ROC曲线找出最佳阈值 sklearn中的支持向量机SVM(下) 1 二分类SVC的进阶 1.1 SVC用于二分类的原理复习 支持向量机分类器,是在数据空间中找出一个超平面作为决策边界,利用这个决策边界来对数据进行分类,并使分类误差尽量小的模型。
1.2 参数C的理解进阶 有一些数据,可能是线性可分,但在线性可分状况下训练准确率不能达到100%,即无法让训练误差为0,这样的数据被我们称为“存在软间隔的数据”。此时此刻,我们需要让我们决策边界能够忍受一小部分训练误差,我们就不能单纯地寻求最大边际了。
因为对于软间隔地数据来说,边际越大被分错的样本也就会越多,因此我们需要找出一个”最大边际“与”被分错的样本数量“之间的平衡。因此,我们引入松弛系数 和松弛系数的系数C作为一个惩罚项,来惩罚我们对最大边际的追求。
那我们的参数C如何影响我们的决策边界呢?在硬间隔的时候,我们的决策边界完全由两个支持向量和最小化损失函数(最大化边际)来决定,而我们的支持向量是两个标签类别不一致的点,即分别是正样本和负样本。然而在软间隔情况下我们的边际依然由支持向量决定,但此时此刻的支持向量可能就不再是来自两种标签类别的点了,而是分布在决策边界两边的,同类别的点软间隔让决定两条虚线超平面的支持向量可能是来自于同一个类别的样本点,而硬间隔的时候两条虚线超平面必须是由来自两个不同类别的支持向量决定的。
1.3 二分类SVC中的样本不均衡问题 重要参数class_weight
对于分类问题,永远都逃不过的一个痛点就是样本不均衡问题。样本不均衡是指在一组数据集中,标签的一类天生占有很大的比例,但我们有着捕捉出某种特定的分类的需求的状况。比如,我们现在要对潜在犯罪者和普通人进行分类,潜在犯罪者占总人口的比例是相当低的,也许只有2%左右,98%的人都是普通人,而我们的目标是要捕获出潜在犯罪者。这样的标签分布会带来许多问题。
首先,分类模型天生会倾向于多数的类,让多数类更容易被判断正确,少数类被牺牲掉。因为对于模型而言,样本量越大的标签可以学习的信息越多,算法就会更加依赖于从多数类中学到的信息来进行判断。如果我们希望捕获少数类,模型就会失败。其次,模型评估指标会失去意义。这种分类状况下,即便模型什么也不做,全把所有人都当成不会犯罪的人,准确率也能非常高,这使得模型评估指标accuracy变得毫无意义,根本无法达到我们的“要识别出会犯罪的人”的建模目的。所以现在,我们首先要让算法意识到数据的标签是不均衡的,通过施加一些惩罚或者改变样本本身,来让模型向着捕获少数类的方向建模。然后,我们要改进我们的模型评估指标,使用更加针对于少数类的指标来优化模型。要解决第一个问题,我们在逻辑回归中已经介绍了一些基本方法,比如上采样下采样。但这些采样方法会增加样本的总数,对于支持向量机这个样本总是对计算速度影响巨大的算法来说,我们完全不想轻易地增加样本数量。况且,支持向量机中地决策仅仅决策边界的影响,而决策边界又仅仅受到参数C和支持向量的影响,单纯地增加样本数量不仅会增加计算时间,可能还会增加无数对决策边界无影响的样本点。因此在支持向量机中,我们要大力依赖
我们调节样本均衡的参数:SVC类中的class_weight和接口fit中可以设定的sample_weight。在逻辑回归中,参数class_weight默认None,此模式表示假设数据集中的所有标签是均衡的,即自动认为标签的
比例是1:1。所以当样本不均衡的时候,我们可以使用形如{“标签的值1”:权重1,“标签的值2”:权重2}的字典来输入真实的样本标签比例,来让算法意识到样本是不平衡的。或者使用”balanced“模式,直接使用n_samples/(n_classes * np.bincount(y))作为权重,可以比较好地修正我们的样本不均衡情况。但在SVM中,我们的分类判断是基于决策边界的,而最终决定究竟使用怎样的支持向量和决策边界的参数是参数C,所以所有的样本均衡都是通过参数C来调整的。
导入需要的库和模块
创建样本不均衡的数据集
在数据集上分别建模
绘制两个模型下数据的决策边界
可以看出,从准确率的角度来看,不做样本平衡的时候准确率反而更高,做了样本平衡准确率反而变低了,这是因为做了样本平衡后,为了要更有效地捕捉出少数类,模型误伤了许多多数类样本,而多数类被分错的样本数量 > 少数类被分类正确的样本数量,使得模型整体的精确性下降。现在,如果我们的目的是模型整体的准确率,那我们就要拒绝样本平衡,使用class_weight被设置之前的模型。然而在现实中,我们往往都在追求捕捉少数类,因为在很多情况下,将少数类判断错的代价是巨大的。比如我们之前提到的,判断潜在犯罪者和普通人的例子,如果我们没有能够识别出潜在犯罪者,那么这些人就可能去危害社会,造成恶劣影响,但如果我们把普通人错认为是潜在犯罪者,我们也许只是需要增加一些监控和人为甄别的成本。所以对我们来说,我们宁愿把普通人判错,也不想放过任何一个潜在犯罪者。我们希望不惜一切代价来捕获少数类,或者希望捕捉出尽量多的少数类,那我们就必须使用class_weight设置后的模型。
2 SVC的模型评估指标 从上一节的例子中可以看出,如果我们的目标是希望尽量捕获少数类,那准确率这个模型评估逐渐失效,所以我们需要新的模型评估指标来帮助我们。如果简单来看,其实我们只需要查看模型在少数类上的准确率就好了,只要能够将少数类尽量捕捉出来,就能够达到我们的目的。但此时,新问题又出现了,我们对多数类判断错误后,会需要人工甄别或者更多的业务上的措施来一一排除我们判断错误的多数类,这种行为往往伴随着很高的成本。比如银行在判断”一个申请信用卡的客户是否会出现违约行为“的时候,如果一个客户被判断为”会违约“,这个客户的信用卡申请就会被驳回,如果为了捕捉出”会违约“的人,大量地将”不会违约“的客户判断为”会违约“的客户,就会有许多无辜的客户的申请被驳回。信用卡对银行来说意味着利息收入,而拒绝了许多本来不会违约的客户,对银行来说就是巨大的损失。同理,大众在召回不符合欧盟标准的汽车时,如果为了找到所有不符合标准的汽车,而将一堆本来符合标准了的汽车召回,这个成本是不可估量的。也就是说,单纯地追求捕捉出少数类,就会成本太高,而不顾及少数类,又会无法达成模型的效果。所以在现实中,我们往往在寻找捕获少数类的能力和将多数类判错后需要付出的成本的平衡。如果一个模型在能够尽量捕获少数类的情况下,还能够尽量对多数类判断正确,则这个模型就非常优秀了。为了评估这样的能力,我们将引入新的模型评估指标:混淆矩阵和ROC曲线来帮助我们。
2.1 混淆矩阵(Confusion Matrix) 混淆矩阵是二分类问题的多维衡量指标体系,在样本不平衡时极其有用。在混淆矩阵中,我们将少数类认为是正例,多数类认为是负例。在决策树,随机森林这些普通的分类算法里,即是说少数类是1,多数类是0。在SVM里,就是说少数类是1,多数类是-1。普通的混淆矩阵,一般使用{0,1}来表示。混淆矩阵阵如其名,十分容易让人混淆,在许多教材中,混淆矩阵中各种各样的名称和定义让大家难以理解难以记忆。我为大家找出了一种简化的方式来显示标准二分类的混淆矩阵,如图所示:
混淆矩阵中,永远是真实值在前,预测值在后。其实可以很容易看出,11和00的对角线就是全部预测正确的,01和10的对角线就是全部预测错误的。基于混淆矩阵,我们有六个不同的模型评估指标,这些评估指标的范围都在[0,1]之间,所有以11和00为分子的指标都是越接近1越好,所以以01和10为分子的指标都是越接近0越好。对于所有的指标,我们用橙色表示分母,用绿色表示分子,则我们有:
2.1.1 模型整体效果:准确率 2.1.2 捕捉少数类的艺术:精确度,召回率和F1 score 精确度Precision,又叫查准率,表示所有被我们预测为是少数类的样本中,真正的少数类所占的比例。在支持向量机中,精确度可以被形象地表示为决策边界上方的所有点中,红色点所占的比例。精确度越高,代表我们捕捉正确的红色点越多,对少数类的预测越精确。精确度越低,则代表我们误伤了过多的多数类。精确度是”将多数类判错后所需付出成本“的衡量。在现实的样本不平衡例子中,当每一次将多数类判断错误的成本非常高昂的时候(比如大众召回车辆的例子),我们会追求高精确度。精确度越低,我们对多数类的判断就会越错误。当然了,如果我们的目标是不计一切代价捕获少数类,那我们并不在意精确度。
召回率Recall,又被称为敏感度(sensitivity),真正率,查全率,表示所有真实为1的样本中,被我们预测正确的样本所占的比例。在支持向量机中,召回率可以被表示为,决策边界上方的所有红色点占全部样本中的红色点的比例。召回率越高,代表我们尽量捕捉出了越多的少数类,召回率越低,代表我们没有捕捉出足够的少数类.
如果我们希望不计一切代价,找出少数类(比如找出潜在犯罪者的例子),那我们就会追求高召回率,相反如果我们的目标不是尽量捕获少数类,那我们就不需要在意召回率。注意召回率和精确度的分子是相同的(都是11),只是分母不同。而召回率和精确度是此消彼长的,两者之间的平衡代表了捕捉少数类的需求和尽量不要误伤多数类的需求的平衡。究竟要偏向于哪一方,取决于我们的业务需求:究竟是误伤多数类的成本更高,还是无法捕捉少数类的代价更高。
2.1.3 判错多数类的考量:特异度与假正率 特异度衡量了一个模型将多数类判断正确的能力,而1 - specificity就是一个模型将多数类判断错误的能力,这种能力被计算如下,并叫做假正率(False Positive Rate):
目录 前言一.什么是registry机制二.registry示例1.创建注册表2.注册表添加类3.测试 三.总结 前言 现在好多项目都会用到registry机制,学习一下
一.什么是registry机制 简单来说registry可以提供字符串到python中类的映射,registry能让开发者输入相应的类名和参数,就能获得一个初始化好的类。
也就是说像是这样,下面这是一个类:
class aclass(object): def __init__(self): ... def ... ... 然后通过registry获取类:
cfg=dict(type="aclass") aclass=registry(cfg) 这样就通过字符串获取到了类接口了,下面笔者以mmcv中的registry为例子讲解registry机制,python中的其他工具箱中的registry机制也是大同小异的。
二.registry示例 1.创建注册表 首先创建一个目录,随意取个名字code,在code下再创建一个目录,名为registry,在这个目录下创建一个名为builder的python文件,代码如下:
from mmcv import Registry from mmcv.utils.registry import build_from_cfg CLASS=Registry("class_test") 在这里我们创建了一个名为class_test的注册表,其中Registry的参数如下
name (str): 注册表的名字 build_func(func, optional):构造类接口的函数,简单来说就是用来后续处理获取初始化类的函数, mmcv提供了一个build_from_cfg的函数,只需要建立一个字典,然后type=需要调用的类名,然后正 常的参 数的键值对输入就可以得到一个用自己配置参数获取的初始化的类了。当然也可以自己写。 parent (Registry, optional): 父注册表,如果没有指定build_func,就调用父注册表里面的,当然 父注册表里面的接口也是可以继承的 2.注册表添加类 然后在registry目录中创建一个名为class_test的python文件,代码如下:
from .builder import CLASS @CLASS.register_module() class test(object): def __init__(self,n): self.n=n def printf(self): print(self.n) 我们在这里定义了一个类,@CLASS.register_module()的作用是将我们这个类放入CLASS注册表里面,只要在@CLASS.register_module()下写入一个类就可以将这个类放入我们创建的注册表里面了。
然后在registry中创建一个__init__.py文件,将我们的registry变成一个python包,这是必要的。代码如下:
from .builder import CLASS from .class_test import test __all__=["
1、keras、tensorflow版本对应问题 可以看这个:https://docs.floydhub.com/guides/environments/
不知道为什么原来的网站不行了,好在有热心人士存了下来:
最全tensorflow,PyTorch ,numpy和keras 版本匹配汇总_源代码杀手的博客-CSDN博客_numpy和pytorch版本
部分截图:
2、numpy的版本问题 像这样:FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecat
就是numpy版本的问题,直接重新下载numpy即可(我之前的numpy版本是1.17,会报这个错,改成了1.16,就不报错了):
pip install numpy==1.16.0
成绩单 <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>输出成绩表</title> <style> body{text-align:center; font-family:微软雅黑} label{ margin-left:20px;} .report{width:560px; margin:30px auto;} .title{ background: #f6f6f6; font-size:18px; } .title,.content{ width:560px; height:36px; line-height:36px; border: 1px solid #dddddd;} .title div{ width:80px; text-align:center; float:left} .content{ clear:both} .content div{ width:80px; text-align:center; float:left} </style> <script src="../JS/vue.js"></script> </head> <body> <div id="example"> <h2>成绩表</h2> <label>姓名:</label><span>{{name}}</span> <label>性别:</label><span>{{sex}}</span> <label>年龄:</label><span>{{age}}</span> <div class="report"> <div class="title"> <div>学期</div> <div>数学</div> <div>物理</div> <div>化学</div> <div>英语</div> <div>计算机</div> <div>总分</div> </div> <div class="content" v-for="(grade,index) in grades"
C++未定义的函数或者标识 问题描述 Visual studio,多个函数会出现C++未定义的函数或者标识、声明不兼容等
解决方案 多半就是函数的问题,请大家仔细检查自己的函数是否都进行了命名、函数定义是否出现问题。
1.前言 归一化算法Normalization将数据处理成量纲一直的数据,一般限定在[0,1]、[-1,1]
一般在进行建模的时候需要进行数据归一化处理,原因如下:
降低计算难度有可能提高模型的预测精度消除量纲影响 下面介绍三种常见的标准化方法,分别是最大最小值、正态中心化、小数点定标
2.Min-Max方法 2.1 公式 x ′ = x − m i n A m a x A − m i n A x^{'}= \frac{x-minA}{maxA-minA} x′=maxA−minAx−minA
2.2 算法实现逻辑 1.找一组数据的最大最小值2.利用公式归一化3.输入结果(为了方便可视化展示,我们设计了代码) 2.3 代码 import numpy as np import pandas as pd import matplotlib.pyplot as plt # 1.最小最大标准化 Data = np.array([[0.2,0.9,29], [0.9,0.1,100], [0.5,0.5,30]]) #最小-最大归一化算法 # 1.1数据转化 def MinMax(data): min = 0 max = 1 C = data[:,2] min = np.
一、条件 查询班级表 返回所有学生信息 (一对多问题) 二、数据库 班级class_info
学生student
二、代码实现 <!-- 多对一 或者 一对一 --> <!-- <association property=""--> <!-- 一对多 返回集合--> <!- - <collection property=""- -> 实体类ClassInfo.java
@Data public class ClassInfo { private Long id; private String name; private String nameTest; private List<Student> studentList; } ClassInfoMapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!--名称空间:对应mapper层某个接口的包的全名称--> <mapper namespace="com.example.demo.mapper.ClassInfoMapper"> <!-- 查询班级 返回所有学生的信息 一对多--> <!-- 自定义映射规则--> <resultMap id="OneToMany" type="com.qcby.zsgc.entity.ClassInfo"> <result column="name" jdbcType="VARCHAR" property="
目前再前后端传递数据的方式最广泛的引用使用到的就是Json的数据格式;go语言对Json也有一个非常良好的支持
Marshal 生成Json package main import ( "encoding/json" "fmt" ) type Order struct { ID string Name string Quantity int TotalPrice float64 } func main() { o := Order{ ID: "123456", Name: "吹风机", Quantity: 1, TotalPrice: 45, } bytes, err := json.Marshal(o) if err != nil { panic(err) } fmt.Println(string(bytes)) } { "ID": "123456", "Name": "吹风机", "Quantity": 1, "TotalPrice": 45 } 以上输出的Json就可以再网络上进行传输,绝大部分语言都对Json有良好的支持.但是上面的Json所有的字段名都是首字母大写的,再其他语言上是不多见的,我们希望遵循网络上常用的大小写的使用方式
修改首字母大写 package main import ( "encoding/json" "fmt" ) type Order struct { id string name string quantity int totalPrice float64 } func main() { o := Order{ id: "
文章目录 1.备份所有数据库2.查询所有库3.备份A库4.备份B、C库5.删除A、B、C库6.创建A库7.Mysql命令还原A库8.Mysql命令还原B、C库9.查询所有库10.备份A库11.备份B、C库12.删除A、B、C库13.创建并使用A库14.Source命令还原A库15.Source命令还原B、C库16.查询所有库 1.备份所有数据库 mysqldump -uroot -p123456 --all-databases>E:\mysql\beifen\my.sql //不登录MySQL执行备份所有数据库到指定目录下; 截图:
2.查询所有库 show databases; 截图:
3.备份A库 mysqldump -uroot -p123456 xia>E:\mysql\beifen\xia.sql //不登录MySQL执行备份单个数据库到指定目录下 截图:
4.备份B、C库 mysqldump -uroot -p123456 --databases mass lianxi>E:\mysql\beifen\mass.sql //不登录MySQL备份两个数据库到指定目录下; 5.删除A、B、C库 drop database 数据库名; //删除数据库 //删除三个数据库; 截图:
6.创建A库 create database 数据库名; //创建数据库 //创建A库 截图:
7.Mysql命令还原A库 mysql -uroot -p123456 xia>E:\mysql\beifen\xia.sql //不登录MySQL还原A库; 截图:
8.Mysql命令还原B、C库 mysql -uroot -p123456 mass lianxi>E:\mysql\beifen\mass.sql //不登录MySQL还原B、C库; 截图:
9.查询所有库 show databases; //查看所有数据库; 截图:
10.备份A库 mysqldump -uroot -p123456 xia>E:\mysql\beifen\xia.sql //不登录MySQL执行备份单个数据库到指定目录下 截图:
微信公众号,关注:georgezheng
今天主要聊一聊银行金融科技岗,虽然互联网大厂工资高,但也不是那么好进的,这两年内卷越来越严重,想进大厂也越来越难。而银行的信息科技岗难度则会小很多,工资也还说的过去,并且工作相对稳定,很少会裁员,但可能会对学历有一定要求(相比于互联网公司)。
银行与大家以往认知的不同,并非只招收财经类专业的同学。近些年来,响应数字金融、金融科技发展的需求,招收理工类专业及计算机岗位的商业银行也越来越多了。
同时,银行的科技岗是属于软件中心/信息科技中心的,科技岗具体的工作内容跟一般的程序员有相似的地方也一定有不同的地方,综合来说这份工作是金融行业和计算机行业的相结合。
银行主要分为中央银行、政策性银行(中国农业发展银行、中国进出口银行)、国有银行(工、农、中、建、交、邮储等)、股份制银行(招商、平安、浦发、渤海银行等)、城市商业银行(北京银行、上海银行等)、农村商业银行、外资银行(花旗、渣打、汇丰银行)等。
一、你适合去银行做程序员吗?
下面先来看几个问题,看看你是否适合去银行做程序员。
是否能接受较低的工资,并且涨薪很慢(这是相比于互联网,如果和传统行业相比,工资还是可以的)
是否能接受较落后的技术栈,并且技术上的成长性较差(因为银行都是稳定为主,一般对技术要求并没有那些高)
是否能接受在职业晋升上会有论资排辈的情况存在
是否能接受国企那种人情世故的氛围
是否能接受在银行工作也可能会加班
是否能接受整天工作重复性极高,没什么难度,技术不会提高,并且可能会整天都很闲
如果上面的银行信息科技岗的缺点你都能接受,那么银行科技岗还是挺适合你的。
二、科技岗专业要求及工作内容?
可以根据岗位来区分:
一种是纯技术背景岗位,比如运维、测试、开发架构这些岗位,很多同学也会把它理解为科技人员,实际上是金融IT的人员。这些同学的背景都是技术背景,大多是计算机相关专业。
第二种是数据背景岗位,类似于以前学习统计学、数据科学等专业的同学。这类同学很多也会选修金融。这类可能更受欢迎,因为真正的金融科技时代,需要对数据的理解应用,这是一个很关键的岗位,做大数据分析需要这些人才。
第三类是金融岗位,其实在新型金融公司(BAT系)纯金融平台的金融人才反而占比不大,比如保险公司的竞争力在精算环节,而传统银行在产品设计环节,金融人才会占比更大一点。
但是整体趋势上,不管是新型金融机构还是传统金融机构,IT人员、技术人员的占比会越来越多。总体而言,金融科技岗位的诉求更多是信息技术能力、数据能力与金融知识的结合。
三、科技岗考什么?
各大银行的科技岗主要服务于银行的软件开发中心、数据中心与电子银行中心等部门,主要从事开发和测试应用软件,安装和维护硬件系统,保障信息系统安全稳定,支持业务发展要求等信息科技相关工作。
招聘的专业也是像计算机、软件工程、电子工程、自动化、管理科学与工程、数学等计算机相关这样的专业,所以从工作性质与招收的专业我们也能看出来银行科技岗的笔试一定是会考专业知识的。
一般软件开发中心的专业知识考题和软件设计的题目比较类似,包括计算机系统结构方面、网络方面、软件工程、操作系统、数据库、数据结构,再就是JAVA、C、C++、C#、SQL、RPG、COBOL等开发语言方面的题。
数据中心的专业知识考题则更偏IT系统工程师的考试题,比如操作系统(如Linux、AIX、HP-UX),数据库的相关操作(如MySQL、DB2),计算机网络(如网络地址、网络设备、防火墙、IPS/IDS)等。
四、考试难度如何?
笔试
内容大多是:行测、英语、计算机基础、性格测试。
行测:这部分也挺恶心的,主要包括逻辑推理、言语理解、数字运算、逻辑判断、资料分析等,主要考察逻辑思维能力
英语:题型有阅读理解、单项选择、完型填空等等
计算机基础:主要是计算机的一些基础知识,c、Java、数据库、计算机网络、操作系统、信息安全等等
性格测试:通常笔试最后是性格测试
一般来说,银行笔试难度较大,一是因为考查的内容很广,比如EPI里包括了数量关系、数字推理、资料分析、言语理解、判断推理等科目;
二是题量相对于考试时间而言非常大,每题平均分配时间不到1分钟;
三是部分银行对科技岗单独出题,题目专业度非常高,像2021年建行就考了计算机网络、操作系统、软件工程、信息安全、中间件、主要分布体系及架构、设计模式、数据结构与算法、开发语言语法、数据库(语法)等方面的知识。
面试 一面,主要是技术面,会问些计算机的基础知识,Java、数据路、计算机网络、操作系统等等,以及做过的一些项目。
二面,有些银行仍然是半结构化面试(就是和一面一样,面试官问,你回答),有些银行则是会进行无领导小组面试,可能会有团队协作、主题辩论等形式,主要考察沟通能力、组织能力、团队协作能力。
上面说的是一些主流银行,还有一些银行如招银网络,笔试、面试、工作强度都和互联网类似,号称技术体系最强的银行。
五、金融科技岗的职业发展
进入到该岗位的会先从信息技术部专员做起,前期会有些辛苦,接到项目工作可能需要加班加点完成,大约经3年到5年的磨练,会逐步做到团队长、副总、总经理,一直到部分老总级别。
当然,如果希望有更进一步发展的同学,还是需要选择调至业务条线增加阅历,才能从部门老总的位置上突破至副行长等位置。
毕竟,银行是以业务为导向的。不管怎样,走IT条线的同学会比营销岗和服务岗前期更轻松一些,专业性也更强一些,因此收入也相对更加稳定些(但后者如果业务做的好,收入也可以很高)。
六、想进银行的金融科技岗?
继去年秋招之后,在今年春季的校招、社招中,部分国有大行、股份行以及地方性商业银行仍不断向金融科技人才抛出橄榄枝。还有的银行对IT人才明码实价,开出了较其他待招岗位更高的薪酬。
在2022年启动的春季校园招聘中,多家银行直接开设“金融科技专场”。
进入2月,农业银行、交通银行、浦发银行、南京银行、成都银行等相继发布了春季招聘公告,在各类岗位的招聘需求中,科技类人才需求依然旺盛。其中,交行在今年的金融科技部门校园招聘中公布了人数,合计招聘900人,其中软件工程师岗位招聘人数达700人。
除了全国性银行,多家区域性银行也加大了金融科技相关人才招聘力度。近期,锦州银行、汉口银行、泰隆银行发布的春季校园招聘里均有相关岗位需求。
有华东某城商行的科技部负责人表示,结合人才招聘的经历,非一线城市招聘专家很难,而校园招聘成为该行另辟蹊径培养科技人才的主要方式。
求职者反馈:
在很多应届生眼里,非一线城市的银行科技岗也是不错的选择。“地方的银行金融科技公司、金融科技部都是不错的机会,虽然待遇可能不如一线大厂,也不如总行,但是也不受银行存款指标等传统业务的限制。”有应届生表示。
科技部经理反馈:
“后期我们行招不到成熟的专家,我们行从零开始。在211高校里,招聘数学、统计相关的研究生。”部分科技部负责人表示。
应届生相对社会招聘来说,缺少丰富的工作经验和实战经验,上述科技部总经理称,2021年又招了不少应届生,招聘之后,不仅是自己银行进行培养,也会与科技公司有很多业务往来,例如与科技公司交互分析等,有助于人才的培养和成长。这种模式也类似与上述几家大中型银行的金融科技管培生,后续对全行不同条线进行了人才输出,现在这个团队目前在线上贷款等业务条线、公司业务等条线上,都发挥了比较大的重要作用。
七、金融IT需求依然旺盛
银行重视金融科技人才背后,不仅是因为用户需求导致银行不断加快科技投入、提高科技能力,例如,银行客户的需求逐步转向线上,银行的金融服务需要云端运算、网路安全、人工智慧及机器学习技术等不同的技术,而且监管对于金融业的数字化建设也提出了要求。
2022年1月4日,央行印发《金融科技发展规划(2022-2025年)》(下称《规划》),提出将以加强金融数据要素应用为基础,以深化金融供给侧结构性改革为目标,以加快金融机构数字化转型、强化金融科技审慎监管为主线,将数字元素注入金融服务全流程,将数字思维贯穿业务运营全链条,注重金融创新的科技驱动和数据赋能,力争到2025年实现整体水平与核心竞争力跨越式提升。
1月26日,银保监会印发《关于银行业保险业数字化转型的指导意见》,要求银行保险机构结合实际认真贯彻落实。《指导意见》指出,充分利用科技手段开展个人金融产品营销和服务,拓展线上渠道,丰富服务场景,加强线上线下业务协同。构建面向互联网客群的经营管理体系,强化客户体验管理,增强线上客户需求洞察能力,推动营销、交易、服务、风控线上化智能化。
“基础技术的供给越来越丰富,部署的成本是在直线下降,金融行业确实有相对于其他行业充足资金的预算,吸引非常多的优秀人才加入金融科技相关工作。”有接近监管人士认为。
八、银行的金融科技岗的待遇怎么样?
注:以下数据来源于网上数据统计和相关人士分享,不同银行不同地区待遇存在差异,具体情况以各大行及地方分行数据为准。
根据目前的情况来看,科技岗可以算是一个风口岗位。据说某行总行软件中心数据,银行提供的薪资是高于均值的,部分核心IT岗位甚至比互联网名企的相关岗薪资高。
当然,很多同学进入银行科技岗并不是追求薪资,而是追求“生活和身体上的可持续发展”,把银行与其他的互联网企业相比,银行的业务量、工作压力、工作时长都要比其他的互联网企业小的多。同时在银行工作时,技能也可以得到锻炼,在金融科技上深入钻研。
薪资 下面简单说下各大银行的基本薪资待遇,取的中位数(大多数人爆料的薪资),仅供参考哈,未说明学历,默认为硕士。
整体来说:
不管是哪家银行,可影响薪资的因素有很多,他们包括:地域经济发展水平、网点业务水平、地区市场占有率、岗位等,这些都可能会影响你的薪资。
我们找工作考虑的因素是不同的:有的同学主要考虑薪资,有人考虑附加的福利,有人会考虑工作时间,有人会考虑是否离家近。但无论哪一点,银行相比于其他行业,在工作稳定性、薪资福利等方面都有很大优势!
如果同学们想要在毕业前,敲定一份稳定高薪且体面的工作,而不需要跟其他毕业生在人才市场抢破头,那么今年银行招聘就是大家最好的机会。由于银行基本只招应届生,因此这是你们第一次,也是唯一一次进入银行的绝佳机会了。
Java文件上传大杀器-绕waf(针对commons-fileupload组件) Ps:高版本才有1.3以上
来个中二的标题,哈哈哈,灵感来源于昨晚赛博群有个师傅@我是killer发了篇新文章,在那篇文章当中提到了在filename="1.jsp"的filename字符左右可以加上一些空白字符%20 %09 %0a %0b %0c %0d %1c %1d %1e %1f,比如%20filename%0a="1.jsp"(直接用url编码为了区别)这样导致waf匹配不到我们上传⽂件 名,⽽我们上传依然可以解析,我对次进行了更深入的研究,也是对师傅文章对一次补充,下面为了衔接还是先梳理一遍,看过赛博群的师傅可以先跳过前面的部分,直接看最后一部分(毕竟我想发个博客)
上传代码 针对使⽤commons-fileupload处理⽂件上传
public class TestServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { String path = "/Users/y4tacker/Desktop/JavaStudy/testtest"; try { ServletFileUpload servletFileUpload = new ServletFileUpload(new DiskFileItemFactory()); servletFileUpload.setHeaderEncoding("UTF-8"); List<FileItem> fileItems = servletFileUpload.parseRequest(request); for (FileItem fileItem : fileItems) { response.getWriter().write(fileItem.getName()); fileItem.write(new File(path+"/"+fileItem.getName())); } }catch (Exception e){ } } } 前置分析 将断点打在servletFileUpload.parseRequest(request),跟入getItemIterator
一直往下到org.apache.commons.fileupload.FileUploadBase.FileItemIteratorImpl#FileItemIteratorImpl
Content-Type 要开头为 multipart/ 接下来对流的处理部分忽略,到下面有个this.
知晓云在2019年十月份左右就上线了微信小程序订阅消息这个服务,后来迭代升级,又相继提供了相应的sdk插件,然而这之前,我却没有很认真,花精力去使用这些服务,刚好国庆几天假,我就熬了两个通宵,将这个小程序订阅消息的知晓推送服务集成到了我自己的微信小程序上,下在就来讲讲我实现的步骤.
首先得有一个自己的已经写好的微信小程序比如本站的微信小程序《无忧电脑技巧网》,就算是没有,也可以用微信小程序开发者工具生成的demo小程序,也能完成本篇文章中讲到的效果.
一、微信小程序端的部署
1、在知晓云,中创建一个应用,然后完成微信小程序的授权。
2、然后点击刚才新建的应用,然后点击知晓推送,在自己微信小程序项目中的app.json 中加入插件的引用声明,如下图所示,sdk的最新版本号是3.14.3
在微信小程序项目中的app.js中加入接入向导中指定的几段代码,如下图
在 app.js 文件中完成 SDK 的初始化,然后保存重新编译一下微信小程序,完成后,在接入向导中点一下,初始化校验,校验通过后,就能进入下一步,上报订阅状态这里.
3、上报订阅状态
如下图所示,在小程序页面加入一个按钮,或者是image图片,然后绑定一个方法”subscribeMessage”
然后,在page.js中加入这个果js方法,如下图.
最后在小程序源码中的改造,还有最后一下,就是要在page.js中的data中给id赋一个值,这个值,就是在微信小程序后台申请订阅消息模板的模板id,然后再次编译一次微信小程序.
二、知晓云,知晓推送端的操作
上图中,这个跳转链接,让我觉得奇怪,为什么从微信小程序中获得的文章链接”pages/detail/detail.html?id=28″不能直接在小程序消息卡片中直接跳转,非要改造成”pages/detail/detail?id=28″才能达到目的?
最终效果如下图.
写在最后,为什么在市面上已经有提供多种多样的开源微信小程序,而且也支持了,微信小程序的订阅消息,但是就使用wordpress做微信小程序后台,大多数提供订阅消息功能的小程序,多是以wordpress插件来实现的,有此局限性,比如,我是企业版小程序,可以选用文章更新的模板,而个人主体的小程序就无法选择文章更新的模板,如果要改变一下的话,那么就只有改插件的源代码来实现了,所以我就化繁为简,使用”知晓推送”开发微信小程序订阅消息功能,国庆假期结束后,就去上线发布.
torch.cuda.is_available函数总返回False问题解决 一、问题描述(使用网上两种解决方法仍不能解决)1. 网上总结的方法一:根据自己cuda版本按照官网提供的安装命令安装pytorch2. 网上总结的方法二:去NVIDIA官网安装最新驱动 二、问题分析三、解决方法 一、问题描述(使用网上两种解决方法仍不能解决) 在import pytorch后,使用以下函数:
torch.cuda.is_available() 这个函数返回True即为使用了cuda,但是我这里总是返回False。
1. 网上总结的方法一:根据自己cuda版本按照官网提供的安装命令安装pytorch 如果函数返回False,一般是pytorch及其组件与cuda版本不对应导致的,这个可以查看pytorch的官网(https://pytorch.org/get-started/locally/),官网给出了不同cuda版本下安装pytorch的命令,直接复制命令安装对应版本pytorch即可。
cuda版本查看可以通过在命令行使用以下命令查看:
nvcc -V 结果如下图,可以看到我这台电脑使用的cuda是11.3版本的。
于是我按照网上的方法,按照我的cuda版本11.3使用了对应的安装命令:
conda install pytorch torchvision torchaudio cudatoolkit=11.3 -c pytorch 然后再使用torch.cuda.is_available()函数,还是返回False。
2. 网上总结的方法二:去NVIDIA官网安装最新驱动 我去了NVIDIA官网(https://www.nvidia.cn/geforce/drivers/)根据自己的显卡版本,下载了最新的驱动,驱动版本已更新到511.79:
然后再使用torch.cuda.is_available()函数,仍然返回False。
二、问题分析 我用以下命令检查了一下当前环境的安装包:
conda list 发现在列表中有一个cpu版本的pytorch包(问题已解决没来得及截图)。我认为可能是这个包的存在所以导致pytorch一直是使用cpu版本的。
所以我使用以下命令卸载了pytorch:
conda uninstall pytorch 然后我再根据pytorch官网上的提供的命令,安装了cuda11.3对应的pytorch。然后再使用torch.cuda.is_available()函数,终于返回True了啊啊啊啊啊啊啊啊。
所以可能是我先前安装pytorch时没有使用官网建议的命令,然后重新使用官网提供的命令安装时又没有把原先安装的pytorch卸载,所以导致后来安装的pytorch可能版本正确了但默认使用cpu版本的pytorch。
三、解决方法 如果在确认了已使用pytorch官网建议的安装命令安装pytorch了,并且显卡驱动是官网上最新的驱动了,但torch.cuda.is_available函数仍然返回False,那么可以尝试将已安装的pytorch卸载干净,卸载命令:
conda uninstall pytorch 然后再根据官网提供的命令安装对应版本的pytorch。
使用JKD8提供的时间工具 获取当年的开始时间 和去年开始时间
LocalDateTime thisYear = LocalDateTime.of(LocalDate.now().getYear(), 1, 1, 0, 0, 0); LocalDateTime lastYearStr = LocalDateTime.of(LocalDate.now().minusYears(1).getYear(), 1, 1, 0, 0, 0); 运行结果:
将时间戳转换为日期格式:
第一个是String类型的时间戳
第二个是Long类型
LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochSecond(Long.parseLong("1647310688")), ZoneId.systemDefault()); LocalDateTime localDate = LocalDateTime.ofInstant(Instant.ofEpochSecond(1647310688L), ZoneId.systemDefault()); 运行结果:
public static void main(String[] args) { //今年 LocalDateTime thisYear = LocalDateTime.of(LocalDate.now().getYear(), 1, 1, 0, 0, 0); System.out.println("thisYear = " + thisYear); //去年 LocalDateTime lastYearStr = LocalDateTime.of(LocalDate.now().minusYears(1).getYear(), 1, 1, 0, 0, 0); System.out.println("lastYearStr = "
PowerDesigner一键导入数据库所有表并画数据模型图
五分钟学会PowerDesigner创建概念数据模型 PowerDesigner设计的pdm模型导出超清图片
PowerDesigner工具栏消失恢复 目录
一、工具栏
二、点击工具-自定义菜单和工具栏
三、选择Palette即可
一、工具栏 不小心点到工具栏右上角的关闭按钮了,需要恢复下
二、点击工具-自定义菜单和工具栏 三、选择Palette即可 有用请点赞,养成良好习惯!
疑问、交流、鼓励请留言!
同样的三维世界当中的,当面言语,与看书文字。同样的言语,表达出来,可能效果也是完全不一样的。 不得不说,一个人的想法随着时间的移动而改变,变化的. 之前几个月前您或许是拿到目前收入,胜任目前工作就基本满足了。但是随着形势的发展变化, 个人想法也是完全跟随变化的. 就是几个月前,半年前认为可以的收入,在胜任后的几个月后,觉得也没有什么,甚至于仅仅糊口收入. 这是个人主观想法的变化,个人主观想法的随时变化所在. 当然,您的客观收入,也确实仅仅入行开发,一个普通开发的薪资待遇水平,完全没有溢价的收入。 不过虽然变化,存在,但是基本上个人做事方向,定型的了。
曾经的心酸付出,也成为个人开发历史的一个不可或缺的部分了,也是浓墨重彩的一页了。另外向着继续往上的心,还是有激情的. 甚至于有时候是激情洋溢的,只是随着时间的推移,恐怕激情也会退却. 所以,客观优势的扩大,就是迫切需要逐步实现的事情. 唯独文字,可以把时间定格.就是此时此刻。内心想法的文字定格. 一个最牛逼的程序员,该是什么样子的? 目前可能就是隔壁老王,隔壁老张,隔壁老陈那样子.先达到隔壁老王的样子,再说然后,或许更加现实. 这个与您的往上爬台阶,不冲突.甚至可以说是相辅相成. 只有趁着隔壁大佬,打游戏的时候,您也在努力写代码,还有什么不能超越的呢? 没有不能超越的
论文下载:https://arxiv.org/abs/2111.11837
源码下载:https://github.com/yzd-v/FGD
Abstract 知识蒸馏已成功应用于图像分类。然而目标检测要复杂得多,大多数知识蒸馏方法都失败了。本文指出,在目标检测中,教师和学生的特征在不同的区域有很大的差异,尤其是在前景和背景中。如果我们平均蒸馏它们,特征图之间的不均匀差异将对蒸馏产生负面影响。因此,我们提出了局部和全局蒸馏(FGD)。局部蒸馏分离了前景和背景,迫使学生将注意力集中在老师的关键像素和通道上。全局蒸馏重建不同像素之间的关系,并将其从教师传递给学生,以补偿局部蒸馏中丢失的全局信息。由于我们的方法只需要在特征图上计算损失,FGD可以应用于各种检测器。我们在各种不同backbone的检测器上进行了实验,结果表明,学生检测器实现了良好的mAP提升。例如,基于ResNet-50的RetinaNet、FasterRCNN、RepPoints和Mask RCNN使用了我们的蒸馏方法在COCO2017上实现了40.7%、42.0%、42.0%和42.1%的MAP,分别比基线高3.3、3.6、3.4和2.9。
1、Introduction 最近,深度学习在各个领域取得了巨大的成功。为了获得更好的性能,我们通常使用更大的backbone,这需要更多的计算资源和更慢的推理。为了克服这个问题,人们提出了知识蒸馏。
知识蒸馏是一种将大型教师网络中的信息继承到一个紧凑的学生网络中,并在推理过程中不增加额外成本而获得强大性能的方法。然而,大多数蒸馏方法都是为图像分类而设计的,这导致了目标检测的微小提升。
众所周知,前景背景的极端不平衡是目标检测中的一个关键问题。不平衡的比率也会影响目标检测的蒸馏。对于这个问题人们也做了一些努力。Chen[3]等人分配权重以抑制背景。Mimick[17]蒸馏学生的RPN网络提出的感兴趣区域。FGFI[31]和TADF[28]分别使用细粒度和高斯Mask来选择蒸馏区域。Defeat[9]分别蒸馏前景和背景。然而,蒸馏的关键区域在哪里还不清楚。
图1 教师检测器(RetinaNet-ResNeXt101)和学生检测器(RetinaNet-ResNet50)的空间和通道注意力图可视化 为了探索学生和教师的特征之间的差异,我们进行了空间和通道注意力的可视化。如图1所示,学生的注意力和老师的注意力在前景中的差异非常显著,而在背景中的差异相对较小。这可能会导致学习前景和背景上的不同的困难。在本文中,我们进一步探讨了前景和背景的知识蒸馏对目标检测的影响。我们通过分离蒸馏过程中的前景背景来设计实验。令人惊讶的是,如表1所示,前景和背景同时蒸馏的性能最差,甚至比只在前景或背景中蒸馏的性能更差。这一现象表明,特征图中的不均匀差异会对蒸馏产生负面影响。此外,如图1所示,每个通道之间的注意力也非常不同。再深入一步,不仅前景和背景之间存在负面影响,像素和通道之间也存在负面影响。因此,我们建议进行局部蒸馏。在分离前景和背景的同时,局部蒸馏还计算教师特征中不同像素和通道的注意力,使学生能够聚焦于教师的关键像素和通道。
表1.不同蒸馏区域的对比 fg:前景 bg:背景 Split:将前景和背景分开,用不同的权重蒸馏它们 然而,仅仅关注关键信息是不够的。众所周知,全局上下文在检测中也起着重要作用。许多关系模块已成功应用于检测,如non-local[32]、GcBlock[2]、relation network[14],极大地提高了检测器的性能。为了弥补局部蒸馏中丢失的全局信息,我们进一步提出了全局蒸馏。在全局蒸馏中,我们利用GcBlock提取不同像素之间的关系,然后把它们从教师蒸馏到学生。
图2 FGD的说明,包括局部蒸馏和全局蒸馏。局部蒸馏不仅可以分离前景和背景,还可以使学生网络更好地关注教师网络特征图中的重要信息。全局蒸馏弥合了学生和教师的全局上下文之间的差距
正如我们在上面所分析的,我们提出了局部和全局蒸馏(FGD),结合了局部蒸馏和全局蒸馏,如图2所示。所有损失函数仅根据特征计算,因此FGD可直接用于各种检测器,包括两阶段网络、基于anchor的一阶段网络和anchor-free的一阶段网络。在没有华丽的点缀下,我们通过FGD实现了最先进的目标检测性能。简而言之,本文的贡献如下:
1、我们提出,教师和学生关注的像素和通道是相当不同的。如果我们提取像素和通道而不区分它们,它将只有一个微不足道的改进。
2、我们提出了局部和全局蒸馏,这使学生不仅关注教师的关键像素和通道,而且还了解像素之间的关系。
3、通过在COCO[21]上的大量实验,我们验证了我们的方法在各种检测器上的有效性,包括单阶段、两阶段、无锚方法,都实现了最先进的性能。
2、Related Work 2.1 object Detection 目标检测是计算机视觉中一项基本的、具有挑战性的任务。基于CNN的高性能检测网络分为两阶段[1,10,25]、基于anchor的单阶段[20,22,24]和无锚的单阶段检测器[7,29,36]。单阶段检测器直接在特征图上获取目标的分类和bounding box。相比之下,两阶段检测器利用RPN和RCNN获得更好的结果,但花费更多的时间。anchor boxes为单阶段模型提供了proposals来检测目标。然而,anchor boxes的数量远远超过目标的数量,这带来了额外的计算。而无锚检测器则提供了一种直接预测目标关键点和位置的方法。虽然有不同的检测头,但它们的输入都是特征。因此,我们的基于特征的知识蒸馏方法可以应用于几乎所有的检测器。
2.2 Knowledge Distillation 知识蒸馏是一种不改变网络结构的模型压缩方法。Hinton等人[13]首先提出了这一方法,该方法使用输出作为soft labels,将暗知识从大型教师网络转移到小型学生网络,用于分类任务。此外,FitNet[26]证明来自中间层的语义信息也有助于指导学生模型。已经有很多工作[12,30,37,38]显著提升了学生分类器。
最近,一些工作已经成功地将知识蒸馏应用于检测器。Chen等人[3]首先通过提取neck特征、分类头和回归头上的知识,将知识蒸馏应用于检测。然而,由于前景和背景之间的不平衡,提取整个特征可能会引入很多噪声。Liet al.[17]从RPN中取样来计算蒸馏损失。
Wang et al.[31]提出了细粒度mask来提取由ground truth计算出来的区域。Sunet等人[28]利用高斯Mask来覆盖ground truth用于,这种方法缺乏对背景的蒸馏。在不区分前景和背景的情况下,GID[6]提取了学生和教师表现不同的区域。Guo等人[9]指出,前景和背景对蒸馏都起着重要作用,将它们分开蒸馏对学生更有利。这些方法都从背景中提取知识,并取得了显著的效果。然而,它们平等地对待所有像素和通道。FKD[39]使用注意力masks和非局部模块[32]分别来引导学生和蒸馏关系。然而,它同时蒸馏前景和背景。
用于检测的蒸馏的关键问题是选择有价值的蒸馏区域。以前的蒸馏方法对所有像素和通道进行同等对待[6,9,28,31],或将所有区域一起蒸馏[39]。大多数方法缺乏对全局上下文信息的蒸馏。在本文中,我们使用ground truth来分离图像,然后使用教师的注意力mask来选择关键部分进行蒸馏。此外,我们捕获不同像素之间的全局关系,并将其蒸馏给学生,这带来了另一个改进。
3、Method 大多数检测器都使用FPN[19]来利用多尺度语义信息。来自FPN的特征融合了来自backbone的不同层次的语义信息,并用于直接预测。从老师那里转移这些特征的知识显著提高了学生的表现。一般来说,特征的蒸馏可以表述为:
式中,Ft和Fs分别表示教师和学生的特征,f()表示自适应层来将Fs reshape为与Ft相同的维度。H、 W指定特征的高度和宽度,C代表通道。
然而,这种方法对所有部分都一视同仁,缺乏对不同像素之间全局关系的蒸馏。为了克服上述问题,我们提出了FGD,它包括局部蒸馏和全局蒸馏,如图2所示。这里我们将详细介绍我们的方法。
3.1 Focal Distillation 对于前景和背景的不平衡,我们提出了局部蒸馏来分离图像,并引导学生聚焦于关键像素和通道。蒸馏区域的比较如图3所示。
图3 比较我们的方法(FGD)和其他方法之间的蒸馏区域。FGFI和GID仅蒸馏红色边界框中的区域。在训练期间,GID和FKD蒸馏的区域是可变的。不同的颜色表示不同的权重,绿色部分表示空间注意力像素
首先,我们设置了一个二进制mask掩码M来分离背景和前景:
其中,r表示gt boxes,i,j分别表示了特征图的水平和垂直坐标。如果(i,j)落在ground truth中,那么M(i,j)=1,否则为0。
较大尺度的目标由于像素较多,会造成较大的损失,从而影响小目标的蒸馏。在不同的图像中,前景和背景的比例差异很大。因此,为了平等对待不同的目标,平衡前景和背景的损失,我们设置了一个尺度mask S:
其中,Hr和Wr表示ground truth r的高度和宽度。如果一个像素属于不同的目标,我们选择最小的框来计算S。
SENet[15]和CBAM[34]表明,关注关键像素和通道有助于基于CNN的模型获得更好的结果。Zagoruyko et al.
目录
项目场景
解决思路
方案实施
项目场景 一个项目由 A 开发团队和 B 开发团队共同开发,由于网络等客观因素的限制,两个开发团队需要分别将代码提交到位于不同服务器上的 A 仓库 和 B 仓库的 develop 分支。A 团队成员可以访问 A 仓库和 B 仓库,B 团队成员只能访问 B 仓库。为了实现 A 仓库和 B 仓库的同步,需要 A 开发团队的负责人每天将两个仓库 develop 分支的代码进行同步更新。
解决思路 在 B 仓库里拉一个 develop-merge 的分支,每次把 A 仓库 develop 分支的代码覆盖到这个分支,再把 B 仓库的 develop 分支合并到 develop-merge 分支。最后覆盖回 A 仓库的 develop 分支,并 merge 到 B 仓库的 develop分支。在 B 仓库的 develop-merge 分支合并代码,合完后有两个方向,一是拷贝到 A 仓库的本地目录,再提交;二是 merge 到 B 仓库的 develop 分支。 方案实施 A 开发团队和 B 开发团队分别在 A 仓库和 B 仓库的 develop 分支上提交所有代码。
1、下载yolov5 6.0源码 2、转换为ONNX格式(参数一定要全,很关键!!!) python export.py --weights yolov5n.pt --img 640 640 --batch 1 --train --simplify --include onnx #或者 python export.py --weights yolov5n.pt --img 640 640 --batch 1 --train --simplify --include onnx --opset 11 3、简化ONNX模型 python -m onnxsim yolov5n.onnx yolov5n-sim.onnx 4、转为NCCN格式文件 ~/ncnn/build/tools/onnx$ ./onnx2ncnn yolov5n-sim.onnx yolov5n.param yolov5n.bin 5、更改yolov5n.param参数文件 将图中所指向的参数全改为-1,使输出的BBOX可以自适应
6、更改yolov5.cpp源文件 记住下面图中框出的数值
在cpp文件中对应处,填上相应的数值
7、测试
来一个demo
Category category = new Category(); Class<? extends Category> aClass = category.getClass(); Method[] methods = aClass.getMethods(); for (Method method : methods) { System.out.println(method.getName()); if("setId".equals(method.getName())){ try { //传参的时候类型要传对,不然抛异常的 method.invoke(category, 11l); } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } } } //查看是否设置成功 System.out.println(category.getId()); 打印的结果
通过属性名反射获取方法调用 import org.springframework.util.ObjectUtils; import org.springframework.util.ReflectionUtils; import java.lang.reflect.Method; import java.lang.reflect.Field; import java.beans.PropertyDescriptor; private boolean checkSingleParam(Object o, String propertyName){ if(Objects.isNull(o)){ return false; } Field companyNameField = ReflectionUtils.findField(o.getClass(), propertyName); try { PropertyDescriptor propertyDescriptor = new PropertyDescriptor(companyNameField.
从键盘任意输入a,b,c的值,编程计算并输出一元二次方程ax2 + bx + c = 0的根(较小的先输出)。根据一元二次方程的求根公式,令
p = −b2a, q = b2−4ac√2a
假设a,b,c的值能保证方程有两个不相等的实根(即b2 - 4ac > 0)
#include<stdio.h> #include<math.h> int main() { float a, b,c; double p, q, m, n, x1, x2; printf("Please enter the coefficients a,b,c:"); scanf("%f,%f,%f", &a, &b, &c); m= b/a; n= sqrt(b * b - 4.0 * a * c) / a; p = -1.0 / 2.0 * m; q = 1.0 / 2.0 * n; x1 = p + q; x2 = p - q; if (x1 < x2) { printf("
JPEG格式是一个很老的格式了,笔者刚刚认识5寸软盘的时代就知道这种文件是用来保存图片的,而且比同尺寸的“bmp”图片要小很多。很多年过去了,信息技术各个领域全面发展,视频编解码技术更新换代了好几轮,然而大家从网页上看到的、自己磁盘里存储的、照相机/手机拍摄的,仍然以这种格式的图片为主。曾经有人将JPEG称为“来自未来的外星科技”。
为什么JPEG能够流行这么长的时间呢?一个很重要的原因固然是它流行得很早,但另外一个原因则是这种图片编码格式体现了基于主流图片/视频压缩技术最根本的世界观和方法论。本文就以JPEG中最基本最常用的Baseline-DCT模式为例,简单回顾下JPEG编解码技术的整体概况和若干细节。
一. 基本概况 JPEG支持多种编解码模式。最基本的Baseline-DCT支持8比特sample,熵编码采用哈夫曼编码,然而扩展DCT模式则能够支持12比特的sample,熵编码既可以用哈夫曼编码也可以用算术编码。
采样格式方面,支持纯亮度,YUV420,YUV422和YUV444。
分块方面,一律8x8大小分块。
JPEG标准可从ITU-T官网下载,标准编号是T.81。
二. 格式 JPEG文件中的语法单位基本是由marker来组织的。每个marker都是由0xFF开头的一个16位整数,标记接下来的数据内容。对于熵编码部分,如果出现了0xFF则要填充一个0x00。
下面列一些重要的marker:
SOI:即start of image的意思。应出现在文件最开头。纯marker。
SOFn:即start of frame。n取值0到15。其中SOF0即为最基本的Baseline-DCT。
DQT:量化表。大小和块的大小一致(8x8)。编码时除解码时乘。
DHT:哈夫曼编码表。
SOS:即start of scan。一个frame可分为多个scan。
DNL:用于分隔scan。
RSTm:若出现在熵编码中,可使熵编码过程重新开始。m取0~7。
EOI:即end of image。应出现在文件结尾。
总体结构如下图:
其中Tables主要指的就是DQT和DHT。ECS就是熵编码段落。MCU指的就是编码的块。
三. 块的编解码流程 对于编码来讲,过程如下
预测DCT变换Zigzag扫描量化熵编码 下面挨个介绍:
预测。很多人说JPEG没有帧内预测,所以其压缩效率才赶不上当今的技术。然而事实上JPEG在进行DCT变换前会将块内所有值都减去128。这样做相当与128就是所有块的预测值,减去128后得到的就是残差数据。从这个角度看JPEG算是有空域上的预测。HEVC在帧内预测中,如果某PU参考的采样点都无法获取,也会将预测值设成128。DCT。8x8二维离散余弦变换。Zigzag扫描。从左上角到右下角扫描。量化。块中每个值除以当前量化表中对应位置的值。这里会有信息损失。注意zigzag的顺序不能和量化搞反。熵编码。最复杂的步骤。DC分量和AC系数的编码方式不同。DC分量会在各块间建立一个差分序列,然后对残差进行编码(也相当于一种频域上的帧内预测)。每个残差先是进行Exp-Golomb(指数哥伦布)编码,然后将4位的指数部分进行Huffman编码,最后直接输出幅度部分。对于每个AC系数则先变成RRRRSSSS的8比特形式,其中RRRR表示前面有多少个0系数,SSSS为后面的非0系数的指数哥伦布编码的指数部分,然后把RRRRSSSS整个进行Huffman编码,最后同样直接输出非0系数的幅度部分。如果当前块剩下的AC系数全部是0,则RRRRSSSS等于0;否则若0系数个数大于等于16个,则RRRRSSSS=0xF0,表示16个0。 而解码过程需要将上述步骤的顺序和内容都反过来,即反熵编码、反量化、反zigzag、反DCT、反预测。
可以看出与当今的技术用的都是一种套路。
熵编码中多个component则按照Y、U、V的顺序,逐个plane进行编码。而色度的扫描方式要先把一个亮度大小的方块区域内按照从左到右从上到下的顺序编码完成再进行下一个亮度方块内的色度编码。如下图所示:
这里面值得一提的是,AVC和HEVC用熵编码过程中都使用了一种自适应的二进制算术编码(CABAC),Huffman编码由于只有在每个符号概率在2的n次方时才能够达到最理想压缩比,同时缺少自适应机制,压缩比会照CABAC差不少。但实际上JPEG标准中的对于扩展DCT模式定义了一种自适应的算术编码的算法,其基本原理和CABAC一致,但是其执行效率和压缩比都照CABAC差了一些。据统计使用了算术编码的JPEG比baseline-JPEG缩小了%4~%6。后来JPEG又进一步改进了该算法。
四 . 优缺点 第一个缺点是压缩得不彻底(跟目前的技术比)。各个块之间,无论是DC分量还是各个AC分量,在进入熵编码阶段时仍然具有一定的相关性。
第二个缺点是artifect严重。在压缩比较高的情况下,在图片平缓的部分由于低频系数的信息损失会产生严重的blocking效果;而在图片具有强烈边缘的地方由于高频系数的信息损失则会产生严重的ringing效果。JPEG标准没有定义任何针对artifect的滤波器。
第三个缺点则是没有支持alpha通道。这个问题使得在需要alpha通道时,即便对于照片类的图片人们也会选择png格式。但实际上如果JPEG支持alpha的话,照片类图片很可能无论是压缩效率上还是解码速度上都强于png。
最后一个缺点也是所有有损压缩的缺点,每次压缩都会损失一部分信息。png压缩也会丢失信息,但是当你把它解码出来再用同样的参数压缩时,不会有额外的信息损失了;但是JPEG每次编码都会有损失。所以说大家的表情包越传越模糊发绿,也是这个原因。
那么优点是什么呢?就是简单,编解码速度超快,适合并行计算。目前智能手机虽然性能提高了很多了,但是要让CPU实时跑HEVC编码还是非常勉强(也许以后都会用硬编硬解?),但是对JPEG的编解码却完全没有问题。libjpeg-turbo这个库大概是目前最快的jpeg编解码库了,利用了主流架构的SIMD指令,很适合移动端使用。
五. 可能的替代者 WebP。谷歌的格式,衍生自谷歌的VP8视频编码格式。支持clipart,支持动画,支持alpha通道。据说压缩效率比JPEG高,但是也有人指出其实跟JPEG差不多。但总归是比png要好。个人觉得它代替png和gif更合适些。另外libwebp的api设计得很不好用,速度也慢。
HEIF。开发者是MPEG。苹果公司力推的格式,在苹果电脑上已经支持。原理其实就是把HEVC的单帧压缩技术拿出来用。可以想象得到,其压缩效率应该是极高的(应该能达到JPEG的55%),但同时运算复杂度也会很高。
BPG。开源项目,还在开发中。和HEIF一样都是HEVC的单帧压缩技术。然而由于HEVC的各个部分都被专利保护,因此这种格式前途未卜。来自2022年的更新:歇菜了,如先所料。
packJPG。这是一种专门针对JPEG文件进行无损压缩的格式。比baseline-JPEG大小缩减大约20%左右,可以说是非常可观了。它更充分地利用了JPEG中一些属性间的相关性。
Lepton。Dropbox公司在packJPG的基础上开发的格式,同样是专门针对JPG的。比baseline-JPEG大小缩减大约23%左右,同时相对于packJPG大大提高了编解码速度。用于节省Dropbox中JPEG文件的存储空间。
Pik。怀疑为谷歌某些工程师的业余项目。其目标是在保证解码速度不低于JPEG 40%的情况下,大小缩减为JPEG的65%。目前正在开发中,据说使用了一些新技术。来自2022年的更新:歇菜了,不过Pik和另外一种格式FLIF被集成到了Joint Picture Expert Group——即原jpeg标准的制订组织以及“JPEG”缩写所表示的含义——近年来开发的新一代图片格式JPEG XL的标准中。
个人觉得JPEG的替代者应该继承JPEG简单高速的优点。上述列表中的Lepton和Pik是比较契合这一点的。仍然应该避免进行复杂帧内预测以及由此带来的R-D优化。
来自2022年的更新:笔者相信JPEG XL会最终胜出。如先所述,JPEG XL是Joint Picture Expert Group 近年来制订的新一代图片压缩标准,虽然还没有最终完成,但是目前它与其他对手的Benchmark显示JPEG XL不但对JPEG有了不小的提高,对其他竞争对手也有不同方面的优势,比较符合人们对JPEG替代者的期待。
问题描述 点击超链接(微信中的,或者markdown,或者word中的)都没有反应,像是没有点击一样
问题解决 方案零 根据一些同学的反馈和资料的查询,我发现另外一种问题成因和解决方案
在此感谢一下这位博主
https://blog.csdn.net/CoolBoySilverBullet/article/details/123479887
问题成因 原因应该是 chrome 的启动参数被 KGChromePlugin 金格插件篡改了,从而导致部分第三方应用(实测,微信、vscode、cmd都不行,但是 QQ 可以)无法调用 chrome 打开超链接
解决方式 在浏览器中输入chrome://version/
查看配置文件中是否含有--register-pepper-plugins
根据后面的路径信息,找到 KGChromePlugin 所在的文件路径,通常是C:\Program Files (x86)\KGChromePlugin,然后在文件夹中找到卸载程序KGPMUninstall.exe,双击进行卸载即可
卸载之后,重启一下 chrome,这个时候我出现了以下问题chrome打不开了,可以选择重启电脑。再去看一次命令行应该就恢复正常了,此时也能在已打开 chrome 的情况下在第三方应用中顺利打开超链接了
方案一 对浏览器进行升级更新
方案二 对默认浏览器进行刷新,设置默认浏览器
然后将浏览器改为随便的除了google浏览器以外的浏览器
然后在更改会google浏览器
方案三 控制面板卸载了重新安装
注意不要清除浏览器数据
这样装回来的时候所有的配置和插件还有用户登录信息都是在的
总结 我实际使用过程中方案零和方案二和方案三都有效果
方案一来自于网上(当然也有说360杀一下毒的我试了但是没有卵用,我也并不认为360真的就可以解决)
参考文献 【日常踩坑】修复 chrome 打不开微信或者部分第三方应用内链接_ywang_wnlo的博客-CSDN博客
这是 os summer of code 2020 项目每日记录的一部分:
github地址:https://github.com/yunwei37/os-summer-of-code-daily
其他一些 rust 的小练习:
笨办法系列 参考:Learn C The Hard Way 中文版
c32-list: 练习32:双向链表c33-sort: 练习33:链表算法c40-bst: 练习40:二叉搜索树c42-stack-queue: 练习42:栈和队列c38-hashal:练习38:哈希算法 Leecode题目用Rust实现 参考:https://leetcode-cn.com/problemset/all/
文件夹中包含:
README.md: 题目的出处和相关描述信息solution.rs: rust语言实现代码solution.c: c语言的实现代码 题目目录:
leetcode-best-time-to-buy-and-sell-stock - 121. 买卖股票的最佳时机leetcode-binary-tree-inorder-traversal - 94. 二叉树的中序遍历leetcode-game-of-life - 289. 生命游戏leetcode-maximum-depth-of-binary-tree - 104. 二叉树的最大深度leetcode-maximum-subarray - 53. 最大子序和leetcode-remove-element - 27. 移除元素leetcode-set-matrix-zeroes - 73. 矩阵置零leetcode-valid-parentheses - 20. 有效的括号leetcode-longest-consecutive-sequence - 128. 最长连续序列leetcode-friend-circles - 547. 朋友圈 双向链表 注意,这里是很早的时候写的代码,实际上实现双向链表最好要使用 weak 来避免循环引用和内存泄漏问题。
数据结构定义: use std::rc::Rc; use std::cell::RefCell; use std::clone::Clone; #[derive(Debug)] struct ListNode { value :i32, next: Option<Rc<RefCell<ListNode>>>, prev: Option<Rc<RefCell<ListNode>>> } #[derive(Debug)] pub struct List{ count: i32, first: Option<Rc<RefCell<ListNode>>>, last: Option<Rc<RefCell<ListNode>>> } 函数实现 impl ListNode { fn new(value:i32) -> Rc<RefCell<ListNode>>{ let pointer = Rc::new(RefCell::new(ListNode { value, next: None, prev: None, })); Rc::clone(&pointer) } } impl List { pub fn new() -> List { let first = ListNode::new(0); let last = ListNode::new(0); first.
1. 背景 什么是线程池? 线程池技术是池化技术的一种。除了线程池,还是内存池、连接池等其他池化技术。打个比方来说,线程池是将若干个随时可以执行任务的线程放在“池子”这种容器中,当我们要使用线程的时候,从线程池中取出即可;使用完成后再将线程归还给线程池,以便下次或者其他用户使用。
本项目为什么需要线程池? 使用线程池技术的最大好处是服务器可以避免因重复的建立和销毁线程带来的开销,从而提高服务器对客户端的响应速度。
此外,一个线程从诞生到结束,在系统中存在的时间可以分成三个阶段:创建耗时t1, 工作时间t2,销毁耗时t3。
n = t 2 t 1 + t 2 + t 3 n = \frac{t2}{t1+t2+t3} n=t1+t2+t3t2
为了提高服务器的效率,我们应该尽可能的增大t2,减少t1和t3。但一般来说,减少t1和t3是一个比较困难的事情,所以自然而然的会想到提高t2的时间。
目前,线程池技术的应用已经是一件很常见的事情了。该技术原理并不复杂,实现起来也较为容易。对于网络编程人员来说,这是一个必须得掌握的知识。
2. 实现 在编写一个线程池类之前,你需要具备以下知识:
Linux多线程编程;常见的数据结构;C++11编程; 在理解了线程池的工作原理后,自己动手实现一个并不算难。下面po出一张线程池的原理示意图:
线程池类设计要点:
如何定义线程需要去执行的“任务”(Tasks): 首先要明确的一点是,“任务”是函数。无论你是使用Linux C的pthread库,还是C++的库,创建一个线程,为了让线程工作,都需要向线程传递一个函数。然而,这个函数是需要预先声明和定义的。但是在线程池工作的时候,如果我们想要线程执行不同功能的函数,不可能提前知道并声明和定义好。所以,为了让线程执行不同的函数,传递给线程的函数中,会调用其他的函数以实现执行正确的任务; 选择合适的容器:对于线程,数组这类容器就能满足要求;而对于工作队列(Task Queue),可以选择队列或者链表。正确的上锁:本质上,线程池类可以简化成生产者/消费者模型。线程执行task是在消耗资源,往线程池中添加task是在生产资源。这里的资源指的就是需要执行的函数。生产者/消费者模型中,有好几种上锁的方式:互斥锁+条件变量、信号量等。选择一种你习惯使用的就行。 如果你理解到线程池的本质是生产者/消费者模型后,其实如何编写这个类已经清晰很多了。你可能对于如何向线程池中添加不同的函数还感到疑惑,别着急,接着往下看。
我们可以把函数看做是一个对象,在线程池类的接口中,传递不同的函数,也就是传递不同类型的对象。这里引用C++的模板编程(template)。像我们常用的STL容器,例如vector, queue都是使用模板。在定义的时候并不知道,将来使用时将会是什么类型。
基于C++的模板编程,线程池类的对外接口append定义如下:
class ThreadPool { public: /* ... */ template<class F> void append(F &&task) { // 上锁 m_resEmpty.wait(); m_mtx.wait(); m_jobQueue.emplace(std::forward<F>(task)); // 解锁 m_resource.post(); m_mtx.post(); } } 代码非常的简短啊,但是却能实现将不同类型的函数,添加进工作队列中。
当然,为了让工作队列能够存放不同类型的函数,同时编译不发生错误,我是这样定义的:
std::queue<std::function<void()>> m_jobQueue; // 工作队列 std::vector<std::thread> m_workThreads; // 线程 对外接口append函数中,除了上述提到的template模板,还使用了C++11的【右值引用】、【完美转发】、【function】以及【信号量】。右值引用和完美转发一般来说是都会是成对出现的。使用右值引用的原因是为了能够让函数能够接受临时变量作为参数,而完美转发简单来说是让左值始终是左值,右值始终是右值,不改变变量在这方面的属性。function是一个通用的多态函数包装器。在这可以理解成一种不定类型函数,向队列中添加任何类型的函数都不会发生冲突。
二. 常用API vector / list / deque vector<int>v(n, val); v.resize(n, val); vv.resize(n, vector<int>(m, val)); // 二维数组 v.insert(v.begin(), val); v.erase(v.begin() + i); v.push_back(val); v.pop_back(); v.size(); v.empty(); // deque / list deque<int>dq; dp.push_front(val); // 头部插入 dp.pop_front(val); // list list<int>lst; lst.merge(lst2); // 合并有序链表 lst.reverse(); // 反转链表 lst.remove(val); // 删除值为val的所有元素 stack / queue / priority_queue stack<int>st; st.push(val); st.pop(); st.top(); queue<int>q; q.push(val); q.pop(); q.front(); priority_queue<int>pq; // 大根堆, 小根堆 priority_queue<int,vector<int>,less<int>>; // 自己实现cmp结构体, 小根堆 priority_queue<Node>pq; struct Node { int x; friend bool operate< (Node a, Node b) { return a.
思维导图:
1、函数依赖 • 定义:设R(U)是属性集U上的关系模式,X、Y是U的子集。若对R(U)的任何一个可
能的关系r,r中不可能存在两个元组在X上的属性值相等,而在Y上的属性值不等,
则称X函数决定Y或Y函数依赖于X,记作:X→Y
• 如果X→Y,那么对于任意两个相同的X,所对应的Y是一定相同的。
• 如果X→Y,但Y⊈X,则称X→Y是非平凡的函数依赖。一般情况下总是讨论非平凡
的函数依赖。
• 如果X→Y,但Y⊆X,则称X→Y是平凡的函数依赖。
2、完全函数依赖与部分函数依赖
• 定义:在R(U)中,如果X→Y,并且对于X的任何一个真子集X',都有X'不能决定Y,则称Y对X完全函数依赖,记作:X→Y。如果X→Y,但Y不完全函数依赖于X,则称Y对X部分函数依赖,记作:X→Y。部分函数依赖也称局部函数依赖。
例:选课关系SC1(学号,课程号,成绩),F={(学号,课程号)→成绩}。
(学号,课程号)→成绩,学号⇸成绩,课程号⇸成绩。
选课关系SC2(学号,课程号,学生姓名,课程名称,成绩),F={(学号,课程号)
→成绩,(学号,课程号)→课程名称,(学号,课程号)→学生姓名,学号→学生
姓名,课程号 →课程名称}。
3、传递函数依赖
• 定义:在R(U,F)中,如果X→Y,Y→Z,Y⊈X,Y⇸X,则称Z对X传递依赖。
例:供应商(Sno,Sname,Status,City,Pno,Qty),及函数依赖集如下,判断该
关系是否存在传递函数依赖和部分函数依赖。
F={Sno→Sname, Sno→Status, Status→City,(Sno,Pno)→Qty}
码 1、候选码和主码:设K为R(U,F)中的属性的组合,若K→U,且对于K的任何一个真子集K',都有K'不能决定U,则K为R的候选码,若有多个候选码,则选一个作为主码。
• 候选码通常也可以称为候选关键字,主码通常也可以称为主关键字或主键。
• 包含在任何一个候选码中的属性叫做主属性,否则叫做非主属性。
例:选课关系SC1(Sno,Cno,Sname,Cname,G)
选课关系SC2(Sno,Cno,Sname,Cname)
2、外码:若R(U)中的属性或属性组X非R的码,但X是另一个关系的码,则称X是R的外(ForeignKey)或称外键。
例:学生(学号,姓名,班主任,所属学院)
教师(职工号,姓名)
学院(编号,名称)
多值依赖 • 多值依赖具有如下6条性质:
1、多值依赖具有对称性。即若X→→Y,则X→→Z,其中Z=U-X-Y。
2、多值依赖的传递性。即若X→→Y,Y→→Z,则X→→Z-Y。
3、函数依赖可以看成是多值依赖的特殊情况。
4、若X→→Y,X→→Z,则X→→YZ。
5、若X→→Y,X→→Z,则X→→Y ⋂Z。
6、若X→→Y,X→→Z,则X→→Z-Y。
项目场景: 今天 Mac 安装 iTerm2,附带主题、oh my zsh 插件,一切正常。今天运行项目,发现不能用 npm、node、nvm 等命令。
上网找了很多方案,最终受 stackoverflow 一篇帖子启发,成功得到解决。
废话不多说,解决方案如下:
## 只需要按照以下步骤,打开zsh的配置文件,放开宏命令即可 ##第一步 打开配置文件 open ~/.zshrc ##第二步 找到下面这行,你会发现plugin右边的配置默认只有git 这时候你可以自由添加你想要用的,用空格隔开。(node nvm yarn npm )等等 然后保存 'plugins=(git)' -> 'plugins=(git node nvm yarn npm)' ## 第三步 更新配置文件,启用修改 source ~/.zshrc ## 最后一步 重启终端,再尝试一切是否正常 希望能帮到你。
That’s all.
论文地址: https://openreview.net/pdf?id=KmykpuSrjcq
开源代码:Prototypical Contrastive Learning of Unsupervised Representations
摘要 原型对比学习(PCL),一种连接对比学习和聚类的无监督表示学习方法。PCL不仅学习了实例识别任务中的低级特征,更重要的是,它将通过聚类发现的语义结构编码到学习到的嵌入空间中。引入原型作为潜在变量,以帮助在期望最大化框架中找到网络参数的最大似然估计。通过E-step聚类寻找原型的分布,并执行M-step,通过对比学习优化网络。提出了ProtoNCE损失,一个关于对比学习的InfoNCE损失的广义版本,它鼓励表示更接近其分配的原型。
介绍 无监督视觉表示学习旨在不依赖标签而从像素本身学习图像表示,最近的进展很大程度上来自实例对比任务。这些方法通常由两个关键的组成部分组成:图像变换和对比损失。图像转换的目标是通过数据增强、斑块扰动或使用动量特征生成代表同一图像的多个嵌入。对比损失,以噪声对比估计器的形式,旨在使来自同一实例的更接近的样本,并从不同实例中分离样本。
尽管实例识别方法的性能得到了改进,但它们也有一个共同的缺点:不鼓励表示来编码数据的语义结构。这个问题的出现是因为实例级对比学习将两个样本视为负对,只要它们来自不同的实例,而不管它们的语义相似性如何。由于产生了成千上万的负样本来形成对比损失,导致许多负对共享相似的语义,但在嵌入空间中被不希望地分开,这一事实被放大了。
本文作者提出了原型的对比学习(PCL),这是一种新的无监督表示学习框架,它隐式地将数据的语义结构编码到嵌入空间中。图1显示了PCL的说明。原型被定义为“一组语义上相似的实例的代表性嵌入”。我们为每个实例分配了几个不同粒度的原型,并构造了一个对比损失,从而使样本的嵌入更类似于相应的原型。在实践中,我们可以通过对嵌入进行聚类来找到原型。
典型的对比学习的说明。每个实例都被分配给多个具有不同粒度的原型。PCL学习一个编码数据语义结构的嵌入空间。
将典型的对比学习制定为一种期望最大化(EM)算法,其目标是找到最能描述数据的深度神经网络(DNN)的参数分分布,通过迭代逼近和最大化对数似然函数。具体地说,我们引入原型作为额外的潜在变量,并通过执行k-means聚类来估计它们在e步中的概率。在m步中,我们通过最小化我们提出的对比损失来更新网络参数,即ProtoNCE。在假设每个原型周围的数据分布是各向同性高斯分布的情况下,最小化ProtoNCE等价于最大化估计的对数似然。在EM框架下,广泛使用的实例识别任务可以解释为原型对比学习的一种特殊情况,其中每个实例的原型都是其增广特征,每个原型周围的高斯分布具有相同的固定方差。本文的贡献可以总结如下:
1.我们提出了原型的对比学习,一个新的框架的无监督表示学习,桥梁对比学习和聚类。我们鼓励学习到的表示来捕获数据集的层次语义结构。
2.我们给出了一个理论框架,将PCL作为一个基于期望最大化(EM)的算法。聚类和表示学习的迭代步骤可以解释为近似和最大化对数似然函数。以往基于实例识别的方法在所提出的EM框架中形成了一个特例。
3.我们提出了一种新的对比损失方法,它通过动态估计每个原型周围特征分布的浓度来改进广泛使用的InfoNCE。ProtoNCE还包括一个InfoNCE术语,其中的实例嵌入可以被解释为基于实例的原型。我们从信息理论的角度对PCL提供了解释,通过显示学习到的原型包含了更多关于图像类的信息。
4.PCL在多个基准测试上优于实例级对比学习,在低资源迁移学习方面有了显著的改进。PCL还可以导致更好的聚类结果。
原型对比学习 准备工作
给定n个图像的训练集X={x1,x2,...,xn},无监督视觉表示学习旨在学习一个嵌入函数fθ(通过DNN实现),该函数用vi=fθ(xi)将X映射到V={v1,v2,...,vn},这样vi最好地描述xi。实例式对比学习通过优化对比损失函数来实现这一目标,如InfoNCE,其定义为:
在典型的对比学习中,我们使用原型c代替v,用每个原型浓度估计φ代替固定温度τ。我们的训练框架的概述如图2所示,其中聚类和表示学习在每个时代迭代执行。
原型对比学习的训练框架
PCL期望最大化
在E-step中与MoCo类似,我们发现来自动量编码器的特征产生了更一致的簇。
在M-step最大对数似然估计为,(原文里有详细的推导过程):
其中,表示原型周围特征分布的浓度水平,将在后面介绍。请注意,最大对数似然估计形式与InfoNCE损失相似。因此,InfoNCE可以解释为最大对数似然估计的特殊情况,其中特征vi的原型是来自同一实例的增强特征(即c=),并且在每个实例周围的特征分布的集中程度是固定的(即φ=τ)。
在实践中,我们采用与NCE和样本r负原型样本相同的方法来计算归一化项。我们还将不同数量的簇聚类,对编码层次结构的原型具有更稳健的概率估计。此外,我们还增加了InfoNCE损失,以保持局部平滑性,并帮助引导聚类。我们的总体目标,即ProtoNCE,被定义为
浓度估计
每个原型周围的嵌入物的分布有不同的浓度水平。我们使用来表示浓度估计,其中越小表示浓度越大。定义为:
互信息
研究表明,最小化InfoNCE是为了最大化表示V和之间的互信息(MI)的下界。同样地,最小化所提出的原型可以看作是同时最大化V和所有原型{V0,C1,...,CM}之间的互信息。
首先,编码器将学习原型之间共享的信息,并忽略每个原型中存在的单个噪声。共享的信息更有可能捕获更高层次的语义知识。其次,我们表明,与实例特征相比,原型与类标签有更大的互信息。我们比较了我们的方法(ProtoNCE)和MoCo(InfoNCE)获得的MI。如图3(b)所示,与实例特征相比,由于聚类的影响,原型具有类标签的MI。此外,与InfoNCE相比,在ProtoNCE上的训练可以随着训练的进行而增加原型的MI,这表明可以学习到更好的表示来形成更有语义意义的集群。
原型作为线性分类器
PCL的另一种解释可以为学习原型的本质提供更多的见解。最大对数似然估计类似于使用交叉熵损失来优化聚类分配概率,其中,原型c表示一个线性分类器的权重。通过k-means聚类,线性分类器有一组固定的权值作为每个聚类中表示的平均向量,。
实验略。
结论 本文提出了原型对比学习,一种通用的无监督表示学习框架,通过寻找网络参数来最大化观测数据的对数似然。我们引入原型作为潜在变量,并在一个基于EM的框架中执行迭代聚类和表示学习。PCL通过对原型损失的训练来学习编码数据语义结构的嵌入空间。我们在多个基准测试上的广泛实验证明了PCL在无监督表示学习方面的优势。
论文中有详细的公式的推导过程,可以在原论文中查看公式的出处。
namespace概念及常用操作 什么是namespace应用场景新建namespace查看namespace内置的namespace两种指定资源namespace的方法命名空间资源配额 使用kubens切换所在命名空间安装kubens命令kubens切换命名空间 什么是namespace k8s将资源对象逻辑上隔离,从而形成多个虚拟集群.
应用场景 每个单独的项目建议单独创建一个namespace.
根据不同团队划分namespace根据项目划分namespace可以对namespace权限进行划分.用户只能查看自己的空间 新建namespace # 新建namespace kubectl create ns blog 查看namespace [root@master ~]# kubectl get ns NAME STATUS AGE default Active 19h kube-node-lease Active 19h kube-public Active 19h kube-system Active 19h kubernetes-dashboard Active 15h blog Active 15h 内置的namespace default # 默认的namespace kube-node-lease # k8s内部namespace kube-public # 公开的namespace kube-system # k8s系统方面的namespace kubernetes-dashboard # dashaboard使用的namespace blog # 用户自行创建的blog 两种指定资源namespace的方法 命令行加 -n namespace名称yaml资源元数据里指定namespace字段 命名空间资源配额 为命名空间配置内存和 CPU 配额
一、什么是Hash # 1、核心理论:
Hash,一般翻译做散列、杂凑,或音译为哈希,是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
# 2、Hash的特点:
从hash值不可以反向推导出原始的数据输入的数据的微小变化会得到完全不同的hash值,相同的数据会得到相同的值哈希算法的执行效率要高效,长的文本也能快速地计算出哈希值hash算法的冲突概率要小 由于hash的原理是将输入的空间的值映射成hash空间内,而hash值的空间远小于输入的空间。根据抽屉原理,一定会存在不同的输入被映射成相同输出的情况。
抽屉原理:桌上有是个苹果,要把这十个苹果放到九个抽屉里,无论怎样放,我们会发现至少会有一个抽屉里面放不少于两个苹果。这一现象就是我们所说的“抽屉原理”。
二、HashMap中常量、成员变量以及构造方法分析 // 缺省table容量16 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // table最大容量2的30次方 static final int MAXIMUM_CAPACITY = 1 << 30; // 默认的负载因子0.75 static final float DEFAULT_LOAD_FACTOR = 0.75f; // 链表树化阈值 static final int TREEIFY_THRESHOLD = 8; // 树降成链表阈值 static final int UNTREEIFY_THRESHOLD = 6; // 树化阈值的另一个参数,当桶元素数量超过64个,并且链表达到阈值8,才会进行树化 static final int MIN_TREEIFY_CAPACITY = 64; // HashMap类中的静态内部类Node链表 static class Node<K,V> implements Map.Entry<K,V> { final int hash; final K key; V value; Node<K,V> next; Node(int hash, K key, V value, Node<K,V> next) { this.
第一章:概念 1.为什么要拆分: ①MySQL 实例内部结构
1.单一架构
[2]复制架构:
尽管搭建了复制架构,但是实际上从逻辑上来说仍然只有一个 db_hr 数据库。
②性能瓶颈
MySQL 工作过程中的性能瓶颈主要来自于下面三个方面(同等硬件条件下):
数据存储量:单表 1000 万条数据达到极限;500 万条开始性能明显下降;300 万条开始就应该考虑拆分。I/O 瓶颈:关系型数据库以硬盘作为主要存储介质,所以必然存在 I/O 瓶颈。访问量瓶颈:通常 MySQL 的最大连接数默认是100,最大可以达到 16384。 由此我们可以看出,对数据库进行拆分主要是出于数据量不断增加的挑战。
2、拆分方式 ①垂直拆分 垂直拆分是最容易想到的拆分方式。它按照项目的业务功能模块,把从属于不同模块的数据库表分散到对应的不同数据库中。
这种拆分的优缺点: -优点: -拆分的规则明确,不同的功能模块或者服务模块分配到不同的数据库 -数据库维护与定位简单 -缺点: -并没有解决单表数据量太大的问题 -会出现跨库join -需要对上层应用系统的代码进行重构,修改原有的事务操作 ②水平拆分
针对一张数据量很大的表,把它拆分为多张表,数据分流保存到各个拆分后的数据库表中。
如果数据量继续增加,超过一个单库能够容纳的极限则需要继续分库:
这种拆分方式的优缺点评价: - 只分表不分库: - 同库无分布式事务问题,事务处理相对简单 - 同库无跨库 join 问题 - 表拆分后不存在超大型表的性能问题 - 只要拆分规则定义好,很难出现扩展性的限制,但拆分规则设定并不简单 ,规则一定会和业务挂钩,如根据 id、根据时间等。 - 既分表又分库: - 异库存在分布式事务问题 - 异库存在跨库 join 问题 - 多数据源管理难度加大,代码复杂度增加 3、MyCat 简介 尽管拆分后面临很多问题,但是随着数据量的增加又不得不拆,mycat就是帮助我们实现这个功能的:
MyCat 是一款数据库中间件。
对于应用程序来说完全透明:不管底层的数据如何拆分,应用只需要连接 MyCat 即可完成对数据的操作。