/** * 跨域支持相关配置 */ @Configuration @EnableWebMvc public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { //设置允许跨域的路径 registry.addMapping("/**") //设置允许跨域请求的域名 .allowedOrigins("*") //是否允许证书 不再默认开启 .allowCredentials(true) //设置允许的方法 .allowedMethods("*") //跨域允许时间 .maxAge(3600); } /** * 跨域配置后swagger2可能不能访问,需要增加如下配置 * @param registry */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("swagger-ui.html") .addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/"); } }
计算机网络原理笔记 第四章 传输层 5.1传输层的两个协议5.1.1 TCP和UDP的应用场景5.1.2 传输层协议和应用层协议之间的关系5.1.3 服务和端口之间的关系 5.2 用户数据报协议 UDP5.2.1 UDP 协议的特点5.2.2 UDP 的首部格式 5.3传输控制协议 TCP5.3.1 TCP 协议主要的特点5.3.2 TCP 报文的首部格式 5.4 可靠传输5.4.1 TCP可靠传输的实现-停止等待协议5.4.2 连续 ARQ 协议和互动窗口协议-改进的停止等待协议5.4.3以字节为单位的滑动窗口技术详解5.4.4改进的确认-选择确认(SACK)5.4.5超时重传的时间调整 5.5 流量控制5.6 拥塞控制5.6.1拥塞控制的原理5.6.2拥塞控制方法-慢开始和拥塞避免5.6.3拥塞控制方法-快重传和快恢复5.6.4发送窗口的上限 5.7 TCP连接管理5.7.1 TCP的连接建立5.7.2 TCP连接释放 5.1传输层的两个协议 5.1.1 TCP和UDP的应用场景 网络中的计算机通信无外乎有以下两种情况:
1.要发送的内容多,需要将发送的内容分成多个数据包发送。
2.要发送的内容少,一个数据包就能发送全部内容。
针对这两种情况,在传输层有两个协议,TCP(Transmission
Control Protocol 即传输控制协议)和UDP(User Datagram
Protocol即用户数据报协议)。
5.1.2 传输层协议和应用层协议之间的关系 应用层协议很多,传输层就两个协议,如何使用传输层两个协议
标识应用层协议呢?
传输层协议加一个端口号来标识一个应用层协议,展示了传输层
协议和应用层协议之间的关系。
- 一些常见的应用层协议和传输层协议,以及它们之间的关系。
HTTP默认使用TCP的80端口标识。
FTP默认使用TCP的21端口标识。
SMTP默认使用TCP的 25端口标识。
POP3默认使用TCP的110端口。
HTTPS默认使用TCP的443端口。
DNS使用UDP的53端口。
远程桌面协议(RDP)默认使用TCP的3389端口。
Telnet使用TCP的23端口。
Windows访问共享资源使用TCP的445端口。
微软SQL数据库默认使用TCP的1433端口。
mySQL数据库默认使用TCP的3306端口。
5.1.3 服务和端口之间的关系 Windows和Linux操作系统有些服务为本地计算机提供服务,有些服务为网络中的计算机提供服务。
为网络中计算机提供服务的服务,一旦启动就会使用TCP或UDP的某个端口侦听客户端的请求。
itextpdf版本:5.5.13
遇到的问题:
创建模板的时候,文本域宽度固定,设置一个比较长的字符串时,超过文本框长度,多余部分不显示
如 阿尔伯特·爱因斯坦:
解决办法:
不断判断使用某fontSize后文字宽度是否大于文本框宽度,直到找到满足文本框宽度的fontSize
代码见下
public static void main(String[] args) { try { String pdf = "/Users/xieshanwu/Documents/Pdf模板.pdf"; Map<String, String> txtFields = new HashMap<>(); txtFields.put("name", "阿尔伯特·爱因斯坦"); InputStream input = new FileInputStream(new File(pdf)); String fileName = "填充后的pdf.pdf"; File file = new File(fileName); FileOutputStream fos = new FileOutputStream(file); PdfReader reader = new PdfReader(input); PdfStamper stamper = new PdfStamper(reader, fos); // 提取PDF中的表单 AcroFields form = stamper.getAcroFields(); // 设置中文字体 BaseFont baseFont = BaseFont.
word最后一页的空白页按delete键删不掉,我遇到了表格后面的情况,经过查询,我发现还有其他的情况,这里记录下来方便日后查看。
感谢此链接
一、存在段落标记
如果因为空白页存在段落标记或者换行标记,只要选中标记,按Backspace键将其删除即可。
二、插入分隔符
由于插入分隔符而产生的空白页,只要显示段落标记(快捷键为Ctrl+Shift+8),之后将光标定位在分页符处,按Delete键即可删除。
三、以表格结束
由于文档是以表格结束而在下一页而产生的空白,这时将光标定位在空白页并选中段落标记,然后右击选择段落将行间距更改为固定值,将其设置为1磅即可删除空白页。
卖一个小萌,嘿嘿
深度学习自学记录(7)——yolov3的整体流程四大步详细纪录 1、整体流程2、解码得到预测结果3、编码过程4、loss的计算5、yolov3整体思路整理完毕 1、整体流程 YOLO系列是很流行的目标检测模型。现在已经更新到yolov4版本,但最经典的还是yolov3版本,v4可以说是对yolov3的一些列改进手段的最优组合。
yolov3总得来讲可以分为四大模块:
(1)特征提取+yolohead:获得模型的输出y_pre;
(2)y_pre的解码:将y_pre转化为预测结果,得到真实图片上的预测框的位置(Xmin,Xmax,Ymin,Ymax)、框的得分以及目标类别;
(3)真实标签的编码:将标签文件中的真实值转化成与y_pre相同形式的tensor——y_true;
(4)loss值计算:对比y_pre,y_true计算loss值进行训练。
第一部分的过程很简单,对图片进行特征提取并输出一定shape的tensor,本篇博客主要记录一下解码得到预测结果,编码过程以及loss计算的部分。
2、解码得到预测结果 yolo输出的结果中包含三个不同尺度的特征层,我们以13x13的特征层介绍解码思路:
首先明确一点:13x13的特征图中一共有13x13个网格点,每一个网格点负责右下角方框区域的预测。
【1】每一个网格点产生3中不同尺度的先验框,一共是13x13x3个先验框。在输出的(4+1+num_class)中包含每一个每一个先验框的信息:
4:先验框的调整系数,分别是x_offest,y_offest,w,h1:先验框内包含目标的置信度,box_confidenceunm_class:每一个类别的概率,判断属于哪一类,box_class_probs 【2】我们利用4中的信息来确定预测框的位置:通过x_offest,y_offest对网格点进行偏移,得到框的中心点的坐标,再经过图像尺寸(scale = input_shape/13)的缩放,就可以得到真实图片上预测框的中心点的坐标(x,y)。效果图如图所示
通过w和h对先验框(anchor)进行微调,得到框的实际宽高,再根据图像尺寸(scale = input_shape/13)的缩放,就可以得到真实图片上预测框的实际宽和高(w,h)。至此得到了实际预测框的位置信息(x,y,w,h)。
【3】我们利用1+num_class得到预测框的得分:box_confidence是预测框含有物体的概率,box_class_probs是每一个类别的概率值,两者存在这一个正相关的关系,所以代码中 box_scores = box_confidence * box_class_probs,框的得分=框的置信度x类别置信度。至此得到了实际预测框的得分box_scores 。
【4】通过上面的方法,我们可以得到三个特征层上所有的预测框,一共13x13x3+26x26x3+52x52x3个预测框。最后,对这些框进行两个筛选,得到最终的预测输出值。第一次筛选:根据box_scores 与score_threshold对比,将得分低于阈值的框删除。第二次筛选:根据iou_threshold利用NMS在重叠度高于阈值的框中保留得分最高的框。
最终得到最后的输出结果!!!大功告成!!
3、编码过程 所谓编码,就是将真实框转化为yolov3输出的形式(基于网格点和anchor表达真实框的位置),以便计算loss值。说白了就是用三个特征图上的网格点和先验框表示真实框的位置,在数据(比如m,13,13,3,4+1+num_class)中存在真实框的点和anchor的位置有值,其他位置为0。——有些拗口,下面会解释。
编码的过程:
【1】从标签中获得真实框的中心以及宽和高,除去input_shape变成比例模式。
【2】创建包含三种特征层的全0列表,与yolov3的输出tensor的维度一致:(m,13,13,3,4+1+num_class)、(m,26,26,3,4+1+num_class)、(m,52,52,3,4+1+num_class),方便后面的数据写入;
【3】计算每一个真实框与先验框(9中不同的尺寸)的IOU,IOU最大的先验框负责那一个真实框的表达,同时根据先验框的尺寸和真实框中心点坐标得到所属特征层以及特征层上网格点的位置。至此我们明确了所有真实框用哪一个anchor表达,确定了这个先验框的所属特征层和网格点,得到形如(m,13,13,1)的tensor。
【4】明确表达真实框的先验框(先验框内有目标),下面就是求出相应的调参系数x_offest,y_offest,w,h,用网格点和anchor表示真实框。负责表达真实框的先验框置信度为1(为计算loss时的正样本,先验框内有目标),不负责表达真实框的位置全为0。并将有目标的先验框内目标类别转化为num_class维度,得到形如(m,13,13,1,4+1+num_class)的tensor——y_true;
至此,我们将全部的真实框转化为了不同特征图上的用先验框和网格点表达的形式。并且有目标的先验框置信度为1,是loss中的正样本,得到了最终的y_true。
4、loss的计算 loss值得计算就是求得模型的输出y_pre与真实值y_true的差距,训练的过程就是让y_pre靠近y_true的过程。
正样本:目标,存在真实目标而先验框框
负样本:背景,不存在真实目标的先验框,即正样本之外所有的先验框。
负样本要远远多于正样本,造成正负样本不平衡的问题
下面以13x13的特征层为例,介绍loss的计算过程:
【1】首先从y_true中取出该特征层中真实存在目标的先验框(m,13,13,1)(即负责表达真实框的先验框,正样本)和对应目标的种类(m,13,13,num_class),这些先验框真实存在目标,其置信度为1。
【2】一共包括三个部分的loss值计算:
x_offest,y_offest,w,h的位置损失:计算的是正样本(真实存在目标的先验框),利用y_pre和y_true的对比结果求得。class_loss分类损失:计算的是正样本(真实存在目标的先验框),利用y_pre和y_true的对比结果求得。置信度损失:计算针对正样本(真实存在目标的先验框)和负样本(除正样本之外的所有anchor,也即是背景,不真实真实目标)(1)--------对于正样本,y_pre的置信度与1对比求得loss;(2)--------对于负样本,首先舍弃一定数目的负样本,目的是为了正负样本的平衡(这也是为什么focalloss对yolov3的提升不大的原因),将IOU>0.5但不用来表达真实框的先验框舍去,不参与loss的计算;将剩下的负样本的模型输出y_pre与0对比求loss。 将三个特征层上的所有loss加在一起就得到了yolov3的loss值。至此loss计算完毕!!!需要注意的是
(1)正样本是真实存在目标的先验框,由y_true(置信度为1)决定
(2)正样本参与了所有loss值得计算
(3)部分负样本参与置信度损失的计算:为平衡正负样本,将真实框和先验框IOU<0.5的负样本保留,将y_pre与0对比计算置信度损失。
5、yolov3整体思路整理完毕 如有错误请指正
前面已经讲了基于live555实现rtsp流媒体代理服务器的完整的流程,以及高性能改造;核心的内容已经讲完了,这篇文章就做一个总结。看看这样做出来的服务器是否还有一些缺陷或者可能的问题。
总体上来说,按照前面的方法你已经可以实现了一个高性能的rtsp流媒体代理服务器了,或者叫rtsp协议媒体网关了;那么他还可能存在哪些问题呢?
1、live555递归问题:函数递归调用比较费cpu,而且不是一个推荐的处理方式,很多公司甚至直接禁止在代码中出现递归调用,不过live555中无法避免;我们怎么办呢?
1.1、对于信令处理来说,通常只有在异步通信出错的时候,才可能需要等待较长时间,导致递归调用不能及时返回;所以我们需要一台服务器(例如VMS)管理被代理前向设备状态,例如IPC相机;在设备下线后,不提供播放代理即可,这样即可避免大量的查询URL错误,或者播放失败,触发递归等待;
1.2、如果我们在live555代理服务器中,记录前向代理失败的会话,并进行一段时间的会话冻结,可以通过streamId来识别,这样也就很容易避免多线程并发时候,出现代理失败,而反复递归等待的问题了;
1.3、通过上述优化我们能够避免了95%以上,因为异步通信阻塞导致递归调用可能出现的性能损耗的情况,很大程度保证了系统cpu占用率的稳定性;
1.4、对于媒体处理来说,live555里面也有一些地方通过递归分析媒体流属性参数的情况;通常都是在流通道建立的时候,所以我们可以通过适当控制呼叫caps来减轻递归压力;这并不影响总体媒体流的吞吐量的,至少在安防应用场景下是不会有任何问题的。
2、媒体转发性能问题:live555对于转发大数据帧时,会出现一些丢包的问题,无论udp还是tcp都一样;通常情况,对于25fps流,我们可以控制1帧数据在40ms内发完即可,而不是前1ms发完,后面39ms没事干。这个逻辑live555实际已经实现了,只不过有些问题,稍稍优化控制一下就可以了。其他也有几个小地方可以优化,不过无伤大雅。目前我们转发数据,以10倍速转发录像数据,问题都不大,再高的话,才可能有丢包。
总体上,live555没有让人失望,达到了我们对流媒体服务器性能设计的需求;在华为提供的48虚拟核服务器上(还部署了其他服务),200路1080P@25fps,H264/H265媒体流转发,2-4Mbitps,输入输出总带宽在交换机上统计到的范围在600mbitps-1200mbitps之间。cpu使用率在200%-1200%之间,也就是相当于跑满2-6个cpu虚拟核心,大多数时间cpu在200%-400%之间;在早期施工阶段,片区IPC断网,导致流媒体服务器出现瞬时大量取流失败,会引起并发大量的live555递归调用,出现超时等待出错等处理,cpu使用上升到1200%左右。后续施工结束了,就很少出现了。特别是,现在加上了上面描述的caps控制等策略,基本就不会出现cpu飙升了。live555配置了1主+24从线程。
基于live555实现多线程代理服务器或点播服务器,其实是一个比较复杂的流程,为了方便后续的讲述,这里首先给出架构设计,或者说是思路吧!
1、首先需要找到创建多线程的点,或说时机;一般来说,至少有两种思路:一种是,单线程处理所有的rtsp消息或信令;使用多线程处理rtp/rtcp媒体流,类似信令和媒体分开处理,这种方法对于rtp over udp应该没有问题,但是rtp over rtsp的话,就有些复杂了,或者是否能够实现,我还不太确定;另一种就相对简单了,使用线程池的思路,在live555初始化时候,创建线程池,每一个线程完全独立运行,处理整个rtsp会话,只需要将公用资源加锁就可以了,为了节省端口资源可以将accept函数放在独立线程处理;基本上就是,accept函数在独立的主线程中,负责接收tcp连接;然后将接收的连接分配给负载的子线程处理rtsp会话,每个rtsp会话都在独立的一个负载子线程中处理;也就是一个主线程处理tcp连接,一个多线程的线程池,负载均衡的处理rtsp会话;我们实现的就是第二种相对简单的方法。
2、基于live555单线程事件调度的原理,以及上面的描述,所以我们需要确保每一个rtsp会话在同一个线程中进行处理;如何理解这句话,按照1中描述的思路,实际在tcp链接完成后,分配的单个线程来处理所有的rtsp消息,实际上已经初步确保了整个会话在独立的同一个线程中处理了;那这里单独拎出来讲是什么意思呢?因为,在rtsp会话过程中,一旦发生了tcp重连,就会导致重连的tcp连接进入accept主线程,会被重新分配线程处理,此时可能分配给了不同的线程,我们就需要进行线程切换了,需要确保出现tcp重连后,我们还能将该会话调度到原始的线程继续进行处理;什么时候会出现tcp重连,rtsp会话建立过程中,以及会话建立后,都可能会出现,所以这个线程切换需要在任何可能的时候执行,这也是多线程实现的主要难点;
3、完成了上述两步的处理实际就可以了,剩下只需要确保在一些公共资源的处理时,不要出现不同步的问题就可以了,也就是适当的对公共资源加锁即可;
废话讲的有些多,直接上代码了:
//多线程创建的时机,在服务器构造函数中创建线程池
GenericMediaServer::GenericMediaServer(UsageEnvironment &env, int ourSocket, Port ourPort,
unsigned reclamationSeconds, unsigned subThreadNum)
: Medium(env), fSubThreadNum(subThreadNum), fSubThreadList(NULL), fCapsControlTask(NULL),
fServerSocket(ourSocket), fServerPort(ourPort), fReclamationSeconds(reclamationSeconds),
fServerMediaSessions(HashTable::create(STRING_HASH_KEYS)),
fClientConnections(HashTable::create(ONE_WORD_HASH_KEYS)),
fClientSessions(HashTable::create(STRING_HASH_KEYS))
{
ignoreSigPipeOnSocket(fServerSocket); // so that clients on the same host that are killed don't also kill us
fSmssMutex = new Lock();//对应fServerMediaSessions
fCcsMutex = new Lock();//对应fClientConnections
fCssMutex = new Lock();//对应fClientSessions
if(fSubThreadNum) {
RTSP_CRIT("Create %d Extra Threads, Live555 Total Run On %d Threads!
去除首尾空格:
std::string& trim(std::string &s) { if (!s.empty()) { s.erase(0,s.find_first_not_of(" ")); s.erase(s.find_last_not_of(" ") + 1); } return s; } 去除所有空格:
void trim(string &s) { int index = 0; if(!s.empty()) { while( (index = s.find(' ',index)) != string::npos) { s.erase(index,1); } } }
主要任务时把分组从源端发送到目的端,为分组交换网上的不同主机提供服务。网络层传输单位是数据报
功能:
路由选择与分组转发(最佳路径 )异构网络互联拥塞控制 数据交换方式 电路交换:通信时延小、有序传输、没有冲突、实时性强、独占资源
建立连接时间长、线路独占,使用效率低,灵活性差,没有差错控制能力报文交换
分组交换 IP数据报格式 片偏移量=首地址/8
总长度单位是1B
片偏移量单位是8B
首部长度单位是4B
MTU:数据链路层可封装数据的最大传送单元。在以太网中MTU为1500字节
IP地址 分类的IP地址 全世界唯一的32位/4字节标识符,标识路由器主机的接口
IP地址 := (网络号,主机号) 点分十进制
路由器不同的接口有不同的IP地址
A类网络减去网络号全0(特殊地址)和全1(127,环回地址)
B类和C类都要减去网络号全0,不清楚为什么
最大主机数减去全0和全1.
特殊地址:
所谓的环回地址指的是该数据报不会实际发送出去,多用于测试。实际上就是自己。
私有IP地址不能在广域网中使用。
网络地址转换(NAT) 路由器对目的地址是私有IP地址的数据报一律不进行转发
网络地址转换NAT(Network Address Translation):在专用网连接到因特网的路由器上安装NAT软件,安装了NAT软件的路由器叫NAT路由器,它至少有一个有效的外部全球IP地址。
局域网中的计算机先将数据发送给NAT路由器,NAT路由器再以自己的IP发送给外网
外网会将信息发送给NAT路由器,NAT路由器再根据NAT转换表发送给应该接收的电脑。
将源IP和端口号(传输层概念)按照NAT转换表转换为可以在外网发送的源IP和端口号。同理,接收外部信息的时候也会首先发送给NAT路由器,再按照NAT路由器将目标IP和端口号更换为局域网中的私有IP和端口号
NAT转换表中LAN端有不同的IP地址,WAN端根据端口号对应不同的IP地址。
子网划分和子网掩码 分类IP地址的弱点:
IP地址空间的利用率有时很低两级IP地址不够灵活 将主机号拆分为子网号和主机号,当某些单位划分子网后,对外仍表现为一个网络,即本单位外的网络看不见本单位内子网的划分。
主机号至少要留下两位
如果只剩下一位,那么主机号要么全0要么全1,这都是不允许的。
子网号能够全0全1要看情况(一般子网划分不允许,只有CIDR中可以)
两级IP地址的子网掩码根据类别,比如B类的子网掩码就是255.255.0.0
三级IP地址的子网掩码也很简单,就是不变的地方都是1
子网网络地址:子网掩码与IP地址逐位相与
路由表中应该包含:
目的网络地址目的网络子网掩码下一跳地址 直接交付:路由器直接交给连接的子网
间接交付:路由器需要传给下一跳
路由器转发分组的算法:
提取目的IP地址是否直接交付特定主机路由检测路由表中有无路径默认路由0.0.0.0TTL耗尽,丢弃,报告转发分组出错 无分类编制CIDR 为了解决IP地址快要耗尽的情况
也叫做无分类域间路由选择CIDR
消除了传统A类、B类和C类地址以及划分子网的概念
CIDR记法:IP地址后加上/,然后写上网络前缀(可以任意长度)的位数融合子网地址和子网掩码,方便子网划分
CIDR地址块:CIDR把网络前缀都相同的连续的IP地址组成一个CIDR地址块
同前面一样,主机部分最多是所有情况-2(不能全0和全1)
如果给CIDR继续划分子网,子网号是可以全0、全1的。 地址块记法:最小地址
地址掩码(子网掩码):网络前缀部分全都是1
构成超网 将多个子网聚合成一个较大的子网,叫做构成超网,或者路由聚合。
方法:将路由前缀缩短
用相同的部分当作前缀
最长前缀匹配 使用CIDR时,查找路由表可能得到几个匹配结果,应该选择具有最长网络前缀的路由。(前缀越长,地址块越小,路由越具体)。
STP详解 冗余链路中存在的问题 如图所示LSW1和LSW2之间有两条线路相连,它们之间任何一条链路出现故障另外一条线路可以马上顶替出现故障的那条链路,这样可以很好的解决单链路故障引起的网络中断,但在此之前有下面三个问题需要考虑。
广播风暴
以太网交换机传送的第二层数据帧不像路由器传送的第三层数据包有TTL(Time To Live),如果有环路存在第二层帧不能被适当的终止,他们将在交换机之间永无止境的传递下去。结合交换机的工作原理,来看一下上面这张拓扑中广播风暴是如何形成的: 1、PC1发出一个广播帧(可能是一个ARP查询),LSW1收到这个广播帧,LSW1将这个广播帧从除接收端口的其他端口转发出去(即发往G0/0/2、G0/0/3、G0/0/4)。
2、LSW2从自己的G0/0/1和G0/0/2都会收到SW1发过来的相同的广播帧,LSW2再将这个广播帧从除接收端口外的所有其他接口发送出去(LSW2将从G0/0/2接收的广播帧发往其他三个端口G0/0/1、G0/0/3、G0/0/4,从fa0/24接收到的也会发往其他三个端口G0/0/1、G0/0/3、G0/0/4)。
3、这样这个广播帧又从G0/0/1以及G0/0/2传回了LSW1,LSW1再用相同的方法传回LSW2,除非物理线路被破坏,否则PC1-4将不停的接收到广播帧,最终造成网络的拥塞甚至瘫痪。
MAC地址表不稳定
广播风暴除了会产生大量的流量外,还会造成MAC地址表的不稳定,在广播风暴形成过程中:
1、PC1发出的广播帧到达LSW1,LSW1将根据源MAC进行学习,LSW1将PC1的MAC和对应端口G0/0/1写入MAC缓存表中。
2、LSW1将这个广播帧从除接收端口之外的其他端口转发出去,LSW2接收到两个来自LSW1的广播(从G0/0/1和G0/0/2),假设G0/0/2首先收到这个广播帧,LSW2根据源MAC进行学习,将PC1的MAC和接收端口G0/0/2存入自己的MAC缓存表,但是这时候又从G0/0/1收到了这个广播帧,LSW1将PC1的MAC和对应的G0/0/1接口存入自己的MAC缓存表。
3、LSW2分别从自己的这两个接口再将这个广播帧发回给LSW1,这样PC1的MAC地址会不停的在两台交换机的G0/0/1和G0/0/2(G0/0/3、G0/0/4)之间波动,MAC地址缓存表也不断的被刷新,影响交换机的性能。
重复帧拷贝
冗余拓扑除了会带来广播风暴以及MAC地址的不稳定,还会造成重复的帧拷贝:
1、假设PC1发送一个单播帧给PC3,这个单播帧到达LSW1,假设LSW1上还没有PC3的MAC地址,根据交换机的原理,对未知单播帧进行泛洪转发,即发往除接收端口外的所有其他端口(fa0/2、fa0/23、fa0/24)。
2、LSW2分从自己的G0/0/1和G0/0/2接收到这个单播帧,LSW2知道PC3连接在自己的G0/0/4接口上,所以LSW1将这两个单播帧都转发给PC3。
3、PC1只发送了一个单播帧,PC3却收到了两个单播帧,这会给某些网络环境比如流量统计带来不精确计算等问题。
STP介绍 基于冗余链路中存在的这些问题STP被设计出来用来解决这些问题,下面介绍STP的工作原理。
交换机上有默认的stp版本为mstp (多实例生成树)stp (生成树)rstp (快速生成树)
1、工作原理 STP通过拥塞冗余路径上的一些端口,确保到达任何目标地址只有一条逻辑路径,STP借用交换BPDU(Bridge Protocol Data Unit,桥接数据单元)来阻止环路,BPDU中包含BID(Bridge ID,桥ID)用来识别是哪台计算机发出的BPDU。在STP运行的情况下,虽然逻辑上没有了环路,但是物理线上还是存在环路的,只是物理线路的一些端口被禁用以阻止环路的发生,如果正在使用的链路出现故障,STP重新计算,部分被禁用的端口重新启用来提供冗余
STP使用STA(Spanning Tree Algorithm,生成树算法)来决定交换机上的哪些端口被堵塞用来阻止环路的发生,STA选择一台交换机作为根交换机,称作根桥(Root Bridge),以该交换机作为参考点计算所有路径。
2、选举:根网桥、根端口、指定端口、非指定端口 1)根网桥(根交换机)—在一棵生成树实例中,有且仅有一台交换机为root
选举:
比较每台交换机的网桥id (优先级+MAC地址) 越小越优先
默认优先级:32768
修改优先级的时候要改成4096的倍数
[系统]stp mode stp 修改stp的模式
Stp priority 4096 修改优先级
2)根端口—在每台非根网桥上,有且仅有一个接口;本地离根网桥最近的接口(最短、星型),接收来自根网桥的BPDU,转发用户的流量(该接口不阻塞)
选举:
1 路径开销值:比较从根网桥发出后,通过该接口进入时最小的cost值;
2 对端网桥id:入向cost值相同,比较该接口对端设备的BID,小优
3 对端端口id:对端BID也相同,比较该接口对端设备的接口的PID
4 本端端口id(hub):小优
端口ID 接口优先级(0-240,步长16,默认128)接口编号
3)指定端口—在每一段存在STP的物理链路上,有且仅有一个;转发来自根网桥的BPDU,同时可以转发用户流量(不阻塞);默认根网桥上所有接口为指定端口;
选举:
1 路径开销:比较从根网桥发出后,通过该接口进入这段链路时的cost值最小(出向)
2 本端网桥id
项目中创建 html 样式的时候,运用到了 v-for="item in listData" 但抛出了如下异常:
Elements in iteration expect to have 'v-bind:key' directives.(vue/require-v-for-key) 解决办法 使用 v-for 的同时需要添加绑定,即 v-bind:key="xxx" 即可。
v-for="item in listData" v-bind:key="item" 注:v-bind:key="item" 中 item 若为对象,则需绑定其具体一个属性,例如 v-bind:key="item.id"
以上便是此次分享的全部内容,希望能对大家有所帮助!
----------乐于分享---------
2020--5-22 10:28
链接: https://pan.baidu.com/s/1gViC-iYNrSME-rXQxmEa7A 提取码: bkqs
2020-05-13 14:59
本来是不想过要整理这些资源,毕竟都可以在官网上免费下载。但自从家里换了移动的宽带,很多网站访问不了导致软件无法下载,索性在百度网盘上做个备份,也顺带分享给需要的人。
一:通过oracle官网下载jdk:
https://www.oracle.com/java/technologies/oracle-java-archive-downloads.html
二:通过百度网盘下载jdk
链接: https://pan.baidu.com/s/1sFtbEWudSIdyOCJds-J2TA
提取码: 8e2h
资源列表:
jdk-7u80-windows-x64.exe
jdk-8u202-windows-x64.exe
jdk-8u241-windows-x64.exe
jdk-9.0.4_windows-x64_bin.exe
jdk-10.0.2_windows-x64_bin.exe
jdk-11.0.6_windows-x64_bin.zip
jdk-12.0.2_windows-x64_bin.zip
jdk-13.0.2_windows-x64_bin.zip
jdk-14_windows-x64_bin.zip
一:通过eclipse官网下载eclipse:
https://www.eclipse.org/downloads/packages/
二:通过百度网盘下载eclipse
链接: https://pan.baidu.com/s/1fm_qQBfRaxxSw8zK0LpxoQ
提取码: c639
资源列表:
eclipse-jee-neon-3-win32-x86_64.zip
eclipse-jee-oxygen-3a-win32-x86_64.zip
eclipse-jee-photon-R-win32-x86_64.zip
eclipse-jee-2018-12-R-win32-x86_64.zip
eclipse-jee-2019-03-R-win32-x86_64.zip
eclipse-jee-2019-06-R-win32-x86_64.zip
eclipse-jee-2019-09-R-win32-x86_64.zip
eclipse-jee-2019-12-R-win32-x86_64.zip
eclipse-jee-2020-03-R-incubation-win32-x86_64.zip
如链接失效或有其他需求,请留言。
本文适用于当前面临java.lang.ClassNotFoundException挑战的Java初学者。 它将为您提供此常见Java异常的概述,这是一个示例Java程序,可支持您的学习过程和解决策略。 如果您对与更高级的类加载器相关的问题感兴趣,我建议您复习有关java.lang.NoClassDefFoundError的文章系列,因为这些Java异常密切相关。 java.lang.ClassNotFoundException:概述 根据Oracle文档,在类加载调用失败后,将使用其字符串名称引发ClassNotFoundException ,如下所示: Class.forName方法 ClassLoader.findSystemClass方法 ClassLoader.loadClass方法 换句话说,这意味着一个特定的Java类找不到或无法从您的应用程序当前上下文类加载器“运行”加载。 对于Java初学者来说,这个问题可能特别令人困惑。 这就是为什么我始终建议Java开发人员学习和完善他们在Java类加载器方面的知识的原因。 除非您参与动态类加载和使用Java Reflection API,否则您遇到的ClassNotFoundException错误不是来自应用程序代码,而是来自引用API。 另一个常见的问题模式是错误包装您的应用程序代码。 我们将在本文结尾处回到解决策略。 java.lang。 ClassNotFoundException :示例Java程序 现在在下面找到一个非常简单的Java程序,该程序通过Class.forName()和ClassLoader.loadClass()模拟两种最常见的ClassNotFoundException方案。 请简单地复制/粘贴并使用您选择的IDE运行该程序( 此示例使用Eclipse IDE )。 Java程序允许您根据以下情况在问题场景1或问题场景2之间进行选择。 根据您要研究的场景,只需更改为1或2。 #Class.forName() private static final int PROBLEM_SCENARIO = 1; #ClassLoader.loadClass() private static final int PROBLEM_SCENARIO = 2; #ClassNotFoundExceptionSimulator package org.ph.javaee.training5; /** * ClassNotFoundExceptionSimulator * @author Pierre-Hugues Charbonneau * */ public class ClassNotFoundExceptionSimulator { private static final String CLASS_TO_LOAD = "org.ph.javaee.training5.ClassA"; private static final int PROBLEM_SCENARIO = 1; /** * @param args */ public static void main(String[] args) { System.
前言 前几天收到已被录取的消息,心中万分感慨。在脑中预演了无数遍的场景,最终变成现实的感觉,真好。这几天向我询问考研方向和思路的师弟师妹挺多,但是我并不觉得现在这个时间点是开始备考的好时机,已经五月中旬了,是有点晚了。但是由于今年疫情原因,很多21考研党前期看的经验帖应该是前几年的,20考研人五月份才可能结束复试、分享一些经验。很有幸作为最早一批结束复试的20考研人,我想趁热打铁,把我一年来考研的心路历程与大家说一说,希望其中可以给大家借鉴一二。
我的概况 首先,我决定考研的想法是在2019年1月份,当时在找工作和考研两条路上做过挣扎,后来坚定地选择继续深造读研。原因有几个,对自己的认知——我觉得自己的知识水平和专业技能水平还不够高,出去找工作可能没有多大的竞争力,我是某211的软件工程专业,按理来说软件行业正是一个蓬勃发展的行业,工作机会遍地开花,找一份心仪的工作其实并不会特别难。但是如果预见了五年、十年后、我的优势是否还在?还是说我只是比别人多了几年的经验,仅此而已了吗?我不想太快碰到我的职业天花板。这是其一。其二,我想发掘我的潜力,肯定我的能力,既然说考研不亚于第二次高考,那么我想试试我行不行,现在摆在我眼前的就是:去做,你有可能成功,不做,永远也不知道你能不能成功。我是一个喜欢挑战的人,我当然选择——Just do it。其三,我喜欢把学习的成就当成生活的成就,我喜欢探索更新的事物,我想去我没有涉足的远方,接触更多让我敬佩的牛人,我想让自己的人生,再添上亮丽的一笔。所以,我必须去争取。
确定好自己为何考研,这是十分重要的事情,我不惜笔墨写了那么多条我想读研的理由正是如此,否则,心中没有任何希望和信仰,容易半途而废。
接下来谈一下我的概况,本人是广东某211软件工程专业的,英语基础尚可,四六级都过了(但是六级考了两次才过),数学基础不好,因为高中我的数学不是特别好。成绩在班里是中等水平,没有太多牛逼的奖项和发过牛逼的论文,小奖有三两个,专业课基础很普通,所以考数二+英二+408我鼓起了很大勇气。主要还是408的难度早就让人有所耳闻,在备考过程中也切身体会到了其中的难度,如果我是跨考我绝对学不下去408,真心话,很佩服跨考还能学下408的牛人。408的课程都是本科学过的,可是在备考过程就觉得以前学的程度远远不够。
我在1月份搜集了许多院校的信息并确定了考研的目标院校以及看过许许多多的经验贴。我深知,很多经验贴真的不能完全照搬照抄,我们需要吸取里面符合自身特点的方法,选择性地借鉴。也包括我这一篇经验帖,你可以选择你觉得适合你的方法,去尝试和实践。我是在2月份准备好了所有的考研资料,2月25日正式投入考研的复习,接下来我会按数学、英语、专业课、政治这个顺序来详细谈一谈我的计划和安排,以及用到的学习技巧。
数学 数学可以说是我花的时间最多的科目,也是最能拉分的科目,但是同时也是我的弱势科目,这次考试我数二只考了100分,虽然我估分只有85+……比预计的高,但是总的来说是一个比较低的分数,数学复习经验仅供参考。我使用的教材是张宇18讲和李永乐的线性代数讲义,配套练习是汤家凤的1800和李永乐的660, 模拟题是李林的4+6套模拟题,加上历年真题还有几套合工大共创卷超越卷的选填题。除此之外没有其他练习题。
我没有看高数课本,直接怼张宇18讲,说真的这个效率可能不太高,因为高数的基础很多都忘了,直接看张宇18讲很吃力,每一道习题都不太会,都要认真研究答案解析,每一步都搞明白,做标注。前期我只能一早上看两三页书,进度很慢,看完极限,后来发现了张宇的基础课程,我先把他的基础课看完了,课程里面会讲一些基础题,我把基础题也过了一遍,并做了一些笔记。后来基本上是先看课程,做笔记,再看18讲,然后做里面的练习。我在6月份基本结束高数的复习,每天数学6-7小时,说真的18讲里面的课后题我做的也很吃力,很多都是错的,很打击信心。
然后差不多是6月底开始做汤家凤的1800的基础部分,怎么说呢,虽然说汤家凤的1800已经是很基础的练习册了,我刚开始做的时候真的很奔溃,错很多,正确率基本在50%。不过我第一次错的题目,我会用红笔标记,并用绿笔在旁边写上错误的原因,是计算错误还是看错还是无思路。最后统计我这一小结总的正确率。然后花了一个多星期把基础篇的错题再刷了一遍,第二次错误用蓝色笔标记,然后再花了三四天把二次错误的题再刷一遍,第三次错误的题用星号标记。错了三次以上的题记录到错题本,反复复习。我当时的目标是8月份结束提高题的,当时我8月份花了一个多星期刷汤家凤的提高课程,然后再做提高部分的题,其实时间不太够。从八月份开始我的高数学习时间就从每天6h,降为每天3h。然后9月中旬才差不多把提高题刷了一遍,后来想到要巩固基础,就把提高题又刷了一遍,还有基础部分的第三次错题又刷了一遍。9月份结束。至此高数基础巩固就完成了。(提高阶段安利一下汤家凤的中值定理和物理应用的讲解!)
线性代数我基础特别不好,我是7月份的时候把李永乐的线代基础课听了一遍,做了数学笔记,这个是基础课相当于大学上课那样的,这个基础课因为没有太多时间,我需要兼顾高数和专业课,所以只能一天抽1小时学。8月份的时候把李永乐的线代讲义的课程听了一遍,并做了笔记,他这个课程是有配套讲义的,复习就按讲义来复习,一般课程里面会有很多练习题,我一般会暂停下来自己写答案,思考一下,再看他的讲解。这个讲义课是考研课,跟前面的基础课不太一样,主要还是分析考研命题趋势的,因为我线代基础不好,直接听考研的线代课有点跟不上。然后这个讲义后面又配套的习题。(需不需要看基础课因人而异,之前我咨询我的学长,他半个月就搞定了线性代数,而我不行)后来9月份我单独把线代讲义从头到尾刷了一遍,例题课后题,都独立做一做,做不出来标记一下,哪里不太明白再去看一遍课程。因为我制定的计划是10分月要做真题了,但是线代讲义只刷了一遍,里面还有许多不会的题,所以10月份我抽了时间把讲义再刷了一遍。并做李永乐660的线代部分的习题和汤家凤1800线代部分的习题。
10月份开始每天做一套真题,第二天修改和总结错题。我为了让自己更看重每天的模拟,所以在网上买了数学答题卡,这样比较正式一点。我买了汤家凤的真题解析,他有2000前的真题册和2000-2019的真题卷,我没有做2000年前的,从2000年开始做起,一开始模拟还是挺崩溃的,分数很低,很沮丧。不过没关系,一开始是不太适应的。很多人说数学需要总结,具体怎么总结我也摸索了很久,后来我找到了总结的方法!我准备了一本专门记录真题错题的本子(NoteBook A4)记录是几几年的卷子,考了多少分,接下来划分几个模块,标志第几题错了,这题考察的知识点是什么,左边模块写错误原因,右边模块写正确的过程。重要的过程或者出错的步骤用红笔标注。总结模块写这个知识点涉及到的公式以及总结反思如何避免这个错误。大概花了一个月,把2000-2015年近15年的真题认认真真刷了一遍。接下来就是11月了,我又花了一个星期把真题的错题又刷了一遍。把真题错题第二次错的在错题本上标记,再看几遍,第二天做前一天错的题。然后就开始刷李林的4+6预测题,也是一天一卷,第二天分析。类似真题那样的总结方法,10套题,也是在11月份结束了。期间我每天做1~2道真题错题,然后做完再去吃午饭。不算上对的题目,真题刷了应该有6~7遍。
12月份的时候知道自己的弱点在哪里,然后就查漏补缺,当时我记得我的多元微分还有物理应用不太好,所以我把1800和660的多元微分和物理应用的基础和提高刷了一遍,把18讲的多元微分和物理应用也看了一遍。然后就把留着的几年真题做了,2016-2019。我后期做历年真题主要是想模拟自己的水平,但是我发现这样就没有太多时间去研究近五年的真题,所以我建议真题只留近两年就行了,留到12月份做,并严格按照考研的时间安排模拟,再以前的年份建议在十月份就要刷完!
后期做题速度会快一点,12月份有二十多天,我就想回归基础,所以把张宇18讲的课后题再刷了一遍。然后把真题按模块再刷了一遍。真题按模块刷就是比如我今天要巩固极限基础,我就把每张卷子涉及极限的题重新做一遍,从2000-2019。最后10天,我做了合工大的超越卷和共创卷,但是来不及全做完,只能挑选填题做,还有自己不太熟悉的线代大题做。最后留了3-4天复习之前总结的错题,我很后悔这最后几天没有继续做题保持手感,而是看笔记。我想警示师弟师妹,数学一定要做题,每天1h都好,到最后一刻都要保持手感。我就是犯了这个错误,以为看错题和做题差不多,导致考试的时候做题手感很差。我做的模拟卷完整的只有李林的4+6套,今年又命中了一题……可惜我好像没有算对……不过不要寄希望于押题,切记。
-----------------------------------------------------------5月13日 再更---------------------------------------------------
英语 可能一直以来我的英语基础还行,所以就算离高考那么久了,英语捡起来还是比较快。这次考研英语二我考了83分,算是比较满意的分数。不过我的阅读做的并不好,是作文救了我,英语阅读我错了4个还是5个,然后完型填空错了2个,翻译今年比较简单,接着就是作文,按道理来说阅读错4-5个,冲80分比较难,但是冲到了,应该是我背了几个月的作文拉了我一把。
首先说背单词,英语我前期是买了张伟的恋恋有词,看了一个星期左右他的单词视频吧,怎么说,对我来说,看他的视频就是浪费时间 = =!。恋恋有词我是过了两遍,但是只看了他每章的总词汇那部分= =……感觉这本书对我来说用处不大,就是背单词完事。大概用了一个月背完了他的恋恋有词。然后我就开始用百词斩、扇贝英语、墨墨记单词,用了那么多种背单词软件,我觉得墨墨背单词最好。它会按照你的记忆曲线给你复习单词,每天记忆量可能不会特别多,但是如果单词超过上限需要开会员……额= =。记单词在整个英语的学习中是必须每天坚持的事情,比如做阅读,我也会记单词。下面会详细讲到。
然后是开始做阅读,我在3月份的时候把唐迟的阅读逻辑看了一遍,记了一下有用的笔记,但是怎么说呢。用处不大。【这本书有一个配套视频的,叫做唐迟阅读罗汉班,但是我前期没有发现,是8月份的时候发现的,这个阅读班大概花三天(一天2h)可以看完,强力推荐!看完之后我的阅读正确率确实提高了不少。】我4-5月主要是做精翻,就是把英语一2010-2016的卷子每一篇阅读都翻译出来,一般我是晚上学英语,先做一篇阅读,然后翻译,一开始特别慢,一篇阅读需要花25分钟,翻译一篇文章要2h……有时候一天翻译不完,然后第二天还要把着自己的翻译去对照正确的翻译,逐句修改,挑出翻译严重错误的句子,进行摘抄,写上中文,分解句子成分,标记不认识的单词。所以做精翻特别费时间,一篇文章可能需要研究2-3天。但是!后期翻译多了,速度会快很多,到5月份,翻译一篇文章只需要1h。这个方法是我在b站参考一位英语高分博主的,我觉得很有效。但是如果时间不充足的情况下还是慎重考虑此方法。
ps:6月份我在忙期末考试和大作业,耽搁了许多考研任务。数学、英语、专业课在6月份几乎排不上,顶多每天记一下单词。
到了7-8月份,就是做英语二真题(只推荐张剑的黄皮书),因为英一比较难嘛,所以我想英一搞定了英二做起来会简单得多,事实确实如此。英二比英一简单轻松,所以7-8月份做英语真题,也是做一篇阅读,逐句默念口译,第二天看黄皮书的解析和翻译,用笔记本记录下自己觉得比较难理解的句子和自己完全翻译错的句子,还有记录自己不认识的单词、短语。英语在3-8月份每天安排2h,从9月份开始,降为1.5h,10月份1h,11月份0.5h,不过这个时间安排因人而异,我觉得后期我的英语基础打扎实了,408花时间,所以英语舍弃了许多时间。哦,对了,研究真题的笔记要每天抽15-30分钟朗读,还有真题,到11-12月份我每天会朗读3-4篇阅读,并在脑子想它的意思。
关于作文,我是从9月份开始接触作文并开始背诵的,因为英语进度比较快,我用的是王江涛的考研作文,虽然网上很多人diss这本书,但是我觉得你会利用,并灵活修改,可以很有用,这次就是我的作文发挥得特别好就是离不开这个。9月份背作文是比较早的,但是如果你想英语高分,这时候开始最好。我先背了书信篇的好像是三星级的,一天背一篇,背完马上默写。我背英语比较喜欢大声朗读,不喜欢默背,我觉得大声背书才能有助于记忆(所以我一般选吃完晚饭6:00-6:30这个时间会宿舍背书),一般背一篇书信小作文是花10-12分钟(对,没错,就是有倒计时!!强迫自己10分钟背下来)然后背了半个月吧,就开始背大作文,大作文花时间多一点,要背20-30分钟。默写也是25分钟左右。基本9-10月份没怎么做阅读,都是背作文和背单词和朗读笔记、真题。
10月份中旬,发现,额……自己背了很多英语一的作文= =!!实际上英语一的大作文和英语二的大作文风格很不一样!!感觉白白背了那么多英一的大作文= =。不过英一作文造句丰富点吧,作为借鉴了。10月份中旬左右开始背英二的大作文了……这……大家引以为戒。
11月份,就是自己手写作文了,这个时候其实很慌,因为前期背了那么多作文,能不能化为自己的表达,其实很关键。我把英二历年的真题大小作文都写了一遍,一般是一天一篇。写完之后对着参考答案,借鉴它比较好的表达,总结一些句型和短语,叮嘱自己下次有机会要用上。然后中间为了找回做阅读的手感,也隔几天做一些阅读。还有完型填空,我觉得难度不大,靠语感做下来每次都能8分左右。完型因人而异,有些人觉得很难……这个我没有别的技巧,就是靠语感。
12月份,主要是再做一下真题和写作文,每天写一篇作文和复习自己做的笔记,和精翻时候的笔记。把作文进行分类,总结不同类别的文章惯用的表达短语,把一些常见的表达方式进行美化,上网找了许多替换表达,总结了几套属于自己的作文模板。最后一个星期模拟考了一次,时间控制在3h内,时间并不十分充足,刚刚好。
英语我想强调:重视真题,每天背单词,每一天都要背!我一般是一天背50个,是睡前背的。额,因为我复习期间不带手机,会分心,所以用墨墨背单词只能回到宿舍再背。还有重视作文!不要以为作文不重要可以速成,很多人因为作文被拉开10分都是常见的。
--------------------------------------5月15日 再更--------------------------------------
408 408就是计算机基础综合的代码,考计算机专业的四门核心课程:数据结构,操作系统,计算机组成原理,计算机网络。考408的好处就是不需要像自命题的卷子一样买几百块的历年回忆版真题,这是全国统考的卷子,历年真题都是可以轻松买到的。408的命题难度普遍比自命题难(当然除了清北和个别学校比较难的自命题卷子)而且考试的范围广,考查较为细致,复习起来还是比较辛苦的。许多跨考都不太敢考408也是有这方面的原因。
我自身在这四门课的基础很一般,所以我也比较早准备了408的复习。前期3-5月主要复习数学和英语,所以我每天晚上是花1小时学数据结构,看了一遍浙大刘姥姥的DS课程,帮我回忆起一些基础,大概花了一个月……然后接着就是看王道书,做练习,不太明白的看一下教材(严魏敏的C语言版的数据结构),因为每天只花1小时,所以数据结构进度是比较慢的,我基本上是5月份才结束数据结构的复习。(这里安利一下b站青岛大学王卓老师讲的排序算法,很清晰明了) 到了7月我把数据结构的算法题刷了一遍,就是我开始复习的时候大题的算法题是跳过没做的,因为我自己算法不是特别好。8月份开始二刷,做数据结构思维导图,这里强烈建议自己做一下思维导图!我用的是xmind,基本上是自己精读一下章节的内容,然后把握重点进行用自己的话进行概括。思维导图在后期复习起来很快,也方便联想记忆。
计组是在5月份开始每天花半小时到一小时看哈工大的刘宏伟老师的课(并配套看了刘朔飞老师的计组教材,不过没看完,看了不到一半),主要是想打打基础,但是没有看完,一共125集,我看到90集就没时间看了,已经快进入暑假了。然后7月份开始看王道书,发现直接看王道书有点难受,所以在b站也找了配套的王道计组小姐姐的视频讲解,我觉得讲得超级好!!真的超级好!强烈推荐!(有人说她声音不好听之类的简直是抬杠)强烈建议看一节视频再看一节书(我觉得可以不用看刘老师的视频直接看王道的,效率高点)7月份开始每天花3h~4h看计组,但是计组十分难啃,我计划是7月份就完成任务的,结果到了8月10号左右才结束。期间为了巩固我的基础,我一般是第二天做前一天做错的题。
ps:期间回家休息了4天,毕竟半年多没回家了,学校也空荡荡,怪难受的,就回了几天,但是回家几天也坚持把计组的一些尾巴搞完了= =,要不然10号都搞不完。
操作系统的就在8月10日-8月25日复习,也是每天3h,跟着王道视频然后认真研读王道书和做课后题,也是第二天做前一天的错题。计网就是8月25日-9月15日,因为后期感觉进度有点慢了,调整了一下时间(当然是英语时间--),分多时间给408,所以计网是火速看完视频和刷了一遍王道。我的计划是10月份前要做完四科的思维导图的,所以8-9月每天晚上抽1-1.5h做数据结构、计组、操作系统、计网的思维导图。做导图是作用实际上也把书精读了一遍,所以10月份前,王道单科书是过了两遍的。在此期间,还把之前标记做错的题又做了一遍。就是一刷的时候做课后题,写abcd不要写那么大那么明显,然后对了答案之后错了就打个标记,二刷的时候用书边折一下把答案遮住,直接重做出错的选择题。
10月份开始是要做真题的,不管是数学还是408,这个目标是不会变的。我买了王道的真题册,从2009到2017我都刷了一遍,一般是一年真题需要研究三天,一天花3h左右,先用计时器进行计时⏲(我觉得做卷子还是要掐时间,所以我在某宝买了一个计时器)然后改卷子,估分。第二天研究每一道选择题,不管对的错的都要看一下解析,因为没准你是蒙对的呢= =,总结错题的方法也跟数学类似,准备一本错题本(NoteBook A4)记录年份,分数,第几题,考察知识点,左边模块写错误原因,右边写正确思路或解答,总结模块写涉及的公式和如何避免错误。第三天研究大题,每一题的答案都要仔细搞懂,自己出错的地方一定要弄明白,不懂多百度一下或者是找到原教材翻一下。基本上10月份把真题刷了一遍(留了18,19年的真题)
11月份开始做王道的八套模拟题,也当真题那样模拟,总结方法类似,模拟题我只做了一遍,我觉得没有必要做很多次,把知识盲区揪出来就好了。因为11月份英语时间减少了,时间稍微花多了一点给408,所以差不多半个月就做完了八套卷。还有半个月我把思维导图过了一遍,把王道上的错题又重新做了一遍,还把历年真题的错题重新做了一遍,后期做题速度会快一点。
12月份我开始二刷真题了,就是把我得分低的卷子,重新做一次,再改分,又错的题再总结。几乎是是一天一卷了,花了10天左右,把2017-2007的卷子都刷了一遍,再往前的卷子就没有做了。只是过了一下错题。然后留了一些时间进行模拟考,模拟了18,19年的卷子,考得也不太理想,不过也没时间伤心了。总结完18、19年的卷子,考试前几天又过了一遍思维导图,一天一科,然后记忆了一下总结笔记和计网的一些需要记忆的知识点,就去考试了。
总结:数据结构 3遍 计组 3遍 操作系统 2遍 计网 2遍 重点章节遍数 + 2~4 遍 408 想要拿高分的秘诀就是 :全面 多次 反复
TensorFlow 是由 Google Brain 团队为深度神经网络(DNN)开发的功能强大的开源软件库,其允许将深度神经网络的计算部署到任意数量的 CPU 或 GPU 的服务器、PC 或移动设备上,且只利用一个 TensorFlow API。包括 TensorFlow 在内的大多数深度学习库能够自动求导、开源、支持多种 CPU/GPU、拥有预训练模型,并支持常用的NN架构,如递归神经网络(RNN)、卷积神经网络(CNN)和深度置信网络(DBN)。TensorFlow 则还有更多的特点,如下:
支持所有流行语言,如 Python、C++、Java、R和Go。可以在多种平台上工作,甚至是移动平台和分布式平台。它受到所有云服务(AWS、Google和Azure)的支持。Keras——高级神经网络 API,已经与 TensorFlow 整合。与 Torch/Theano 比较,TensorFlow 拥有更好的计算图表可视化。允许模型部署到工业生产中,并且容易使用。有非常好的社区支持。TensorFlow 在后端使用 C/C++,这使得计算速度更快TensorFlow 不仅仅是一个软件库,它是一套包括 TensorFlow,TensorBoard 和 TensorServing 的软件。 GPU 和 TensorFlow 等工具,可以通过几行代码轻松访问 GPU 并构建复杂的神经网络,而不需要深入复杂的数学细节,大数据集的可用性为 DNN 提供了必要的数据来源。
一.TensorFlow程序结构 通过将程序分为两个独立的部分,构建任何拟创建神经网络的蓝图,包括计算图的定义及其执行。图定义和执行的分开设计让 TensorFlow 能够多平台工作以及并行执行,TensorFlow 也因此更加强大。
计算图:是包含节点和边的网络。本节定义所有要使用的数据,也就是张量(tensor)对象(常量、变量和占位符),同时定义要执行的所有计算,即运算操作对象(Operation Object,简称 OP)
计算图的执行:使用会话对象来实现计算图的执行。会话对象封装了评估张量和操作对象的环境。这里真正实现了运算操作并将信息从网络的一层传递到另外一层。不同张量对象的值仅在会话对象中被初始化、访问和保存。在此之前张量对象只被抽象定义,在会话中才被赋予实际的意义。请记住,每个会话都需要使用 close() 来明确关闭,而 with 格式可以在运行结束时隐式关闭会话。
举例:需要使用 tf.Session() 定义一个会话对象 sess。然后使用 Session 类中定义的 run 方法运行它run(fetches,feed_dict=None,options=None,run_metadata)运算结果的值在 fetches 中提取
养成显式定义所有张量和操作对象的习惯,不仅可使代码更具可读性,还可以帮助你以更清晰的方式可视化计算图
v_1=tf.constant([1,2,3,4]) v_2=tf.constant([2,1,5,3]) v_add=tf.add(v_1,v_2) //Session提供了Operation执行和Tensor求值的环境: with tf.Session() as sess: print(sess.
text()方法可以获取单个元素的链接文本
如果想要列表里的全部元素的链接文本,可以使用get_attribute()方法
使用方法:
list = dr.find_elements_by_xpath("//*[@id='user-table']//tbody/tr[1]//ul/li/a") for i in list: print(i.get_attribute("textContent").strip()) get_attribute()还有get_attribute("innerHTML") 和get_attribute("outerHTML")方法
实践得出,get_attribute("textContent")和get_attribute("innerHTML")可获得链接文本
get_attribute("outerHTML")可获得a链接全部信息,如下图标出的 <a href="#modal" data-toggle="modal" data-url="/admin/user/2964/avatar">修改用户头像</a>
另外,对 a 标签中的每个属性进行 get_attribute 操作获取,如
element.get_attribute("class")
element.get_attribute("href")
elemnet.get_attribute("date-url")
原文:https://www.runoob.com/w3cnote/python-func-decorators.html
https://foofish.net/python-decorator.html
侵删
讲 Python 装饰器前,我想先举个例子,虽有点污,但跟装饰器这个话题很贴切。
每个人都有的内裤主要功能是用来遮羞,但是到了冬天它没法为我们防风御寒,咋办?我们想到的一个办法就是把内裤改造一下,让它变得更厚更长,这样一来,它不仅有遮羞功能,还能提供保暖,不过有个问题,这个内裤被我们改造成了长裤后,虽然还有遮羞功能,但本质上它不再是一条真正的内裤了。于是聪明的人们发明长裤,在不影响内裤的前提下,直接把长裤套在了内裤外面,这样内裤还是内裤,有了长裤后宝宝再也不冷了。装饰器就像我们这里说的长裤,在不影响内裤作用的前提下,给我们的身子提供了保暖的功效。
谈装饰器前,还要先要明白一件事,Python 中的函数和 Java、C++不太一样,Python 中的函数可以像普通变量一样当做参数传递给另外一个函数,例如:
def foo(): print("foo") def bar(func): func() bar(foo) 正式回到我们的主题。装饰器本质上是一个 Python 函数或类,它可以让其他函数或类在不需要做任何代码修改的前提下增加额外功能,装饰器的返回值也是一个函数/类对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景,装饰器是解决这类问题的绝佳设计。有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码到装饰器中并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
先来看一个简单例子,虽然实际代码可能比这复杂很多:
def foo(): print('i am foo') 现在有一个新的需求,希望可以记录下函数的执行日志,于是在代码中添加日志代码:
def foo(): print('i am foo') logging.info("foo is running") 如果函数 bar()、bar2() 也有类似的需求,怎么做?再写一个 logging 在 bar 函数里?这样就造成大量雷同的代码,为了减少重复写代码,我们可以这样做,重新定义一个新的函数:专门处理日志 ,日志处理完之后再执行真正的业务代码
def use_logging(func): logging.warn("%s is running" % func.__name__) func() def foo(): print('i am foo') use_logging(foo) 这样做逻辑上是没问题的,功能是实现了,但是我们调用的时候不再是调用真正的业务逻辑 foo 函数,而是换成了 use_logging 函数,这就破坏了原有的代码结构, 现在我们不得不每次都要把原来的那个 foo 函数作为参数传递给 use_logging 函数,那么有没有更好的方式的呢?当然有,答案就是装饰器。
简单装饰器
把如图所示的用户权限分配中的【拒绝通过远程桌面服务登录】里面的用户删掉。
我们在 VS 中创建 Win32 控制台应用程序,vs 会为解决方案创建默认地创建 4 个 filters(资源管理器中没有对应的目录和文件夹):
头文件:一般为 .h 文件外部依赖项源文件:一般为 .cpp文件资源文件 1. 外部依赖项 & 资源文件 外部依赖项:C++ 外部依赖项有很多,大部分都是静态库文件,编译的时候会递归关联起来生成可执行文件,所以可执行文件才会大很多。
编译的时候: 外部依赖项都是一个填充地址 , 比如 你的代码里调用 外部依赖函数地址 Extern_funA 。
预编译的时候展开头文件,编译生成obj文件的时候,Extern_funA 就是一个填充地址 比如 0x00 00 00 00链接的时候基地址重定位生成对应的 Extern_funA 地址。 链接的时候会根据你的工程配置想一个去查找 DLL 导出符号表,发现没有找到 Extern_funA 。那么就会出错,说无法定位外部符号。 右键【源文件】,选择【添加 ⇒ 新建项】,比如此时我们创建,test.cpp 文件,只需 include 一个文件:
#include <iostream> 123 123 此时重新点开 【外部依赖项】filter,便会看到引入了相当多的库文件。
资源文件:主要是你用到的一些程序代码以外的东西,比如图片之类,或者菜单、工具栏之类的。
2. 库目录 & 附加依赖项 库目录只是查找目录,类似环境变量 PATH;具体用哪一个需要指明的,如果不在附加依赖项里填上,就需要在代码里用
#pragma comment(lib, “xxx.lib”) 1 1 来手动指定了。你写代码读写一个文件需要写明文件名吧,这个文件名就相当于那个lib , 但读写这个文件可以不写全路径,就是因为有工作目录(working directory)的存在。
深度学习自学记录(6)——归一化和BatchNormal的理解 1、标准化与归一化1.1归一化的目的和优势1.2常用的数据标准化方法 2、BatchNormal2.1BN算法强大之处2.2BN算法诞生的背景与目的2.3BN算法思路2.4BN算法实战2.5Keras中的Batch Normalization 3、总结4、参考 1、标准化与归一化 数据的标准化(normalization)是将数据按比例缩放,使之落入一个小的特定区间,或有特定的数据分布。在某些比较和评价的指标处理中经常会用到,去除数据的单位限制,将其转化为无量纲的纯数值,便于不同单位或量级的指标能够进行比较和加权。标准化不会改变数据分布。
其中最典型的数据标准化处理就是数据的归一化,即将数据统一映射到[0,1]区间上。
1.1归一化的目的和优势 目的:
1、把数变为(0,1)之间的小数。主要是为了数据处理方便提出来的,把数据映射到0~1范围之内处理,更加便捷快速
2、把有量纲表达式变为无量纲表达式。 归一化是一种简化计算的方式,即将有量纲的表达式,经过变换,化为无量纲的表达式,成为纯量,便于不同单位或量级的指标能够进行比较和加权
总得来说:归一化的目的就是使得预处理的数据被限定在一定的范围内(比如[0,1]或者[-1,1]),从而消除奇异样本数据导致的不良影响
优势:
1、提升模型的收敛速度
2、提升模型的精度;在涉及到一些距离计算的算法时效果显著,可以让各个特征对结果做出的贡献相同。从经验上说,归一化是让各指标值都处于同一个数量级别上,在数值上有一定比较性,可以大大提高分类器的准确性。
3.、深度学习中数据归一化可以防止模型梯度爆炸。
1.2常用的数据标准化方法 最常用的是 min-max标准化 和 z-score 标准化:
min-max标准化:
数据的归一化,即将数据统一映射到[0,1]区间上。
z-score 标准化:
最常见的标准化方法就是Z标准化,也叫标准差标准化,这种方法给予原始数据的均值(mean)和标准差(standard deviation)进行数据的标准化。经过处理的数据符合标准正态分布,即均值为0,标准差为1。也可以说把数据归一化至:均值0、方差为1的数据分布。
转换函数为:
x* = (x - μ ) / σ
其中μ为所有样本数据的均值,σ为所有样本数据的标准差。
这两种最常用方法使用场景:
1、在分类、聚类算法中,需要使用距离来度量相似性的时候、或者使用PCA技术进行降维的时候,第二种方法(Z-score standardization)表现更好。
2、在不涉及距离度量、协方差计算、数据不符合正太分布的时候,可以使用第一种方法或其他归一化方法。比如图像处理中,将RGB图像转换为灰度图像后将其值限定在[0 255]的范围。
2、BatchNormal 2.1BN算法强大之处 (1)你可以选择比较大的初始学习率,让你的训练速度飙涨。以前还需要慢慢调整学习率,甚至在网络训练到一半的时候,还需要想着学习率进一步调小的比例选择多少比较合适,现在我们可以采用初始很大的学习率,然后学习率的衰减速度也很大,因为这个算法收敛很快。当然这个算法即使你选择了较小的学习率,也比以前的收敛速度快,因为它具有快速训练收敛的特性;
(2)你再也不用去理会过拟合中drop out、L2正则项参数的选择问题,采用BN算法后,你可以移除这两项了参数,或者可以选择更小的L2正则约束参数了,因为BN具有提高网络泛化能力的特性;
(3)再也不需要使用使用局部响应归一化层了(局部响应归一化是Alexnet网络用到的方法,搞视觉的估计比较熟悉),因为BN本身就是一个归一化网络层;
(4)可以把训练数据彻底打乱(防止每批训练的时候,某一个样本都经常被挑选到,文献说这个可以提高1%的精度,这句话我也是百思不得其解啊)。
2.2BN算法诞生的背景与目的 神经网络学习过程本质就是为了学习数据分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低;另外一方面,一旦每批训练数据的分布各不相同(batch 梯度下降),那么网络就要在每次迭代都去学习适应不同的分布,这样将会大大降低网络的训练速度,这也正是为什么我们需要对数据都要做一个归一化预处理的原因。
对于深度网络的训练是一个复杂的过程,只要网络的前面几层发生微小的改变,那么后面几层就会被累积放大下去。网络一旦train起来,那么参数就要发生更新,除了输入层的数据外(因为输入层数据,我们已经人为的为每个样本归一化,具有同样的数据分布),后面网络每一层的输入数据分布是一直在发生变化的,因为在训练的时候,前面层训练参数的更新将导致后面层输入数据分布的变化。就是要解决在训练过程中,中间层数据分布发生改变的情况,于是就有了Batch Normalization
2.3BN算法思路 为了防止因低层网络在训练的时候更新了参数,而引起后面层输入数据分布的变化;我们想到如果在每一层输入的时候,再加个预处理操作那该有多好啊,所以BN层的本质原理:在网络的每一层输入的时候,又插入了一个归一化层,也就是先做一个归一化处理,然后再进入网络的下一层。
用这个公式,对某一个层网络的输入数据做一个归一化处理。需要注意的是,我们训练过程中采用batch
随机梯度下降,上面的E(xk)指的是每一批训练数据神经元xk的平均值;然后分母就是每一批数据神经元xk激活度的一个标准差了。
但是有一个问题需要解决:如果是仅仅使用上面的归一化公式,对网络某一层A的输出数据做归一化,然后送入网络下一层B,这样是会影响到本层网络A所学习到的特征的,使得特征表达变弱
于是文献使出了一招惊天地泣鬼神的招式:变换重构,引入了可学习参数γ、β,对归一化后的数据x进行(线性变换)变换重构。根据训练数据的每一个batch数据求得均值u、标准差σ 以及γ、β
进一步深入理解参数γ、β的作用:
γ、β在训练过程中学习到对应的两个调节因子,对规范到均值为 0 ,方差为1 的值进行微调。因为经过第一步操作后,Normalization有可能降低神经网络的非线性表达能力,所以会以此方式来补偿 Normalization 操作后神经网络的表达能力。