简单地将文件夹下的所有图片名称写入txt文件 1.只需要导入os
2.只需要修改paths(储存图片的文件夹路径)和生成的txt文件名称
3.outpath是输出的名字,也可以根据需要来修改
import os paths = r'./images' # 储存图片的文件夹路径 f = open('images.txt', 'w') filenames = os.listdir(paths) # 读取图片名称 for filename in filenames: out = filename f.write(out + '\n') f.close()
作者:刘成彬,游族网络资深大数据开发
游族网络股份有限公司(SZ.002174)成立于 2009 年,总部位于上海,在德国、新加披、日本、韩国、印度等十余个国家设有分支机构。2014 年 6 月,游族网络正式登陆中国 A 股主板。
游族网络立足全球化游戏研发与发行,成功推出了《少年三国志》系列、《女神联盟》系列、《盗墓笔记》、《权力的游戏:凛冬将至》、《圣斗士星矢:觉醒》等多款知名游戏产品,在海外积累 1000 多个合作伙伴,发行范围遍及欧美、中东、亚洲及南美等 200 多个国家及地区,全球累计近 10 亿用户。
作为中国领先的互动娱乐供应商,通过与 StarRocks 的全面深入合作,游族网络依靠 StarRocks 丰富的数据导入方式和外表让数据查询更加高效,丰富的数据模型与高并发使数据建模、对外数据提供服务更加精准便捷。
#01 业务背景下,痛点重重 — 之前在计算实时指标时,我们运用过诸多组件:
Presto 和 ClickHouse 用于分钟/小时级调度的指标计算;
使用 Spark Streaming 或 Apache Flink(以下简称 Flink)直接从 Apache Kafka(以下简称 Kafka) 读取数据计算实时指标,结果数据写入 MySQL,报表系统直接读取 MySQL 数据作为展示;
Apache HBase(以下简称 HBase) 除了做计算交互,也会存储一些标签表,通过 DataAPI 的方式提供给其他系统使用,比如客服系统查询玩家标签这类场景;
Presto 直连 Apache Hive(以下简称 Hive);
ClickHouse。
这些组件各展所长,帮助我们解决了不少问题,但从目前来看,也存在不少痛点:
1. 维护多套组件,运维成本高;
2. 各组件 SQL 语法存在差异,开发维护任务成本高;
3. 在同指标数据下,需要保证不同组件计算的结果与口径都一致的成本比较高。
多维度的结果数据量大时,MySQL 的查询性能较差。为解决这些痛点,更好地适应公司实时查询需求,我们迫切需要统一 OLAP 引擎,且满足以下要求:
1. 数据秒级写入,低延迟毫秒级响应;
最近在训练模型,需要加载新的datasets时,同时需要修改相应的model config;
在加载data以后开始训练,在一个epoch中,每当迭代几个或者十几个interation后,就会出现nan数据,定位到是model中conv1d()和conv2d()传出的数据会为nan;
查找了很久很久,排除了data loader问题、torch版本问题、lr问题以后,最后发现,是bs设置过大导致的这问题;
在此记录。
【
给定一个数组 nums ,将其划分为两个连续子数组 left 和 right, 使得:
left 中的每个元素都小于或等于 right 中的每个元素。
left 和 right 都是非空的。
left 的长度要尽可能小。
在完成这样的分组后返回 left 的 长度 。
用例可以保证存在这样的划分方法。
示例 1:
输入:nums = [5,0,3,8,6]
输出:3
解释:left = [5,0,3],right = [8,6]
示例 2:
输入:nums = [1,1,1,0,6,12]
输出:4
解释:left = [1,1,1,0],right = [6,12]
提示:
2 <= nums.length <= 105
0 <= nums[i] <= 106
可以保证至少有一种方法能够按题目所描述的那样对 nums 进行划分。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/partition-array-into-disjoint-intervals
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
】
前缀和思想,一次从左边,一次从右边。
int partitionDisjoint(int* nums, int numsSize){ int idx = 0; int i; int lmax[numsSize - 1]; int rmin[numsSize - 1]; lmax[0] = nums[0]; rmin[numsSize - 2] = nums[numsSize - 1]; for (i = 1; i < numsSize - 1; i++) { // 从左边开始记录前缀中最大数 lmax[i] = fmax(lmax[i - 1], nums[i]); } for (i = numsSize - 3; i >= 0; i--) { // 从右边开始记录前缀中最小值 rmin[i] = fmin(rmin[i + 1], nums[i + 1]); } for (i = 0; i < numsSize - 1; i++) { if (lmax[i] <= rmin[i]) { // 当左边最大数小于最右边最小值即满足要求 return i + 1; } } return 0; }
【
给你一个长度为 n 的整数数组,每次操作将会使 n - 1 个元素增加 1 。返回让数组所有元素相等的最小操作次数。
示例 1:
输入:nums = [1,2,3]
输出:3
解释:
只需要3次操作(注意每次操作会增加两个元素的值):
[1,2,3] => [2,3,3] => [3,4,3] => [4,4,4]
示例 2:
输入:nums = [1,1,1]
输出:0
提示:
n == nums.length
1 <= nums.length <= 105
-109 <= nums[i] <= 109
答案保证符合 32-bit 整数
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimum-moves-to-equal-array-elements
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
】
看了题解才明白,逆向思考:
n-1个数同时加一,就好比每次有一个数自身减一
因为只能做减法,所以数组最后的数只能是最小值。
这样的话每个元素减去最小值求其和就是答案
int minMoves(int* nums, int numsSize){ int min = INT_MAX; int i; int ret = 0; for (i = 0; i < numsSize; i++) { min = fmin(min, nums[i]); } for (i = 0; i < numsSize; i++) { ret += nums[i] - min; } return ret; }
Ubantu安装ros注意事项 虚拟机VirtualBox中安装ubantu20.04.4安装过程中窗口太小而不能点下一步 Ubantu20.04下安装ros系统设置软件源设置key更新安装ros配置环境变量安装构建依赖初始化ros ros初始化遇到问题 虚拟机VirtualBox中安装ubantu20.04.4 安装过程中窗口太小而不能点下一步 三种解决办法:
1.alt+鼠标左键拖动:只能实现左右拖动
2.win+鼠标左键:任意拖动点击
3.ctrl+alt+t打开终端,输入以下代码改变窗口分辨率:xrandr -s 1280*800
Ubantu20.04下安装ros系统 设置软件源 ==两种办法:== 1.软件与更新(桌面版)(建议使用) 如下图,下载自选择其他,点进去之后选择一个国内源,如清华或阿里,然后重新载入。会自己修改/etc/apt/source.list内容。
2. 打开软件源列表 sudo vi /etc/apt/sources.list
删除国外官方源,换成国内源。如清华源:
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main multiverse restricted universe deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main multiverse restricted universe deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-proposed main multiverse restricted universe deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security main multiverse restricted universe deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates main multiverse restricted universe deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main multiverse restricted universe deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main multiverse restricted universe deb-src http://mirrors.
需求 最近有这么一个要求选取时间的时候,禁止选择今天和之后的日期(因为可能没有数据嘛) 选取的时间区间端不能超过30天 做法 使用a-range-picker
添加以下属性
v-model:value="searchForm.dataTime"选取的值记录value-format="YYYY-MM-DD"可选,值的格式:disabledDate="disabledDateHandler"不可选择的日期(日期当中的每一天都会调用这个函数)@calendarChange="dates => dateCalc.selectDateTime = dates[0]"待选日期发生变化的回调也就是我们每一次点击选择日期,就会调用一下这一个函数,这里作用是记录下第一个选择的日期时间(也就是日期开始的时间)@openChange="_ => dateCalc.selectDateTime = ''"弹出日历和关闭日历的回调,这里弹出或者关闭日期选择的时候清空下之前记录日期开始值@change="dateCalc.selectDateTime = ''"时间发生变化的回调,也就是开始时间,结束时间都选取完成后执行的回调:ranges="timeScopedPre"选取预设,可选(比如点击一下就可以选取7天,14天,30天的预设) import moment from "moment"; <a-range-picker v-model:value="searchForm.dataTime" value-format="YYYY-MM-DD" :disabledDate="disabledDateHandler" @calendarChange="dates => dateCalc.selectDateTime = dates[0]" @change="dateCalc.selectDateTime = ''" @openChange="_ => dateCalc.selectDateTime = ''" :ranges="timeScopedPre" /> const searchForm = ref<SearchFormTypes>({ dataTime:[moment().subtract(7,'days').format('YYYY-MM-DD'),moment().subtract(1,'days').format('YYYY-MM-DD')] //数据时间 默认前七天 }); //计算日期相关数据 const dateCalc = ref<any>({ selectDateTime:"",//计算日期数据-限制30天 }) const timeScopedPre = shallowRef<any>({ '近七日':[moment().subtract(7,'d'),moment().subtract(1,'d')], '近14日':[moment().subtract(14,'d'),moment().subtract(1,'d')], '近30日':[moment().subtract(30,'d'),moment().subtract(1,'d')], }) /* 禁用时间 */ const disabledDateHandler = (current) => { if(dateCalc.
不少读者反应,觉得周志华老师的西瓜书很难,难道真的很难?其实对于零基础的小白来说,是真的很难,这本书不适合刚入门的学者学习!
作为周老师的“扛鼎之作”,这本《机器学习》是真的很经典!
讲述了机器学习核心数学理论知识和算法
✏ 适合作为学校的教材或者中阶读者(有一定的扎实基础,学过机器学习数学基础啥的)自学使用
本书一共十六章,分为三个部分
✍✍第一部分:第一章~第三章(机器学习的基础知识)
✍✍第二部分:第四章~第十章(机器学习的经典算法:支持向量机、决策树、神经网络算法、贝叶斯算法、集成学习、降维与度量学习)
✍✍第三部分:第十一章~第十六章(机器学习进阶学习知识:稀疏学习、计算学习理论、半监督学习、概率图模型、规则学习、强化学习)
每次学完一个章节还会有习题可以做,并且介绍了相关的阅读材料,其实周志华老师就说了,这本书是他按照他以前的教案整理出版的,所以就很适合当教材用。
最后还有一本书也很需要就是——南瓜书《机器学习公式详解》
南瓜书的所有内容都是以西瓜书的内容为前置知识进行表述的, 所以南瓜书的最佳使用方法是以西瓜书为主线,遇到自己推导不出来或者看不懂的公式时再来查阅南瓜书
需要这两本电子书(2022年十月份最新南瓜书PDF)
可以私聊或者工重号:AI技术星球 回复:211
还有60G入门到进阶AI资源包(经典论文/书籍/项目课程/学习路线大纲)+带论文/学习/就业/竞赛指导+大牛技术问题答疑
内含:深度学习神经网络+CV计算机视觉学习(两大框架pytorch/tensorflow+源码课件笔记)+NLP等
适用人群
①准备毕业论文的学生
②准备跳槽,正在找工作的AI算法工程师等
③自学和准备转行到AI领域的人
④想巩固AI核心知识,查漏补缺的人
这篇补充了上篇的代码实现,可直接参见第二部分。
《ImageNet Classification with Deep Convolutional Neural Networks》基于深度卷积神经网络的Image分类
ImageNet:是一个图片分类数据集,分成1000类,每类大约1000多张图片
用到的技术:图像增强(两种方法)、ReLU、Dropout
第一部分:论文解读 0、摘要 (写法不怎么好)
第一步:告诉我们干了什么事情:我们训练了一个大型的深度卷积神经网络,将LSVRC-2010竞赛中的ImageNet 120万张高分辨率图像分类到1000个不同的类别。第二步:结果:在测试数据上,top-1的错误率是37.5%,top-5的错误率为17.0%,这大大优于之前的最先进水平。(2010年的竞赛给了测试集)该神经网络有6000万个参数和65万个神经元,由5个卷积层组成,其中一些是最大池化层,还有三个全连接层,最后是1000路的softmax。为了使训练更快,采用GPU。为了减少全连接层的过拟合,采用名为“dropout”的正则化方法。参加了LSVRC-2012比赛,2012年没有给测试集,我们的模型top-5错误率为15.3%,第二名的错误率为26.2%。表示我们的模型比第二名的模型好了很多。 1、序言 有了足够的计算和足够的数据,对于需要集成许多不同的、嘈杂的线索的复杂任务,学习胜过编程。(训练很重要)反向传播很重要。整个网络的分类性能取决于每个连接上的权重值。错误的结论:随机初始权重学习神经网络太难了。可以学习:但是要大量的标记数据和大量的计算。 现在无监督学习的发展,可以在无标记数据里学到想要的知识,例如GAN。
2、引言 本文干了什么:提出了一个物体识别方法。为了提高方法的性能:要大的数据集,学习更大的模型,还要防止过拟合。 过拟合(使用正则化)是深度学习的一个分支,重点是网络架构,网络架构很好的话正则化也没有那么重要。
本文提出的模型:CNNs,广度深度同样重要,CNNs的连接和参数要少很多,并且更容易训练,理论上的性能只是略差。(自己写论文的时候不能只说自己的东西很好)但是CNNs不好训练:用GPU训练,并且ImageNet够大,过拟合也不会太严重。 本文具体贡献如下:
训练了一个最大的CNNs,有着最好的准确率。但是现在看来AlexNet是小网络。编写了一个高度优化的二维卷积的GPU实现,以及CNNs固有的功能。一些新的不寻常的功能(在第四节中详细介绍),提高了性能、减少了训练时间。采用了以下有效的技术来防止过拟合(在第五节中详细介绍)。 最终的网络:
5个卷积层、3个全连接层。在GPU上进行训练。 文章说深度似乎很重要:我们去除任何的卷积层,都会导致性能下降。这个说法现在看来似乎不太对,深度和宽度同样重要,即使去掉一层,参数调好也能达到同样的效果。
3、数据集 使用的数据集:
使用ImageNet的一个子集,1000个类别,每个类别1000张图片。大约有120万张训练图像,5万张验证图像和15万张测试图像。 图像预处理:
预处理:仅仅做了剪裁,没有做任何的特征提取方法:最后要将图像下采样成256×256。先将短边缩放至256,长边不够256的话拉成256,长边够256的话从图像中裁剪出中央的256×256块。所以我们在像素的(居中)原始RGB值上训练我们的网络(没有抽取抽取特征,直接在原始的pixels上,原始的RGB上训练网络) 这个预处理很重要!现在绝大多数都采用原始的RGB图像,采用end to end,原始的图片,原始的文本直接放进去,不做任何的特征提取,神经网络直接做出来。这是在当时一个很重要的创新点,但是这篇文章没有细说。
4、架构 五个卷积层、三个全连接层 4.1 Rectified Linear Unit nonlinearity(非线性激活ReLU) 非线性激活一般方法是:Tanh或sigmoid。(当时用的几乎都是这两个,现在也用,ReLU用的比较多)
从图上就可以看出来走的很慢,该文章用ReLU激活函数:小于0的为0,大于0的是本身。
本文使用ReLU是因为tanh(X)慢,ReLU快。现在看来也没有快多少,但还是用ReLU,因为简单。
实验结果:
4.2 Training on multiple GPUs 在多个GPU上进行训练 我们自己训练肯定不会多个GPU,大型人工智能机构的肯定会。这里就略过。
4.3 Local response normalization LRN归一化 对局部神经元的活动创建了竞争机制,使得其中相应较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力,但是现在不用了。
-因为ReLU不像tanh、sigmoid有值域区间,所以在ReLU后面做一个normalization,本篇文章就是LRN。
4.4 池化层 对传统的pooling有一定的改动。采用了重叠的最大池化,此前的CNNs中普遍使用平均池化,采用最大池化,避免了平均池化的模糊化效果;并且重叠和覆盖,提升了特征的丰富性。
传统的pooling:stride=2,z=2,无重叠,为以下这种情况:
走两步,发现没有重叠。
本文的pooling:stride=2,z=3,有重叠,为以下这种情况:
走两步,可以看到是有重叠的。
本文使用的s=3,z=2,使得top-1和top-5的错误率分别降低了0.4%和0.3%,池化层不改变通道数,采取这种方法对过拟合也有一定的缓解。
4.5 整体架构 前五个是卷积层,后三个是全连接层。最后一个全连接层的输入被送入一个1000路的softmax,产生1000个类别标签的分布。二、四、五卷积层的内核只与前一层中位于同一GPU的内核图相连。第三层卷积层的神经元与第二层的所有内核图相连。全连接层的神经元与上一层的所有神经元相连。LRN加在第一层、第二层卷积层后。最大池化层在LRN后面和第五层卷积层后。ReLU用在每个卷积层和全连接层后。 第一层卷积层:卷积层、ReLU、LRN、最大池化层
最近写了两个个h5页面嵌套在小程序中,其中有一个按钮点击通过window.location.href跳转到第二个页面,在第二个页面中需要点击跳转按钮跳转到小程序中的某个页面,但是点击了没反应 现将问题记录如下
import wx from 'weixin-js-sdk' // 跳转方法 wx.miniProgram.navigateTo({ url: '/pages/**/**' }) 解决方法
let pageLocation = window.top.location || window.location; pageLocation.href = "http://****.com" 总结:
如果直接用window.location.href这种方式 小程序内嵌h5页面去调用微信的方法的时候
有些会失败,包括支付啊,跳转小程序页面什么的
在post请求中的参数中,Request Payload会经常碰到,但很多同学可能并未真正如何去使用,碰到复杂点的Request Payload往往一头雾水,下面就我日常所遇到的一些案例做个简单的说明,希望对大家有帮助。
关于Form Data与Request Payload的区别,可以参考文章:https://juejin.cn/post/6844904149809627149
https://leejason.blog.csdn.net/article/details/88720102
1 正常的json参数(非Request Payload) 这种是最普通常见的POST请求类型,请求头中Content-Type值通常为:application/x-www-form-urlencoded,也就是所谓的Form Data方式。
在scrapy的用法如下:
param = {"playerid": "25635555"} return scrapy.FormRequest(url=self.url_post, formdata=param, meta={ 'gameUserName': seed_keyword, #自定义参数 'SpiderRunTime': SpiderRunTime,#自定义参数 }, dont_filter=True, callback=self.parse) 在post中用法
requests.post(self.url_post, data=param )
2 简单Request Payload 如果发送失败的话,记得添加method=“POST”
param = {"playerid": "25635555"} return scrapy.FormRequest(url=self.url_post, body=json.dumps(param),#字典转换为json meta={ 'gameUserName': seed_keyword, #自定义参数 'SpiderRunTime': SpiderRunTime,#自定义参数 }, dont_filter=True, callback=self.parse) 3 复杂Request Payload 如果是复杂Request Payload,比如Request Payload是列表或或有子字典等,简单用json.dumps(param)转换后请求会经常报错。且使用Scrapy框架时利用自带的FormReuqest 是无法完成要求的。一般用python requests,直接将内容转换为字符串提交。如下:
处理这个参数一般有两种方式:
A:字典转字符
headers = { "Accept": "application/json, text/plain, */*"
前言 Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。
Pinia API 与 Vuex ≤4 有很大不同,即:
mutations 不再存在。他们经常被认为是 非常 冗长。他们最初带来了 devtools 集成,但这不再是问题。无需创建自定义复杂包装器来支持 TypeScript,所有内容都是类型化的,并且 API 的设计方式尽可能利用 TS 类型推断。不再需要注入、导入函数、调用函数、享受自动完成功能!无需动态添加 Store,默认情况下它们都是动态的,您甚至都不会注意到。请注意,您仍然可以随时手动使用 Store 进行注册,但因为它是自动的,您无需担心。不再有 modules 的嵌套结构。您仍然可以通过在另一个 Store 中导入和 使用 来隐式嵌套 Store,但 Pinia 通过设计提供平面结构,同时仍然支持 Store 之间的交叉组合方式。 您甚至可以拥有 Store 的循环依赖关系。没有 命名空间模块。鉴于 Store 的扁平架构,“命名空间” Store 是其定义方式所固有的,您可以说所有 Store 都是命名空间的。 1、安装 Pinia
pnpm install pinia 提示
如果您的应用使用 Vue 2,您还需要安装组合 API:@vue/composition-api。
2、main.ts 中创建一个 pinia 并挂载
import { createApp } from "vue"; import App from "
文章目录 论文原文摘要介绍相关工作基于会话的推荐SBR超图学习自我监督学习 具体实现方法符号和定义定义1,超图定义2:超图的线图 超图的构造双通道超图卷积网络超图通道和卷积线图通道和卷积模型优化和推荐生成通过自我监督学习增强DHCN 实验实验设置数据集基线方法(Baseline Methods)评估指标超参数设置 实验结果总体性能Ablation Study消融实验不同会话长度的影响模型深度的影响自我监督学习的影响 结论 阅读总结 论文原文 摘要 基于会话的推荐(SBR)侧重于某一时间点的下一项预测。由于在这种情况下用户概要文件通常不可用,因此捕获项目转换中的用户意图发挥了关键作用。
现有的基于图神经网络(GNNs)的SBR方法将项目转换视为成对关系,忽略了项目之间复杂的高阶信息。超图提供了一种捕获超成对关系的自然方法,而它在SBR中的潜力还未被开发。
在本文中,我们通过将基于会话的数据建模为超图来填补这一空白,然后提出一个双通道超图卷积网络- DHCN来改进SBR。此外,为了增强超图建模,我们创新地将自监督学习集成到网络的训练中,最大化DHCN中通过两个通道学习到的会话表示之间的相互信息,作为辅助任务来改进推荐任务。在三个基准数据集上的大量实验证明了我们的模型优于SOTA方法,消融研究验证了超图建模和自监督任务的有效性和基本原理。
介绍 基于会话的推荐(SBR)是一种新兴的推荐范式,其中长期用户资料通常不可用。通常,会话是一个购物事件中包含多个购买商品的事务,SBR通过使用实时用户行为关注下一个商品的预测。在这一领域的大多数研究工作将会话视为有序序列,其中基于循环神经网络(RNNs) 和基于图神经网络(GNNs) 的方法显示了良好的性能。
在基于RNNs的方法中,将基于会话的数据建模为单向序列被认为是成功的关键,因为数据通常在短时间内生成,而且很可能是时间依赖性的。然而,这种假设也可能会使这些基于rnn的模型陷入困境,因为它是欠考虑的。事实上,不像语言序列是按照严格的顺序生成的,在用户行为中,可能没有这样严格的时间顺序。例如,在Spotify上,用户可以选择打乱一张专辑或按顺序播放,这将生成两种不同的收听记录。然而,这两种播放模式都序列化同一组歌曲。换句话说,在这种情况下,颠倒两个项目的顺序不会导致用户偏好的扭曲。相反,如果只对项目的相对顺序进行严格建模,可能会使推荐模型容易过拟合。
过拟合(over-fitting)也称为过学习,它的直观表现是算法在训练集上表现好,但在测试集上表现不好,泛化性能差。过拟合是在模型参数拟合过程中由于训练数据包含抽样误差,在训练时复杂的模型将抽样误差也进行了拟合导致的。所谓抽样误差,是指抽样得到的样本集和整体数据集之间的偏差。直观来看,引起过拟合的可能原因有:
模型本身过于复杂,以至于拟合了训练样本集中的噪声。此时需要选用更简单的模型,或者对模型进行裁剪。训练样本太少或者缺乏代表性。此时需要增加样本数,或者增加样本的多样性。训练样本噪声的干扰,导致模型拟合了这些噪声,这时需要剔除噪声数据或者改用对噪声不敏感的模型。 最近,图神经网络(GNNs)的有效性已在包括SBR在内的许多领域报道。与基于rnns的推荐方法不同,基于gnns的方法将基于会话的数据建模为有向子图,将项目转换建模为成对关系,这略微放松了连续项目之间的时间依赖性假设。然而,与基于rnn的方法相比,现有的模型只显示出微不足道的改进。潜在的原因是他们忽略了基于会话的数据中复杂的项相关性。在实际场景中,项目转换通常是由以前的项目单击的联合作用触发的,项目之间存在多对多和高阶关系。显然,简单的图无法描述这种类似集合的关系。
为了克服这些问题,我们提出了一种新的基于超图的SBR方法,以模拟会话中项目之间的高阶关系。
从概念上讲,超图(Bretto 2013)由顶点集和超边集组成,其中超边可以连接任意数量的顶点,可用于编码高阶数据相关性。我们还假设会话中的项目在时间上是相关的,但不是严格的顺序依赖的。超边的特征完全符合我们的假设,因为超边是类似的,它强调所涉及元素的连贯性而不是相对顺序。因此,它为我们提供了在会话中捕获复杂交互的灵活性和能力。
从技术上讲,我们首先将每个会话建模为一个超边,其中所有项都相互连接,通过共享项连接的不同超边构成了包含项级高阶相关性的超图。然后,通过将每个超边建模为一个节点,基于该超图构建线图,并关注超边的连通性,从而描述会话级关系。之后,开发了一个双通道超图卷积网络(DHCN),分别从两个图中获取其两个通道的复杂项目相关性和交叉会话信息。
图1说明了超图构造和所提出方法的流水线。通过在两个通道中堆叠多层,我们可以借用超图卷积的优势来生成高质量的推荐结果。然而,由于每个超边只包含有限数量的项,固有的数据稀疏性问题可能会限制超图建模带来的好处。为了解决这个问题,我们创新性地将自我监督学习(Hjelm等人,2018年)集成到我们的模型中,以增强超图建模。直观地说,我们网络中的两个通道可以被看作是描述会话内部和内部信息的两个不同视图,而它们中的每一个对另一个的信息知之甚少。通过自监督学习使通过两个通道学习的会话表示之间的互信息最大化,两个通道可以相互获取新信息,以提高它们在项目/会话特征提取中的性能。然后,我们将推荐任务和自我监督任务统一在主辅助学习框架下。通过联合优化这两个任务,推荐任务的性能获得了可观的收益。
总体而言,这项工作的主要贡献总结如下:
我们提出了一种用于SBR的双通道超图卷积网络,该网络可以通过超图建模来捕捉项目之间的跨空中关系和跨会话信息。我们创新地将自我监督任务集成到我们的网络训练中,以增强超图建模并改进推荐任务。大量实验表明,我们提出的模型比最先进的基线具有压倒性优势,并在基准数据集上取得了显著的统计改进。 相关工作 基于会话的推荐SBR SBR的初步探索主要集中于序列建模,其中马尔可夫决策过程是该阶段的首选技术。(Shani、Heckerman和Brafman 2005年;Rendle、Freudenthaler和Schmidt-Thieme 2010年;Zimdars、Chickering和Meek 2013年)是这一研究领域的代表性作品。深度学习的繁荣提供了利用顺序数据的替代方法。诸如递归神经网络(Hochreiter和Schmidhuber 1997;Cho等人2014)和卷积神经网络(Tuan和Phuong 2017)等深度学习模型随后被应用于SBR并取得了巨大成功。(Hidasi等人2015年;Tan、Xu和Liu 2016年;Li等人2017年;Liu等人2018年)是经典的基于RNN的模型,它借用了RNN的优势来建模基于会话的数据。
图形神经网络(GNN)(Wu等人,2020年;Zhou等人,2018年)最近引起了越来越多的关注,其在SBR中的应用也显示出了良好的结果(Wang等人,2020b,c;Y uan等人,2019年;Chen和Wong 2020年)。与处理顺序数据的基于RNN的方法不同,基于GNN的方法通过会话诱导图学习项目转换。SR-GNN(Wu等人2019b)是一项开创性工作,它使用门控图神经网络将会话建模为图结构数据。GC-SAN(Xu等人,2019年)采用自我注意机制,通过图形信息聚合捕获项目依赖性。FGNN(邱等,2019)构建会话图来学习项目转换模式,并重新思考SBR中项目的顺序。GCE-GNN(Wang等人2020c)对单个会话图和全局会话图进行图卷积,以学习会话级和全局级嵌入。尽管这些研究表明,基于GNN的模型优于其他方法,包括基于RNN的模型,但它们都未能捕捉到复杂的高阶项目相关性。
超图学习 超图为复杂的高阶关系提供了一种自然的方式。随着深度学习的兴起,超图神经网络也受到了广泛的关注。HGNN(Feng等人2019)和HyperGCN(Y adati等人2019年)是第一个将图卷积应用于超图的。(Jiang et al 2019)提出了一种动态超图神经网络,(Bandyopadhyay,Das和Murty 2020)开发了线超图卷积网络。
还有一些研究将超图学习与推荐系统相结合(Bu等人2010;Li和Li 2013)。与我们最相关的工作是HyperRec(Wang等人,2020a),它使用超图来模拟用户对下一项推荐的短期偏好。但是,它不利用超边缘间信息,也不设计用于基于会话的场景。此外,该模型的高度复杂性使得它不可能在实际场景中部署。目前,还没有研究将超图神经网络和SBR连接起来,我们是第一个填补这一空白的人。
自我监督学习 自监督学习(Hjelm等人,2018)是一种新兴的机器学习范式,旨在从原始数据中学习数据表示。它首先用于视觉表征学习(Bachman、Hjelm和Buchwalter 2019)。该领域的最新进展将自监督学习扩展到图形表示学习(Velickovic等人,2019年)。基于对比学习的主导范式(Hassani和Khasahmadi 2020;Qiu等人,2020a)表明,对比具有相互信息最大化的图的一致和不一致视图可以帮助编码丰富的图/节点表示。
由于自我监督学习仍处于初级阶段,只有几项研究将其与推荐系统相结合(Zhou等人2020;Ma等人2020;Xin等人2020)。与我们最相关的工作是S3 Rec(Zhou等人,2020年),用于顺序推荐,它使用特征掩码创建自我监控信号。但它不适用于SBR,因为会话数据非常稀疏。目前,超图表示学习和SBR的自监督学习潜力尚未得到研究。我们是第一个将自我监督学习集成到SBR和超图建模场景中的人。
具体实现方法 在本节中,我们首先介绍本文中使用的概念和定义,然后展示如何将基于会话的数据建模为超图。然后,我们给出了SBR的双通道超图卷积网络。最后,我们将自监督学习集成到网络中以增强超图建模。
符号和定义 设 I = { i 1 , i 2 , i 3 , … , i n } I = \{i_1,i_2,i_3,\ldots,i_n\} I={i1,i2,i3,…,in}表示项的集合,其中N是项的数目
文章目录 前言一、委托是什么?1 官方关于委托的概述2 通俗解释 二、如何使用委托1 使用委托详解1) 申明委托2) 编写委托对应的方法3) 实例化委托4) 使用委托5) 委托使用的综合案例 2 使用多播委托详解(委托链)1) 关于多播委托2)案例讲解3)扩展 3 【?.Invoke】小知识点 三、为什么使用委托1 原因2 实例说明1) 需求:实现不同地域的人不同打招呼的方式2) 第一次需求变更,新增加一个地区人打招呼的方式3) 第二次需求变更,需要每次打招呼之前都先招手4) 方案对比5) 小结 四、泛型委托1 自定义泛型委托2 Action3 Func 总结 前言 该文主要讲解委托的使用,让我们在编程的时候更加得心应手的使用委托
一、委托是什么? 1 官方关于委托的概述 1 委托是一种引用类型,表示对具有特定参数列表和返回类型的方法的引用。
2 在实例化委托时,你可以将其实例与任何具有兼容签名和返回类型的方法相关联。 委托可以链接在一起,一次性调用多个方法
3 你可以通过委托实例调用方法。
4 委托用于将方法作为参数传递给其他方法,可用于定义回调方法
5 可将任何可访问类或结构中与委托类型匹配的任何方法分配给委托。该方法可以是静态方法,也可以是实例方法。 此灵活性意味着你可以通过编程方式来更改方法调用,还可以向现有类中插入新代码。
6 委托类型派生自 .NET 中的 Delegate 类。 委托类型是密封的,它们不能派生自 Delegate,也不能从其派生出自定义类
2 通俗解释 1 委托相当于是对具有相同返回类型和参数列表这一类方法进行了封装
2 由于委托本质是也是一个派生自Delegate类的类,其本质也是类,因此类可以申明在哪里,委托就可以申明在哪里
二、如何使用委托 1 使用委托详解 1) 申明委托 代码如下(示例):
public delegate void ShowDelegate(); public void Show() { Debug.
第一步:检查电脑是否支持虚拟化 1、任务管理器---->性能---->CPU
第二步:安装VMware,查看VMnet1和VMnet8是否存在
1、控制面板---->网络和Internet---->网络和共享中心---->更改适配器设置
2、VMnet1和VMnet8---->属性---->显示"已启用"即可
第三步: 在VMware中查看,虚拟网络编辑器
1、编辑---->虚拟网络编辑器---->主机连接"已连接"
完结撒花!!!
现在很多同学都更新了win11的系统,但是Win11和VM有的版本不兼容,导致出现蓝屏问题。这里简单记录一下安装VM和Win10的过程,以及解决蓝屏的方法。
事实上,如果是从官网上下载的最新版的VM,对于Win11来说不会出现蓝屏的问题,因为我是下载的别人提供的资源,不是最新版的所以才出现了版本不兼容的问题。
一、VMware虚拟机安装教程 1、下载VM 首先需要下载VMware,可以从官网下载。
进入官网之后,首先在工作台里面找workstation pro点进去
然后往下滑,找到试用版并下载
进去之后,再往下滑,找到适合自己电脑系统的版本,Win11这里选择的是适用于Windows的版本
2、安装VM 下载之后打开安装,安装过程比较简单,几乎不会有什么问题,一般不要安装在C盘,别的基本按照默认就差不多了。 3、创建新的虚拟机(Win10) 安装好之后打开VM,点击创建新的虚拟机,这里的示例是安装的Win10
在此处选择你Win10所下载的位置,图片上的是我自己电脑想要装的Win10所在的位置
密钥可以不写
也可以自定义硬件配置
到此win10就算安装完毕了。
二、解决蓝屏问题 但是当开启win10的时候,电脑就会出现蓝屏。对于蓝屏的解决方法,我主要试了两种。第一种就是在更改电脑的虚拟化设置,但是没有什么用。第二种是对VM进行了升级,成功解决问题。
首先在VM中的帮助中点击软件更新,
根据提示更新到最新,重启电脑即可解决蓝屏问题。
1. 进制转换
n = 16 print(n) print(bin(n)) # 十进制转二进制 print(oct(n)) # 十进制转八进制 print(hex(n)) # 十进制转十六进制 # 16 # 0b10000 # 0o20 # 0x10 print(int('10000', 2)) # 二进制转十进制 print(int('0o20', 8)) # 八进制转十进制 print(int('0x10', 16)) # 十六进制转十进制 # 除十进制外,其他进制之间相互转换,需要使用十进制中转 # 八进制转十六进制,应该先由八进制转成十进制,再从十进制转十六进制 print(hex(int('0o20', 8))) 2. 位运算
# &:按位与运算符,参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0; print(bin(21)) print(bin(6)) print(bin(21 & 6)) # |:按位或运算符,只要对应的二个二进位有一个为1时,结果位就为1; print(bin(21)) print(bin(6)) print(bin(21 | 6)) # ^:按位异或运算符,当两对应的二进位相异时,结果为1; print(bin(21)) print(bin(6)) print(bin(21 ^ 6)) # ~:按位取反运算符,对数据的每个二进制位取反,即把1变为0,把0变为1; print(bin(21)) print(~21) print(bin(~21)) # >>:右移动运算符,把 >> 左边的运算数的各二进位全部右移若干位,>> 右边的数指定移动的位数; print(bin(21)) print(21 >> 3) print(bin(21 >> 3)) # <<:左移动运算符,运算数的各二进位全部左移若干位,由 << 右边的数指定移动的位数,高位丢弃,低位补0。 print(bin(21)) print(21 << 3) print(bin(21 << 3))
0. 前言 装饰器在 python 中使用的频率非常高,它可以在不改动原有函数的基础上对其进行增强功能。
下面主要是介绍装饰器的各种用法,并理解其运行过程。
1. 使用 1.1 在函数上添加装饰器 decro 是一个装饰器函数,其实现是将内部的函数 wrapper 作为返回值返回出去。
在函数 test 上添加 @decro 进行使用,可以将本函数作为一个参数传入到 decro 函数中,然后,然后得到的是装饰器函数内部返回的函数 wrapper, 我们在调用 test 方法时,其实调用的是装饰器返回的 wrapper 函数,该函数中会调用被装饰的函数 test
def decro(func): def wrapper(*args, **kwargs): print("wrapper") return func() return wrapper @decro def test(): print("test") test() 输出:
wrapper test 1.2 装饰器的运行过程 装饰器时在被装饰的函数定义之后立即运行的,当执行到@decro 装饰 test 函数时,会马上执行函数 decro,然后将 wrapper 给返回出去。
def decro(func): print("decro") def wrapper(*args, **kwargs): print("wrapper") return func() return wrapper print("start") @decro def test(): print("
写放大,Write Amplification Factor,缩写WAF,这一术语最早是在2008年左右,由Intel公司和SiliconSystems公司(2009 年被西部数字收购)第一次在公开稿件中提出了并使用。WAF代表的含义就是NAND实际写入数据量与host写入量的比值,最理想的情况就是WAF=1,这个值越接近1越好。
linux环境的nvme ssd举例,可以通过nvme smart-log-add命令获取NAND和host写入量:
nvme smart-log-add /dev/nvme0 Additional Smart Log for NVME device:nvme0 namespace-id:ffffffff key normalized raw program_fail_count : 100% 0 erase_fail_count : 100% 0 wear_leveling : 62% min: 1114, max: 1161, avg: 1134 end_to_end_error_detection_count: 100% 0 crc_error_count : 100% 0 timed_workload_media_wear : 100% 37.941% timed_workload_host_reads : 100% 51% timed_workload_timer : 100% 446008 min thermal_throttle_status : 100% 0%, cnt: 0 retry_buffer_overflow_count : 100% 0 pll_lock_loss_count : 100% 0 nand_bytes_written : 100% sectors: 16185227 host_bytes_written : 100% sectors: 6405605 要想完全理解写放大,我们需要先了解固态硬盘的读写机制。我们知道,固态硬盘的存储单元是由闪存颗粒组成的,无法实现物理性的数据覆盖,只能擦除然后写入,重复这一过程。因而,我们可以想象得到,在实际读写过程中,数据的读写势必会在闪存颗粒上进行多次的擦除写入,特别是当某些区块已经完全被塞满的情况下。
内存 一、内存二、指令三、逻辑地址,相对地址四、写程序到程序运行五、装入三种方式5.1 绝对装入5.2 静态重定位5.3 动态重定位5.4 总结 六、链接三种方式6.1 静态链接6.2 载入时动态链接6.3 运行时动态链接 七、思维导图 一、内存 内存是用于存放数据的硬件,程序执行前需要放到内存中才能被CPU处理
内存地址从0开始,每个地址对应一个存储单元
二、指令 高级语言编译后的代码,会形成对等的机器指令
内存中,变量存放在数据段,指令存放在程序段。CPU会依次执行指令,每个指令对应的有操作码和地址码,一般来说机器指令不知道该进程数据会存放在哪里,这里指令给出的地址参数一般是逻辑地址
进程在逻辑上由程序段、数据段、PCB组成
三、逻辑地址,相对地址 编译时产生的指令只关心 相对地址(逻辑地址),实际放入内存中根据起始位置得到 绝对地址(物理地址) 四、写程序到程序运行 编译:由程序将用户源代码编译成若干个目标模块(翻译为机器语言)
链接:由链接程序将编译后形成的一组目标模块,以及所需库函数链接在一起,形成完整的装入模块
装入:由装入程序将装入模块装入内存运行
在装入过程要先完成逻辑地址到物理地址的转换,然后将程序和数据装入内存中指定的物理地址。根据逻辑地址到物理地址所采用的不同转换方法将装入分为三种方式,下面详细讲解这三种装入方式(逻辑地址转物理地址方式)
五、装入三种方式 5.1 绝对装入 定义:即在编译时,就已经知道程序将放到内存中的哪个位置,编译程序直接产生绝对地址(物理地址)的目标代码。装入程序按照装入模块中的地址,直接将程序和数据装入内存即可
这种方式只适用于单道程序环境,因为单道程序保证只有一个程序在访问内存,不会导致不同程序相互竞争占用同一块内存的情况。
5.2 静态重定位 定义:装入之前就必须分配其需要的全部内存空间,并且确定内存的起始位置,然后装入程序一次性完成所有指令的逻辑地址到物理地址的转换
静态重定位的特点是在一个作业装入内存时,必须分配其要求的全部内存空间,如果没有足够的内存,就不能装入该作业。作业一旦进入内存后,在运行期间就不能再移动,也不能再申请内存空间。
5.3 动态重定位 定义:这种方式就是在将逻辑地址转为物理地址推迟到了具体的程序运行时期,具体是通过一个系统设置的重定位寄存器实现的。重定位寄存器中存放了装入模块在内存中的起始地址,我们只需要将逻辑地址与寄存器中的起始地址相加就可以得到实际的物理地址
采用动态重定位时允许程序在内存中发生移动(只需要对应修改重定位寄存器中的起始位置就可以了)
5.4 总结 1、绝对装入和静态重定位装入的方式,都是一次性将程序全部装入到指定内存位置, 并且后续程序位置不能发生改变; 2、动态重定位装入方式是可以一部分一部分的装入内存,并且程序在内存中的位置并不固定, 可以发生移动(只需要对应修改重定位寄存器中的起始位置就可以了) 六、链接三种方式 链接是将编译为CPU可以识别的多个机器代码目标模块整合为一个完整的装入模块。根据链接的时期将其分为三种方式
6.1 静态链接 在程序运行之前,先将各目标模块及它们所需的库函数连接成一个完整的可执行文件(装入模块),之后不再拆开
6.2 载入时动态链接 将各目标模块装入内存时,边装入边链接的链接方式(一次性依次将所有模块装入)
6.3 运行时动态链接 在程序执行中需要该目标模块时,才对它进行链接。其优点是便于修改和更新,便于实现对目标模块的共享
七、思维导图
1 volatile的基本信息 1.1 volatile的特性 可见性、有序性(禁止重排 )。
volatile不具备原子性。在一个线程(t1)操作volatile变量时,另一个线程(t2)更新了该volatile变量的值,则t1线程需要去主内存中获取最新的volatile变量值,t1线程之前的操作则全部作废,出现操作丢失问题。由此可见volatile解决的是可见性的问题,而无法保证其原子性。所以在多线程修改主内存变量的情况下必须加锁。
1.2 volatile变量的读写过程 在对一个volatile变量进行写操作时,JMM会将该线程工作内存中的该volatile变量立即刷新回主内存中,并通知其它线程该变量已更新。在对一个volatile变量进行读操作时,JMM会将该线程工作内存中的该volatile变量置为无效,重新回到主内存中读取该变量。 1.2.1 8个原子性操作
read(读取):作用于主内存,将变量从主内存读取到工作内存中。load(加载):作用于工作内存,将读取到工作内存中的变量放入工作内存的变量副本中(工作线程修改的都是自己副本中的变量)。use(使用):作用于工作内存,将工作内存中的变量副本中的值传递给执行引擎进行操作。assign(赋值):作用于工作内存,将执行引擎中返回的值赋值给工作内存中的变量副本。store(存储):作用于工作内存,将赋值完毕的变量副本写回给主内存。write(写入):作用于主内存,将工作内存写回的值赋值给主内存中的变量。lock(锁定):作用于主内存,在工作内存写回变量的过程中,为防止多个线程同时向主内存写入,因此需要加锁,确保同一时刻只能有一个线程写入。unlock(解锁):作用于主内存,对应lock,线程写入后解锁,其他线程才能继续写入该变量。 1.2.2 volatile变量的读写过程流程图
从volatile的读写过程中,可以看出改变volatile变量后通知其它线程实现了volatile的可见性。
1.3 volatile的适用场景 状态标志:将volatile修饰的状态变量改变时,会立刻通知其他线程。开销较低的读,写锁策略:当读远多于写的情况下,可以将变量设置为volatile,则只需要在写操作上添加sync同步即可,每次写操作都会通知读操作去读取最新的值。 单例模式中为变量添加volatile,保证多线程情况下new对象时禁止指令重排的问题(先获取一块内存地址,再通过这块内存初始化对象,再返回对象的地址); 2 内存屏障 2.1 内存屏障的作用 内存屏障是为了保证volatile的有序性,即禁止指令重排序(在多线程环境下,指令会根据编译器等重排序)的一种屏障指令。主要用于禁止屏障两侧的指令重排。
2.2 内存屏障的实现方式 当一个变量被定义为volatile时,在其字节码层面会为这个字段的flags里添加一个ACC_VOLATILE,jvm在生成对应的字节码指令时,发现操作的是volatile变量时,会在相应位置插入内存屏障。
2.3 内存屏障分类 通过读屏障与写屏障之间的配合,能够实现指令的顺序执行,从而达到有序性的特点。
2.3.1 写屏障
告诉处理器,在写屏障之前的所有存储在工作内存中的变量数据同步到主内存中。即在写屏障之前必须将所有写入指令执行完成才能继续执行。
在写指令之前插入写屏障,将写屏障之前的缓存数据强制刷回主内存中。
2.3.2 读屏障
处理器在读屏障之后的操作只能在读屏障之后进行。即保证读屏障之后的读操作一定能读取到最新的数据。
在读指令之前插入读屏障,让工作内存或cpu中的缓存数据失效,从而回到主内存中读取最新的数据。
2.3.3 四种屏障
LoadLoad屏障(Load1;LoadLoad;Load2):保证Load1的读取在Load2之前执行。StoreStore屏障(Store1;StoreStore;Store2):保证在Store2写操作之前,Store1的写操作已经刷新到主内存。LoadStore屏障(Load1;LoadStore;Store1):保证在Store1写操作之前,Load1的读操作已经完成。StoreLoad屏障(Store1;StoreLoad;Load1):保证在Load1读操作之前,Store1以及之前的写操作已经刷新回主内存中。 2.4 volatile规则之四种屏障的位置 当第一个操作为volatile读操作时,无论第二个是什么操作,都不能重排;当第二个操作为volatile写操作时,无论第一个操作是什么,都不能重排;当第一个操作为volatile写操作,第二个为volatile读操作时,不能重排; 2.4.1读操作内存屏障指令示意图
2.4.2 写操作内存屏障指令示意图
3 总结 通过上述内存大致可以看出,volatile的读写流程实现了其可见性,即读写完立即通知其他线程获取最新的值。volatile的内存屏障则实现了其有序性(禁止重排),通过四种读写屏障强制指定读写命令的顺序。
❤️ 堆排序 文章目录 ❤️ 堆排序💟 堆排序实现思路✏️ 实现思路:🖊 疑问解决: 💜 堆排序实现💚 堆排序时间复杂度分析 💟 堆排序实现思路 堆排序(HeapSort)是利用堆这种数据结构所设计的一种排序算法,它是选择排序的一种。
堆分为大根堆和小根堆,并且堆必须为完全二叉树,使用物理上使用数组实现。
大堆:父节点总是大于子节点的堆小堆:父节点总是小于子节点的堆 ✏️ 实现思路: 1、建堆
升序:建大堆降序:建小堆 2、利用堆删除思想来进行排序
🖊 疑问解决: 1、堆排序时为什么升序要建大堆?降序建小堆?
升序建小堆时,如图: 建好小堆后,我们需要对其调整至升序的状态 ①:升序用小堆建好后,只有第一个数据已经排好,为最小的数据,但是剩下的数据是没有排好的,次小的数据也不一定就在下一位,所以需要重新建堆。
②:倘若将剩下的数据看做堆,再重新向下调整,但此时的二叉树不能被看成小堆了已经。如图:
因为向下调整的前提是:左右子树必须是个堆。
③:所以此时就需要重新建堆,选出次小的元素,然后重复①,②、③。
这里的时间复杂度为O(N^2)
升序建大堆时,如图: 建好大堆后,我们需要对其调整至升序状态 ①:这里我们可以将最后一个叶子节点的值与堆顶的值进行交换,交换后如图:
②:然后将交换后的最后一个节点不看做堆里面的数据,然后向下调整,选出次大的数据到堆顶,之后再重复①、②
这里的时间复杂度为O(N*logN)
综合以上两种方法,得出升序建大堆时时间复杂度较小,所以升序建大堆,降序同理得建小堆。
2、建堆时算法的选择,是使用向上调整还是向下调整?
向上调整建堆时间复杂度分析 向上调整建堆是从堆顶开始依次向上建堆,我们以满二叉树来分析其时间复杂度
我们假设数的高度为h,分析每一层数据需要向上调整的次数
第1层,2^0个节点,需要向上调整0层
第2层,2^1个节点,需要向上调整1层
…
第h-1层,2^(h-2)个节点,需要向上调整h-2层
第h层,2^(h-1)个节点,需要向上调整h-1层
总的调整次数 = 每一层节点个数 ×这一层节点最坏向下调整的次数 N = 2^h-1
利用错位相减法算出其时间复杂度为 O(N*logN)
向下调整建堆时间复杂度分析 向下调整建堆是从最后一个节点的父节点开始依次向下建堆,我们以满二叉树来分析其时间复杂度
我们假设数的高度为h,分析每一层数据需要向下调整的次数
第1层,2^0个节点,需要向下调整h-1层
第2层,2^1个节点,需要向下调整h-2层
…
第h-1层,2^(h-2)个节点,需要向下调整1层
第h层,2^(h-1)个节点,不需要向下调整
所以总的调整次数 = 每一层节点个数 ×这一层节点最坏向下调整的次数
T(N) = 2^0×(h-1) + 2^1×(h-2) + …… + 2^(h-2)×1 N = 2^h-1
之前用网上的代码,直到有一天遇到了问题,决定添加异常判断(因为这个问题找了好几天才发现原因)。
1.添加对输入字符串合法性判断(可以根据个人需要更改)
2.添加输出内存字节判断防止越界。
void HexStringToASCII(const std::string & strInput, char * pOutput, int iOutPutSize) { if (strInput.size() % 2 != 0) return; if (strInput.size() / 2 > iOutPutSize) return; for (std::string::size_type i = 0; i < strInput.size(); i+=2) { int n = i / 2; if (strInput[i] >= '0' && strInput[i] <= '9') pOutput[n] = (strInput[i] - '0') << 4; else if (strInput[i] >= 'A' && strInput[i] <= 'F') pOutput[n] = (strInput[i] - 'A' + 10) << 4; else if (strInput[i] >= 'a' && strInput[i] <= 'f') pOutput[n] = (strInput[i] - 'a' + 10) << 4; else return; if (strInput[i+1] >= '0' && strInput[i+1] <= '9') pOutput[n] |= (strInput[i+1] - '0'); else if (strInput[i+1] >= 'A' && strInput[i+1] <= 'F') pOutput[n] |= (strInput[i+1] - 'A' + 10); else if (strInput[i+1] >= 'a' && strInput[i+1] <= 'f') pOutput[n] |= (strInput[i+1] - 'a' + 10); else return; } }
一. npm init -y 命令的作用是: 对项目进行初始化操作,对包进行管理
-y 的含义:yes的意思,在init的时候省去了敲回车的步骤,生成的默认的package.json
如果不想使用默认的package.json,可以用npm init来自定义
二. npm install -D -S -g的区别 npm install 后缀写入到适用打包环境举例-D、–save-devdevDependencies对象开发环境babel,sass-loader,gulp ,webpack-S、–savedependencies对象生产环境axios,当无后缀时,默认 -S-g全局安装vue 三.全局安装和本地安装 1. 全局安装 全局安装的包可提供直接执行的命令(例:gulp -h可以查看gulp定义了什么命令)。 比如gulp全局安装后,可以在命令行上直接执行gulp -v、gulp -h等(原理:全局安装的gulp会将其package.json中的bin命令注入到了全局环境,使得你可以全局执行:gulp xxx命令,这另一个话题了,不深入)。倘若只在本地安装了gulp,未在全局安装gulp,直接执行这些命令会报错。你想要执行相应的命令则可能需要例如:node ./node_modules/gulp/bin/gulp.js -v(查看版本) 这样用一大串命令来执行。因此全局安装就发挥到他的好处了,一个gulp -v就搞定
当然,不是每个包都必须要全局安装的,一般在项目中需要用到该包定义的命令才需要全局安装。比如gulp 执行gulp任务…等,所以是否需要全局安装取决于我们如何使用这个包。全局安装的就像全局变量有点粗糙,但在某些情况下也是必要的,全局包很重要,但如果不需要,最好避免使用。
2. 本地安装 (1)如果只是全局安装了而没本地安装,就得require(‘’) 例:引入一个全局的包可能就是requirt(‘/usr/local/…’)通过全局包的路径引入,这样显然十分的不灵活。如果安装了本地包,那么就可以直接require(‘’)引入使用。
(2)一个包通常会在不同的项目上会重复用到,如果只全局安装,那么当某个项目需要该包更新版本时,更新后可能就会影响到其他同样引用该包的项目,因此本地安装可以更灵活地在不同的项目使用不同版本的包,并避免全局包污染的问题,
要用到该包的命令执行任务的就需要全局安装,要通过require引入使用的就需要本地安装
新创建了一个vue3+typescript项目,在项目中加一个空格或者回车换行就出现红色波浪线;
我的解决办法是在vsCode的扩展中找到 ESLint 点击禁用 然后再点击重新加载就可以解决了
el-table属性,文档中默认的实在第一列显示的,如何改变成第二行列显示或者........
在第一列的 el-table-column标签中添加type="",就可以将树形列表添加到第二列,想在那一列显示就可以将前面的el-table-column标签中添加type=""
一:背景 用户在查看文章详情的时候,文章除了正文外还附带有各类型附件(如:word,excel,ppt,zip等),当用户想要查看附件时,需要先下载到本地再打开,这样很不方便,于是用户希望能够有在线预览附件的功能。
二:方案(参考:https://blog.csdn.net/xinghui_liu/article/details/125641300) 日常开发中常见的文件格式有pdf,word,Excel,PPT,Html,txt,图片等。pdf,Html,txt,图片这种实现在线预览非常简单,有一些前端的插件可以满足要求。word,Excel,PPT如果要实现在线预览,就非常的困难。word,Excel,PPT实现在线预览常用的方式就是先转换成pdf,然后在进行预览。下面我就介绍常用的几种方案
方法一、kkfileview 文件在线预览
kkfileview支持文件格式多,而且不用开发。不过需要单独部署一个文件预览的服务,而且服务
器也需要安装openoffice。
方法二、officetohtml纯前端的方式
officetohtml纯前端的方式可以不用安装任何插件及服务,但是目前只支持文件地址的方式预览
,如果是文件流的话无法使用。
方法三、JODConverter
JODConverter 依赖于openoffice,需要在服务器单独安装openoffice。
方法四、Aspose
Aspose使用的是破解版的,如果商用使用需要考虑版权问题。
综上所述,考虑到方法四有版权问题所以我首先排除了选四,一,二,三都需要安装openoffice,又由于方法一支持的文件类型更多而且无需开发,所以最终我选择了方法一,接下来我就单讲方法一的整个实现过程。
三:kkfileview 文件在线预览具体实现 1. windows环境部署运行
1.1 环境要求
1. Java: 1.8+
2. OpenOffice或LiberOffice(Windows下已内置)无需考虑此条
1.2 下载 kkFileView-4.0.0.zip(Windows版)
下载链接:kkFileView 发行版 - Gitee.com
或从我的资源里拿
1.3 解压 kkFileView-4.0.0.zip ,然后进入到kkFileView-4.0.0/bin/ 目录下,双击 startup.bat 即可启动该应用。浏览器能正常访问:http://localhost:8012 即可表示启动正常。
1.4 项目接入使用
如果你的项目需要接入文件预览项目,达到对docx,excel,ppt,jpg等文件的预览效果,那么通过在你的前端项目中加入下面的代码即可成功实现。
var url = 'http://127.0.0.1:8080/file/test.txt'; //要预览文件的访问地址
window.open('http://127.0.0.1:8012/onlinePreview?url='+encodeURIComponent
(Base64.encode(url)));
黄色背景部分为运行的kkFileView的地址
Base64 一定要用,否则文件打不开
完毕! 2. linux环境部署运行
2.1 环境要求
1. Java: 1.8+
2. OpenOffice或LiberOffice(CentOS或Ubuntu下, 联网了会自动下载安装,MacOS下需要
自行安装),由于我是CentOS系统且是内网,无法自动下载,于是我选择了手动下载安装包并离线安装LiberOffice。
最近发现个问题:cdn 引入elementPlus,table标签显示不正常:
<el-table :data="tableData" style="width: 100%" border> <el-table-column prop="date" label="Date" width="180" /> <el-table-column prop="name" label="Name" width="180" /> <el-table-column prop="address" label="Address" /> </el-table> 最后发现是 cdn引入 不支持自结束标签的写法,要写完整标签:
<el-table :data="tableData" style="width: 100%" border> <el-table-column prop="date" label="Date" width="180" ></el-table-column> <el-table-column prop="name" label="Name" width="180"></el-table-column> <el-table-column prop="address" label="Address" ></el-table-column> </el-table>
玩转topic 前言1. 创建topic(--create)2. 查看当前服务器中的所有 topic(--list)3.查看某个 topic 的详情(--describe)4.发布消息(--broker-list )5.消费消息(--bootstrap-server)6.修改分区数7.删除 topic 前言 本文是以kafka_2.6.0为模板
所有的topic命名test 1. 创建topic(–create) bash kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 2 --partitions 3 --topic test zookeeper: 定义 zookeeper 集群服务器地址,如果有多个 IP 地址使用逗号分割,一般使用一个 IP 即可replication-factor: 定义分区副本数,1 代表单副本,建议为 2 partitions:定义分区数topic: 定义 topic 名称 2. 查看当前服务器中的所有 topic(–list) kafka-topics.sh --list --zookeeper localhost:2181 3.查看某个 topic 的详情(–describe) bash kafka-topics.sh --describe --zookeeper localhost:2181 4.发布消息(–broker-list ) bash kafka-console-producer.sh --broker-list localhost:9092 --topic test 5.消费消息(–bootstrap-server) bash kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning 6.
文章目录 入门篇操作系统入门 Linux 编程技能专业基础篇编程语言Java 语言学习 Go 语言 理论学科数据结构和算法其它理论基础知识 系统知识C10K 问题实践项目 软件设计篇编程范式一些软件设计的相关原则一些软件设计的读物 高手成长篇Linux 系统、内存和网络(系统底层知识)Linux 系统相关内存相关计算机网络网络学习网络调优网络协议 异步 I/O 模型和 Lock-Free 编程(系统底层知识)异步 I/O 模型Lock-Free 编程相关其它相关论文小结 Java 底层知识Java 字节码相关JVM 相关小结 数据库关系型数据库NoSQL 数据库各种 NoSQL 数据库小结 分布式架构入门(分布式架构)分布式架构入门分布式理论小结 分布式架构经典图书和论文(分布式架构)经典图书经典论文分布式事务Paxos 一致性算法Raft 一致性算法Gossip 一致性算法分布式存储和数据库分布式消息系统日志和数据分布式监控和跟踪数据分析与编程相关的论文其它的分布式论文阅读列表 小结 分布式架构工程设计 (分布式架构)设计模式设计与工程实践分布式系统的故障测试弹性伸缩一致性哈希数据库分布式缓存消息队列关于日志方面关于性能方面关于搜索方面各公司的架构实践 小结 微服务微服务架构微服务和 SOA设计模式和最佳实践相关资源小结 容器化和自动化运维DockerKubernetes小结 机器学习和人工智能基本原理简介相关课程相关图书相关文章相关算法相关资源小结 前端基础和底层原理(前端方向)HTML 5CSSJavaScript浏览器原理网络协议小结 前端性能优化和框架(前端方向)前端框架React.js 框架Vue.js 框架 小结 UI/UX 设计(前端方向)图书和文章推荐原子设计(Atomic Design)设计语言和设计系统Fluent Design SystemMaterial Design其它公司动画效果设计 相关资源文章资源设计收集 小结 技术资源集散地YouTube 技术频道 入门篇 通过这一系列文章,我主要想回答以下几个问题。
理论和现实的差距。你是否觉得自己从学校毕业的时候只做过小玩具一样的程序?走入职场后哪怕没有什么经验也可以把文中提到的这些课外练习走一遍。学校课程总是从理论出发,作业项目都看不出有什么实际作用,到了工作上发现自己什么也不会干。
技术能力的瓶颈。你又是否觉得,在工作当中需要的技术只不过是不断地堆业务功能,完全没有什么技术含量。而你工作一段时间后,自己都感觉得非常地迷茫和彷徨,感觉到达了提高的瓶颈,完全不知道怎么提升了。
技术太多学不过来。你是否又觉得,要学的技术多得都不行了,完全不知道怎么学?感觉完全跟不上。有没有什么速成的方法?
对此,我有如下的一些解释,以端正一下你的态度。
并不是理论和现实的差距大,而是你还没有找到相关的场景,来感受到那些学院派知识的强大威力。算法与数据结构、操作系统原理、编译原理、数据库原理、计算机原理……这些原理上的东西,是你想要成为一个专家必须要学的东西。这就是“工人”和“工程师”的差别,是“建筑工人”和“建筑架构师”的差别。如果你觉得这些理论上的东西无用,那么只能说明,你只不过在从事工人的工作,而不是工程师的工作。技术能力的瓶颈,以及技术太多学不过来,只不过是你为自己的能力不足或是懒惰找的借口罢了。技术的东西都是死的,这些死的知识只要努力就是可以学会的。只不过聪明的人花得时间少,笨点的人花得时间多点罢了。这其中的时间差距主要是由学习方法的不同,基础知识储备的不同决定的。只要你方法得当,多花点时间在基础知识上,会让你未来学习应用知识的时间大大缩短。以绝大多数人努力的程度,和为自己不努力找借口的程度为参考,只要你坚持正常的学习就可以超过大多数人了。这里没有学习技术的速成的方法,真正的牛人不是能够培训出来的,一切都是要靠你自己去努力和持续地付出。如果你觉得自己不是一个能坚持的人,也不是一个想努力的人,而是一个想找捷径的人,那么,这篇文章并不适合你。这篇文章中的成长路径是需要思考、精力和相关的经验的,这都需要时间,而且是不短的时间。你先问问自己有没有花十年磨一剑的决心,如果没有,那这篇文章对你没有任何作用。 学习建议。
一定要坚持,要保持长时间学习,甚至终生学习的态度。一定要动手,不管例子多么简单,建议至少自己动手敲一遍看看是否理解了里头的细枝末节。一定要学会思考,思考为什么要这样,而不是那样。还要举一反三地思考。不要乱买书,不要乱追新技术新名词,基础的东西经过很长时间积累,会在未来至少 10 年通用。回顾一下历史,看看历史时间线上技术的发展,你才能明白明天会是什么样的。 操作系统入门 Linux 学习编程你还需要会玩 Linux,虽然 Windows 占据着更多的桌面市场,但是你还是要了解 Linux。这里,你可以看一下,W3CSchool 上的在线教程 Linux 教程。
ICLR 2020 | GraphAF: a Flow-based Autoregressive Model for Molecular Graph Generation Paper: https://arxiv.org/abs/2001.09382
Code: https://github.com/DeepGraphLearning/GraphAF
graphhaf:一个基于流的分子图生成自回归模型 这篇是来自北京大学和上海交通大学的Chence Shi等人在2020年的ICLR上发表的会议论文。
摘要 分子图谱的生成是药物发现的一个基本问题,越来越受到人们的关注。这是一个具有挑战性的问题,因为它不仅需要生成化学上有效的分子结构,同时也需要优化它们的化学性质。受深度生成模型的启发,本文提出了一种基于流的自回归图生成模型,称为GraphAF。GraphAF结合了自回归和基于流的方法的优点:(1)数据密度估计的高模型灵活性;(2)用于训练的高效并行计算。(3)一个迭代采样过程,它允许利用化学领域的知识进行价键检查。实验结果表明,即使没有化学知识规则,GraphAF也能生成68%的化学有效分子,而有化学规则则能生成100%的有效分子。GraphAF的训练过程比现有的最先进的方法GCPN快两倍。通过强化学习对目标导向性能优化模型进行微调后,GraphAF在化学性能优化和约束性能优化方面都取得了最先进的性能。
介绍 设计具有理想性能的新型分子结构是药物发现和材料科学等各种应用中的一个基本问题。这个问题非常具有挑战性,因为化学空间本质上是离散的,而整个搜索空间是巨大的,据信高达 1 0 33 10^{33} 1033。机器学习技术在分子设计领域看到了巨大的机会,这要归功于这些领域的大量数据。近年来,越来越多的人致力于开发能够自动生成化学上有效的分子结构并同时优化其性质的机器学习算法。
具体来说,通过将分子结构表示为图,并使用深层生成模型生成图结构,例如变分自动编码器(VAEs)、生成对抗网络(GANs)和自回归模型,已经取得了重大进展。例如,Jin提出了一种用于分子结构编码和解码的连接树VAE (joint Tree VAE)。De Cao和Kipf研究了如何使用GAN生成分子图。You提出了一种称为图卷积策略网络(GCPN)的方法,该方法将分子图生成形成一个序列决策过程,并基于现有的图子结构动态生成节点和边。他们使用强化学习来优化生成图结构的性质。最近,另一项非常相关的工作molecular arrnn (MRNN)提出使用自回归模型生成分子图。基于自回归的方法,包括GCPN和MRNN,在分子图生成的各种任务中表现出非常有竞争力的性能。
最近,除了上述三种生成模型外,规范化流程也取得了显著的进展,并已成功地应用于各种任务,包括密度估计、变分推断和图像生成。基于流的方法定义了潜在基分布(如高斯分布)和真实的高维数据(如图像和语音)之间的可逆转换。这种可逆映射允许计算准确的数据可能性。同时,通过隐藏空间与观测空间之间的多层非线性变换,流具有较高的数据密度建模能力。此外,根据不同应用的需求,可以设计不同的架构来促进快速训练或快速采样。
受自回归模型的现有研究成果和具有标准化流程的深层生成模型的最新进展的启发,我们提出了一个基于流程的自回归模型,称为GraphAF,用于分子图生成。GraphAF有效地结合了自回归和基于流的方法的优点。它有很高的模型容量,因此能够模拟真实世界分子数据的密度。GraphAF采样过程设计为自回归模型,根据已有子图结构动态生成节点和边缘。与GCPN和MRNN等现有模型相似,这种连续生成过程允许在每个生成步骤中利用化学域知识和价键检查,从而保证生成的分子结构的有效性。同时,与GCPN和MRNN在训练过程中作为自回归模型不同,GraphAF定义了一个从分子图结构到碱基分布的前馈神经网络,因此能够并行计算准确的数据似然。因此,GraphAF的训练过程是非常高效的。
我们在标准ZINC数据集上进行了广泛的实验。结果表明,graphhaf的训练效率显著,比目前最先进的GCPN模型快2倍。通过结合生成过程中的化学规则,他生成的分子是100%有效的。我们还惊奇地发现,即使在生成过程中没有使用化价检查的化学规则,GraphAF生成的有效分子的百分比仍然高达68%,显著高于现有的最先进的GCPN。这说明GraphAF确实具有较高的模型能力来学习分子结构的数据分布。我们通过强化学习进一步微调生成过程,以优化生成分子的化学性质。结果表明,在属性优化和约束属性优化任务上,GraphAF的性能明显优于之前最先进的GCPN。
相关工作 最近,人们提出了多种用于分子图生成的深度生成模型。RVAE模型使用变分自动编码器生成分子,并提出了一种新的正则化框架,以确保语义的有效性。Jin提议将分子表示为化学支架的连接树,并提出了分子产生的JT-VAE模型。对于基于虚拟空间的方法,化学性质的优化通常是通过贝叶斯优化在潜在空间中搜索来实现的。 De Cao& Kipf使用生成对抗网络进行分子生成。最先进的模型是建立在基于自回归的方法。You根据当前的子图结构动态地添加新的节点和边,将问题表述为一个连续的决策过程,并且生成策略网络由强化学习框架进行训练。最近,Popova提出了一种自回归模型MolecularRNN,基于生成的节点和边缘序列生成新的节点和边缘。自回归模型的迭代特性允许在生成过程中有效地利用化学规则进行价检查,因此这些模型生成的有效分子的比例非常高。然而,由于序列生成的性质,训练过程通常是缓慢的。我们的GraphAF方法具有自回归模型等迭代生成过程(从观测空间映射到潜空间)的优点,同时计算出前馈神经网络对应的精确似然(从观测空间映射到潜空间),它可以通过并行计算有效地实现。
最近的两项工作Graph Normalizing flow (GNF)和GraphNVP也是基于流的图生成方法。但是,我们的工作和他们的工作在精神上是完全不同的。GNF定义了一个从基本分布到预训练的Graph Autoencoders的隐藏节点表示的规范化流程。该生成方案通过两个独立的阶段完成,首先用归一化流生成节点嵌入,然后在第一阶段根据生成的节点嵌入生成图形。 相比之下,在GraphAF中,我们定义了一个从碱基分布直接到分子图结构的自回归流,可以端到端训练。GraphAF还定义了从碱基分布到分子图结构的规范化流。在我们的GraphAF中,我们将生成过程定义为一个顺序决策过程,并通过图神经网络有效地捕获子图结构,在此基础上,我们定义了一个策略函数来生成节点和边。顺序生成过程也允许结合化学规则。这样可以保证所生成分子的有效性。我们在表1中总结了现有方法。
预准备 自回归流 标准化流定义了一个参数化的可逆确定性转换,从基本分布 ε \varepsilon ε(潜在空间,如高斯分布)到真实世界的观测空间 Z Z Z(如图像和语音)。设 f : ε → Z f : \varepsilon \rightarrow Z f:ε→Z为一个可逆变换,其中pE()为基分布,那么我们可以通过变量变换公式计算出真实数据Z的密度函数,即 p Z ( Z ) pZ(Z) pZ(Z)。
异常信息 :我看错误的时候,是dashboard.html,然后我就一直以为是路径的原因,因为我给页面设置了别名,就直觉是别名出错,后来突然发觉他报的是500,和路径没有关系……
2022-10-25 22:48:24.197 ERROR 11480 --- [nio-8087-exec-6] org.thymeleaf.TemplateEngine : [THYMELEAF][http-nio-8087-exec-6] Exception processing template "dashboard": An error happened during template parsing (template: "class path resource [templates/dashboard.html]") org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/dashboard.html]") at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:241) ~[thymeleaf-3.0.15.RELEASE.jar:3.0.15.RELEASE] at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parseStandalone(AbstractMarkupTemplateParser.java:100) ~[thymeleaf-3.0.15.RELEASE.jar:3.0.15.RELEASE] at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:666) ~[thymeleaf-3.0.15.RELEASE.jar:3.0.15.RELEASE] at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098) [thymeleaf-3.0.15.RELEASE.jar:3.0.15.RELEASE] at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072) [thymeleaf-3.0.15.RELEASE.jar:3.0.15.RELEASE] at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:366) [thymeleaf-spring5-3.0.15.RELEASE.jar:3.0.15.RELEASE] at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:190) [thymeleaf-spring5-3.0.15.RELEASE.jar:3.0.15.RELEASE] at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1405) [spring-webmvc-5.3.23.jar:5.3.23] at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1149) [spring-webmvc-5.3.23.jar:5.3.23] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1088) [spring-webmvc-5.3.23.jar:5.3.23] at org.
业务需要,做一个用户自定义的公式计算。
公式由前端自定义,生成字符串发给后端,由后端完成计算。
公式需要支持四则运算,支持常用函数,支持函数的嵌套运算。
字符串类似这种
“1-2.5+SUM(3*4,5,SUM(IF(“皮卡”=“皮卡丘”,5,DAYS(“2022-10-19”,“2022-10-29”)),6))”
字符串四则运算,首先下意识就想到后缀表达式,思路就是基于后缀表达式添加函数的兼容。
中缀转后缀之前,首先把字符串分割成列表,这里规定函数中用到字符串为参数,比如日期,字符串,需要用""包起来。
/** * 将表达式转为list */ private static List<String> expressionToList(String text) { int index = 0; List<String> list = new ArrayList<>(); try { String opStr = replaceFunctionStr(text); do { char ch = opStr.charAt(index); if (ch < 48 || ch > 57) { if (ch == '"') { //是字符参数,截取到下一个引号为止 String str = ""; index += 1; while (index < opStr.length() && opStr.charAt(index) != '"') { str += opStr.
本系统是基于jsp+servlet+mysql的前后端分离的酒店管理系统,前后端分离是指前端和后端分别是两个独立存在的项目,能独立运行。没有前端项目,后端也能运行且进行数据管理,没有后端项目,前端也能运行且能注册登录以及下订单。
本系统集中数据管理、分布式应用,实现信息的全面共享,为决策者提供最新的人力资源数据。
完全基于浏览器的操作模式,安装简单、操作方便,具有良好的系统扩充能力。
灵活的模块需求设计,可根据实训项目周期灵活裁剪。
严格的安全管理机制。利用 SSL 技术维护网络传输安全,利用安全规则和特权保证基本信息的安全管理,提供日常操作的审计功能,并对重要的安全事件提供报警,对重要数据进行加密。
支持中英文界面切换。
对于系统执行的重要操作自动记录操作人和操作日期。操作人默认为当前登录人员。操作日期默认为当天。
源码地址:基于jsp+servlet+mysql的酒店管理系统.zip-Web开发文档类资源-CSDN下载
实现效果图如下:
注册登录
注册成功即可写入数据库
主页面为三张全屏轮播展示图,主要以顶端导航栏为主要操作。
服务
关于我们
预定酒店:由于数据库中图片暂时没有添加,故不显示图,可以自行在数据库直接添加,或者在后台修改图片。能选择到达和离开的日期。点击立即预定即可预定成功,此时数据库的book表里已经录入订单。
联系我们:反馈建议提交之后,后台管理端会看见,因为是写入数据库的。
后台管理端
管理员注册登录
注册完录入数据库manage表
管理端主页
管理端所有功能:管理端左侧导航栏中的所有功能均能实现增删改查,由于截图太多,所以放以下部分图。
用户管理
源码地址:基于jsp+servlet+mysql的酒店管理系统.zip-Web开发文档类资源-CSDN下载
关于Mysql 中查询字段中包含相同字符串两次的sql 工作中遇见一个需求,查询一个字段中包含一个字符串超过一次
可以使用子查询
SELECT t.*,locate('字符串',`options`,t.locates+1) FROM (SELECT id,`options`,locate('字符串',`options`) AS locates FROM `table_name` WHERE INSTR (`options`,'字符串')) t WHERE locate('字符串',`options`,t.locates+1) > 0 其中locate() 函数起到重要作用
App网络优化是体验中很重要的一部分, 最近做了一些网络优化相关的工作, 想把最近的工作总结一下;
1. 分析app网络现状: 通过对最新版本最近一周的网络数据统计, 网络错误率中各项占比:
未知主机: 1.33%
请求超时: 0.33%
SSL证书错误: 0.13%
建立连接失败: 0.23%
平均网络请求响应时间:
1237ms 从数据看, 最高的网络错误来自于未知主机, 请求响应时长偏高;
然后通过各种更多维度的数据查看发现, 总结出了下面几个问题:
慢请求中有很多是DNS时间超长, 最长的有几百秒错误请求中, DNS错误占比最高 当然,还有其他一些错误和响应时长的问题, 比如http错误, 需要通过错误码从业务方面解决; 请求连接时长,传输和处理时长, 这些可以通过服务端优化;本次哇们主要做的是DNS相关的优化
2.DNS如何优化 2.1 关于DNS原理简单介绍: 关于DNS的相关介绍:https://www.51cto.com/article/674906.html
传统的DNS解析:
当开始 DNS 解析的时候,如果 LocalDNS 没有缓存,那就会向 LocalDNS 服务器请求(通常就是运营商),如果还是没有,就会一级一级的,从根域名查对应的顶级域名,再从顶级域名查权威域名服务器,最后通过权威域名服务器,获取具体域名对应的 IP 地址。
传统DNS缺点: 不稳定(DNS服务器被劫持或故障), 访问慢
2.2 传统DNS替代 使用HttpDNS解析:
HttpDNS其实也是对DNS解析的另一种实现方式,只是将域名解析的协议由DNS协议换成了Http协议,并不复杂。使用HTTP协议向D+服务器的80端口进行请求,代替传统的DNS协议向DNS服务器的53端口进行请求,绕开了运营商的Local DNS,从而避免了使用运营商Local DNS造成的劫持和跨网问题;
HttpDNS核心是需要稳定且速度快的DNS服务器, 一般都是需要收费的; 目前有阿里DNS,腾讯云DNS等选择; (我没有尝试过收费的); 免费的有开源的七牛sdk, 需要自己配置服务器与连接方式;
七牛开源地址: https://github.com/qiniu/happy-dns-android DnsManager dns; if(DnsManager.needHttpDns()){ IResolver[] resolvers = new IResolver[2]; // dohResolver 需要配置一个支持 Doh(Dns over http) 协议的 url resolvers[0] = new DnhResolver("
配置前提:确保域名在HTTP普通网站可以正常打开,并且域名已经解析到百度加速。
一、登录沃通数字证书商店下载:SSL证书文件并且解压,选择nginx文件夹,百度云加速只需要用到nginx文件夹。
二、登录百度云加速:https://su.baidu.com/
三、选择需要配置SSL证书的域名
四、证书管理——证书列表——上传证书
五、证书上传——名称:自定义——填写证书——填写私钥——确定
六、配置强制HTTPS访问网站
1、其它——特定页面规则
2、添加URL:http://www.wosign.com/*
3、URL跳转301永久跳转
4、跳转到:https://www.wosign.com/$1
5、确定
注意:www.wosign.com域名改成自己的域名。
七、安全功能——HTTPS——半程加密
选择说明:
1、仅在CDN配置SSL证书选择[半程加密]
2、服务器已经安装了可信SSL证书需要设置[严格加密]
3、服务器已经安装了自签名不可信SSL证书需要设置[全程加密]
生效时间:一般情况下5分钟左右生效,清空浏览器测试访问效果。
标注之后labelme出现闪退:
Traceback (most recent call last):
File “D:\install\anaconda\lib\site-packages\labelme\app.py”, line 1364, in newShape
self.addLabel(shape)
File “D:\install\anaconda\lib\site-packages\labelme\app.py”, line 1139, in addLabel
self.labelList.addItem(label_list_item)
File “D:\install\anaconda\lib\site-packages\labelme\widgets\label_list_widget.py”, line 167, in addItem
item.setSizeHint(self.itemDelegate().sizeHint(None, None))
TypeError: setSizeHint(self, QSize): argument 1 has unexpected type ‘QSizeF’
解决方法:
先安装python3.8,再安装pyqt5
conda create --name=labelme python=3.8 pip install pyqt5 相关资料:https://www.bilibili.com/video/BV1xT4y1j7A9/?from=search&seid=2903997967250679674
通过labelme生成的json文件得到mask: https://blog.csdn.net/qq_48355075/article/details/122805677
JENKINS 配置多个仓库(多个SSH) 在阿里云服务器中生成公私钥:
cd /root/.ssh
输入:ssh-keygen -t rsa (切换Jenkins账户生成,或者修改/etc/sysconfig/jenkins)
第二步:可以输入文件名(不输入则默认是id_rsa、id_rsa.pub),因为考虑多个仓库,需要多组公私钥,所以我取了其他名称。然后一直enter…
生成公私钥后,如何让Jenkins从仓库获取代码呢 1.将刚才生成的公钥id_rsa.pub 里面的内容copy到你的远程仓库
2.将公钥对应的私钥里面的内容复制到Jenkins中
身份认证通过了,就不会有红字报错信息了这样,Jenkins就可以从远程仓库丝滑的拉取代码了。
如果公私钥配置完后(root账号可以拉取代码),但是Jenkins还是连不上gitLab,那就给Jenkins账号赋权限(chown Jenkins /root/.ssh)。
完结。
目录
指定语言
下载:
引入使用
使用
获取时间戳
生成指定时间的moment
获取对象
格式化
获取时间
获取当月的第一天时星期几
获取前n天/后n天
获取两个日期的时间差
比较两个时间的大小
判断一个年份是否是闰年
获取月份和星期
基础操作 在我们前端开发中,我们会涉及到许多对时间日期的一些处理,本文就是对moment常见用法的总结
指定语言 不然可能会引起不必要的bug
moment.locale('zh-cn') 下载: npm install moment --save 或 yarn add moment 引入使用 import moment from 'moment' 使用 获取时间戳 # 精确到毫秒 moment().valueOf() ## 1584182611042 ;返回值为数值类型 moment().format('x') ## 返回值为字符串类型 # 精确到秒 moment().unix() ## 1584182618 精确到秒 返回值为数值类型 moment().format('X') ## 返回值为字符串类型 生成指定时间的moment moment("2000-9-28") #带格式 moment("2000-9-28","MM-DD-YYYY") 获取对象 moment().toObject(); # 返回一个包括:年、月、日、时、分、秒、毫秒的对象 # { years: 2020 months: 2 date: 14 hours: 18 minutes: 47 seconds: 56 milliseconds: 526 } 格式化 moment().
SqlServer备份,还原,生成脚本 目录 SqlServer备份,还原,生成脚本1 SqlServer备份1.1 选择需要备份的数据库,右键菜单=》选择任务=》选择备份1.2 配置备份数据库的参数,选择备份类型以及备份路径1.3 配置完毕,点击确定即可备份 2 SqlServer还原2.1右键菜单,选择还原数据库2.2 配置还原数据库相关设置2.3 选择好文件,点击确定,完成还原 3 SqlServer生成脚本3.1 右键菜单,选择任务,选择生成脚本3.2 配置生成脚本相关设置 4 生成脚本和备份在数据库备份上的区别 1 SqlServer备份 1.1 选择需要备份的数据库,右键菜单=》选择任务=》选择备份 如下图所示
1.2 配置备份数据库的参数,选择备份类型以及备份路径 如下图所示
此处注意【目标】也就是备份路径,可以删除和添加,但是保持这里只有一项内容,多项路径备份的时候会报错
如下图
1.3 配置完毕,点击确定即可备份 2 SqlServer还原 2.1右键菜单,选择还原数据库 2.2 配置还原数据库相关设置 1 【目标数据库,注意手动添加即可】 这里不要事先建库,事先建库容易还原失败。
大多数因为数据库日志或其他配置的问题不统一导致无法还原,因此推荐只需手动写目标数据库名称即可
2 【选择源设备】
3 在新的对话框里,选择【添加】
4 找到备份数据库bak文件的路径,选择即可
2.3 选择好文件,点击确定,完成还原 3 SqlServer生成脚本 3.1 右键菜单,选择任务,选择生成脚本 3.2 配置生成脚本相关设置 1 点击生成脚本后,选择第一项
如下图操作,可以灵活的选择编写脚本的数据库对象,
【编写整个数据库及所有数据库对象的脚本】则表示导出的脚本,可以让你在执行这个脚本的时候重建整个数据库,甚至包括里面的数据
【选择特定数据库对象】则可以根据自己的需求,选择对应的表或者函数,存储过程等对象进行脚本编写
2 选择高级,将【要编写脚本的数据的类型】修改为【架构和数据】
【仅限架构】只会导出数据库的框架,但是没有数据
【架构和数据】则是相当于有备份数据库的功能
【仅限数据】则只会将数据库中的数据编写成脚本
注意哦:这里还可以选择 你需要保存的路径,这个地方有时容易忽略,导致自己不知道导出到哪里去了
3 点击确定,下一步即可完成
4 生成脚本和备份在数据库备份上的区别 1 生成脚本和备份都可以达到数据库完整备份的目的,但是侧重点不同,具体使用看需求场景而定
APM32F4在RT-Thread系统上使用LwIP网络功能—基于RT-Thread Studio环境 RT-Thread Studio 是RTT官方的一款集成开发环境,可以很方便的进行RT-Thread实时系统的程序开发,而且对应RT-Thread系统常用的组件可以进行图形化配置,非常的方便。
RT-Thread Studio可以访问官网 RT-Thread Studio 下载地址,在官网下载最新的 RT-Thread Studio 软件安装包。
下面基于 RT-Thread Studio ,把 LwIP 网络协议栈和RT-Thread系统移植到 APM32F4 上运行。
1. 创建APM32F4的工程项目 1、首先点击新建RT-Thread项目
2、然后选择下面的配置,如果你的RTT Studio还没有APM32F4的软件包的话,选择添加更多资源,然后找到geehy厂商的软件包,然后安装即可。
上面的一些配置可以看自己板子的实际情况进行选择,比如可以选择其他串口作为控制台,或者选择其他调试模式等等。最后点击完成即可。
2. 编译下载生成的基本工程项目 点击完成之后,就可以在左边的资源管理器看到生成的项目文件了,如下:
我们可以点击编译,可以看到编译完成没有任何警告和错误。
这个时候,是可以把程序下载到我们的板子上运行的。下载程序后,打开串口终端软件,可以看到RT-Thread打印的信息,如下:
其中,程序会不断打印 Hello … 字符串,这是因为Main函数里面输出的打印,如果觉得占用了控制台可以把该语句屏蔽。
3. 解决shell不能输入字符bug 这时,我们在串口终端发现,shell不能接收字符输入。这是一个bug,原因就是串口的GPIO配置有问题,我们把下面文件函数修改一下即可:
修改完之后,在重新编译下载,shell就可以正常输入字符、命令了,如下:
4. 使能网络接口设备和LwIP 双击打开配置文件 RT-Thread Settings , 然后找到组件这里,使能网络接口设备和LwIP堆栈。
其中,我们点击使能之后,里面还有更详细的细节配置可供用户进行配置,比如是否使用DHCP进行动态获取IP地址等,这里我设置为静态IP,因为我没用插路由器。
然后点击保存后,再重新进行编译,可以看到没有任何警告和错误。
这个时候,我们其实可以下载程序运行了的,但是网络功能是还不能正常使用的,因为底层的网络驱动文件还没编写。
下载程序后,在终端输入 ifconfig 命令,可以看到说网络设备有错误,如下:
5. 添加RTT的网络驱动文件 这个驱动文件如果bsp包里面有的话,应该是可以配置加入 RTT Studio 里面的吧,但是APM32并没有这个文件的支持,所以只能我们自己编写这个网络驱动文件了,可以参考下面RTT官方文档的介绍,看看需要我们提供什么样的接口函数。
https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/application-note/components/network/an0010-lwip-driver-porting
这里,我已经提前写好了这个文件,分别是 drv_eth.c 和 drv_eth.h 。我们把这两个文件复制到工程目录的drivers目录下。
6. 然后打开 BSP_USING_ETH 宏定义 我们在 board.
一杯热气腾腾的咖啡,没错,这就是Java的标志。学习Java,我们就从这杯咖啡开始。2022年10月24日🚩
Hello Java! 一、认识Java从Hello world开始二、运行Java程序1、编译运行原理2、JDK、JRE、JVM以及它们之间的关系3、运行步骤展示 三、注释四、标识符 一、认识Java从Hello world开始 编写java的源文件是非常简单的,我们可以创建一个test文本文件,并将后缀改为.java,这样我们就得到了java的一个源文件,然后使用文本编辑器就可以开始编码了(笔者这里使用的是notepad++)。
public class HelloWorld{ public static void main(String[] args){ System.out.println("Hello world"); } } 下面我们简单分析一下这段Java程序:
class HelloWorld: 代表着定义个“类”, 类名叫做:“HelloWorld”,Java是个面向对象的语言。而类是面向对象的定义规则, 一个类就是一个对象。main: 并且指定了一个 main 方法, 这个是 Java 的默认主函数。固定格式为:public static void main(String[] args)System.out:是系统的输出文件。输出一串内容到控制台。 通过上述代码,我们可以看到一个完整的Java程序的结构,Java程序的结构由如下三个部分组成:
源文件(扩展名为.java):源文件带有类的定义。类用来表示程序的一个组件,小程序或许只会有一个类。类的内容必须包含在花括号里面。类:类中带有一个或多个方法。方法必须在类的内部声明。方法:在方法的花括号中编写方法应该执行的语句。
总结: 类存在于源文件里面;方法存在于类中;语句存在于方法中。
注意: 在一个源文件中只能有一个public修饰的类,而且源文件名字必须与public修饰的类名字相同。
二、运行Java程序 1、编译运行原理 Java是一门半编译型、半解释型语言。先通过javac编译程序把源文件进行编译,编译后生成的.class文件是由字节码组成的,与平台无关、面向JVM的文件。最后启动java虚拟机(JVM)来运行.class文件,此时JVM会将字节码转换成平台能够理解的形式来运行。如图:
也许看到这里你还是一头雾水,什么是JDK、JRE、JVM?他们之间又有怎样的联系?别急,我们往下看:
2、JDK、JRE、JVM以及它们之间的关系 JDK(Java Development Kit):Java开发工具包,提供给Java程序员使用,包含了JRE,同时还包含了编译器javac与自带的调试工具Jconsole、jstack等。JRE(Java Runtime Environment):Java运行时环境,包含了JVM,Java基础类库。是使用Java语言编写程序运行的所需环境。JVM:Java虚拟机,运行Java代码 注意: 在运行Java程序前,必须先安装好JDK,JDK里面就包含了javac和java工具,Java程序最终是在JVM(Java虚拟机)中运行的。
3、运行步骤展示 安装配置好Java环境后,想要编译运行Java程序就会变得容易的多,下面展示在cmd中使用命令编译运行Java程序:
1.使用cd命令转到.java目录下
2.javac命令编译java源程序
3.java命令运行.class字节码文件
你有没有成功运行起来你的第一个Java程序呢?如果没有,快来看看是不是下面的问题👇
编写运行第一个Java时可能出现的错误:
源文件名后缀不是.java类名与文件名不一致main方法名字写错:mian类没有使用public修饰方法中语句没有以分号结尾中文格式的分号JDK环境没有配置好,操作系统不能识别javac或者java命令 三、注释 类似于其它开发语言,Java中也有注释的使用,注释风格主要有如下3种:
单行注释:// 注释内容(用的最多)多行注释:/* 注释内容*/(不推荐)文档注释: /** 文档注释 */(常见于方法和类之上描述方法和类的作用),可以被javadoc工具解析,生成一套以网页文件形式体现的程序说明文档 注意:
适用于 Linux 的 Windows 子系统没有已安装的分发版。 可以通过访问 Microsoft Store 来安装分发版: https://aka.ms/wslstore
wsl --install -d Ubuntu 版本查看命令:winver
运行命令 wsl --install 如:
下载官方安装包,https://yarnpkg.com/zh-Hans/docs/install
安装nodejs
https://nodejs.org/en/download/
安装yarn
npm i -g yarn
验证
yarn -v # 出现对应版本号即代表安装成功
安装VUE
配置yarn镜像
yarn config set registry https://registry.npm.taobao.org --global yarn config set disturl https://npm.taobao.org/dist --global
下载 使用git工具下载libmodbus库源码
git clone git://github.com/stephane/libmodbus 安装 下载好后会出现一个libmodbus的文件夹在当前目录下。
cd libmodbus 然后执行autogen.sh文件
./autogen.sh orangepi@orangepizero:~/luo/libmodbus$ ./autogen.sh configure.ac:33: installing 'build-aux/compile' configure.ac:56: installing 'build-aux/config.guess' configure.ac:56: installing 'build-aux/config.sub' configure.ac:32: installing 'build-aux/install-sh' configure.ac:32: installing 'build-aux/missing' src/Makefile.am:2: error: Libtool library used but 'LIBTOOL' is undefined src/Makefile.am:2: The usual way to define 'LIBTOOL' is to add 'LT_INIT' src/Makefile.am:2: to 'configure.ac' and run 'aclocal' and 'autoconf' again. src/Makefile.am:2: If 'LT_INIT' is in 'configure.ac', make sure src/Makefile.am:2: its definition is in aclocal's search path.
1 cuda卸载 我windows11下安装的cuda为11.1,常用的cuda为10.2和11.3,所以选择卸载重装。
1)首先打开控制面板->程序和功能
卸载:框住的内容。
保留:NVIDIA的图形驱动程序、NVIDIA Physx系统软件、NVIDIA GeForce Experience
其中NVIDIA Nsight Systems是NVIDIA官方近几年推出了新一代性能分析工具——NSight系列,包括NSight System和NSight Compute,其中Nsight Systems就是全新一代的nvprof,可以用于监测代码执行效率及分析性能。
2)卸载完如下所示
2 cuda10.2安装的准备 2.1 查看可以安装的cuda版本 1)打开NVIDIA Control Panel
2)点击左下角系统信息
一般是驱动版本决定了能用的CUDA版本的上限,比如新版的显卡驱动可以支持老的CUDA runtime。但是老的显卡可能无法更新到最新的显卡驱动,因此我这里只能用到CUDA11.2。
2.2 CUDA toolkit Download 注:下载推荐使用迅雷,速度快。
https://developer.nvidia.com/cuda-toolkit-archive
2.3 CUDNN Download https://developer.nvidia.com/rdp/cudnn-archive
3 cuda安装 1)双击“exe文件”,选择下载路径(推荐默认路径)
2)如果你是第一次安装,尽量全选
如果你是第n次安装,尽量只选择第一个,不然会出现错误
3)不要选Visual Studio Integration
4)记住安装位置
5)安装完成
6)查看系统变量中是否添加了路径,如果没有需要自己添加
7)测试是否安装成功
运行cmd,输入nvcc -V 即可查看版本号;
set cuda,可以查看 CUDA 设置的环境变量。
4 CUDNN配置 1)解压压缩包得到下面文件
2)把以上三个文件夹直接复制到cuda安装目录下,覆盖原有内容
3)拷贝
4)添加至系统变量
5)验证安装是否成功
cd到C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.2\extras\demo_suite,然后分别执行bandwidthTest.exe和deviceQuery.exe
参考博客 [1] windows下CUDA的卸载以及安装
目录 1.什么是三子棋2.三子棋思想3.三子棋代码分为几个部分4.Test.c(测试部分)5.game.h(头文件)6.game.c(游戏部分)6.1棋盘初始化6.2打印棋盘6.3玩家下棋6.4电脑下棋6.5判断是否赢了6.6 判断棋盘是否为空 1.什么是三子棋 三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利,而对方就算输了,但是三子棋在很多时候会出现和棋的局面。 2.三子棋思想 首先我们需要创建一个9*9的正方形框架 然后由玩家和电脑依次在小型方格内下入他们的棋,需要判断这个格是否为空,如果为空则可以在格内下棋,否则需要从新寻找空格 如果一个人三个棋在同一行或同一列或同一斜线上,则判断获胜. 3.三子棋代码分为几个部分 头文件(Test.c)测试部分(game.c)游戏部分(gamet.h) 4.Test.c(测试部分) Test.c的代码,下面为大家分块讲解
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" void menu() { printf("**********************\n"); printf("***** 1.play ********\n"); printf("***** 0.exit *******\n"); printf("**********************\n"); } void game() { char ret = 0; char board[ROW][COL] = {0};//创建一个数组 init_board(board, ROW, COL);//初始化棋盘 display_board(board, ROW, COL);//打印空白棋盘 while (1) { player_move(board, ROW, COL);//玩家下棋 display_board(board, ROW, COL);//打印棋盘 ret = is_win(board, ROW, COL);//判断是否赢了 if (ret != 'C') break; computer_move(board, ROW, COL);//电脑下棋 display_board(board, ROW, COL);//打印棋盘 ret = is_win(board, ROW, COL); if (ret !
项目场景: 在学习SpringMVC部署项目过程中,出现了如下错误
问题描述 具体报错信息如下:
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "ServletContext resource [/WEB-INF/templates/index.html]") org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:235) org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parseStandalone(AbstractMarkupTemplateParser.java:100) org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:649) org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098) org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072) org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:366) org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:190) org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1401) org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1145) org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1084) org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) javax.servlet.http.HttpServlet.service(HttpServlet.java:670) org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) javax.servlet.http.HttpServlet.service(HttpServlet.java:779) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) 解决方案 这里信息是找不到WEB-INF目录下相关文件夹内的index.html文件,经过查阅网上相关博客,大致有以下两种情况
检查SpringMVC.xml核心配置文件里面信息是否与文件目录符合 如图,检查文件前缀和文件夹目录是否符合,如果符合,进入另外一种情况分析
检查文件Web目录是否工作正常 这种做法最粗显的做法便是检查文件目录下web文件夹是否有蓝点,如果有蓝点则说明工作正常
如果没有蓝点,那么检查Web文件目录配置是否正常
这里选到Web目录即可
原因分析 idea重启的过程中可能扫描包结构的时候自己修改了一些配置,按照以上两种做法基本能解决
文章目录 1.简介2.直接使用like语句效率低的原因3.模糊查询优化的方法1.索引2.LOCATE(‘substr’,str,pos)方法3.POSITION(‘substr’ IN field)方法4.INSTR(str,‘substr’)方法5.CONTAINS(`column`,str)方法 4.字符串精准匹配1.默认函数2.自定义函数 1.简介 在平时使用msyql需要模糊的匹配字段的时候,我们第一反应就是使用like查询语句来模糊匹配,当数据量小的时候,我们通常感觉不到是否影响查询效率,但在数据量达到百万级,千万级的时候,like查询的低效率就很容易显现出来。这个时候查询的效率就显得很重要。
2.直接使用like语句效率低的原因 下面建立一张测试表作为所有演示的数据。
在mysql中直接使用like并不会影响查询使用索引,但在开头使用通配符后(% 或者_)索引就会失效,查询数据量较大时必然会造成性能问题。
3.模糊查询优化的方法 1.索引 SELECT `column` FROM `table` WHERE `field` like 'keyword%'; 没加索引情况下是全表搜索,加了索引情况下速度会大幅度提升,但不适用于全部搜索,只适用于"keywork%"关键字开头
2.LOCATE(‘substr’,str,pos)方法 SELECT `column` FROM `table` WHERE LOCATE('keyword', `field`)>0 keyword是要搜索的内容,field为被匹配的字段,查询出全部存在keyword的数据
3.POSITION(‘substr’ IN field)方法 SELECT `column` FROM `table` WHERE POSITION('keyword' IN `filed`) position能够看作是locate的别名,功能跟locate同样
4.INSTR(str,‘substr’)方法 SELECT `column` FROM `table` WHERE INSTR(`field`, 'keyword')>0 5.CONTAINS(column,str)方法 SELECT `column` FROM `table` WHERE CONTAINS(`column`, 'keyword') 4.字符串精准匹配 如测试表中的数据所示,如果我们使用like模糊查询,%admin的查询结果会导致student字段不以admin结尾的数据都无法查出来,而使用%admin%则会导致admin1,admin12这种数据也被查出来。
为解决这种问题,需要使用到精准匹配的函数FIND_IN_SET(‘str’,column)。
1.默认函数 select * from test where find_in_set('admin',student); 查询结果:
目录
一、异常情况
1)查找元素本身不存在
2)元素的页面渲染跟不上速度
3)找到元素但不是最新的(常在首次进入页面刷新后出现的问题)
二、元素本身不存在异常
1)页面元素不存在
2)元素或在某个iframe里面
三、元素渲染跟不上速度
1)隐式等待
2)显示等待
3)循环等待
4)强制等待
四、找到元素但不是最新的
一、异常情况 出现element find error异常情况大概分为以下几种:
1)查找元素本身不存在 2)元素的页面渲染跟不上速度 3)找到元素但不是最新的(常在首次进入页面刷新后出现的问题) 针对第一种异常可能就是代码写的有问题或者页面元素不存在(或有可能要查找的元素在iframe框架中,需要先进入到对应的iframe才能找得到),后面两种就是需要我们做一些动作来等待页面加载。每种方法都有对应的解决方式,下面记录下这几张异常的解决方法。
二、元素本身不存在异常 出现此种异常有两个原因:
1)页面元素不存在 打开页面查看html中的元素及属性
2)元素或在某个iframe里面 需要先进入到对应的iframe中,才能找到对应元素。进入iframe的方法代码如下:
from selenium import webdriver # 使用class_name及id属性皆可定位 driver.switch_to.frame('name/id') 三、元素渲染跟不上速度 简单来讲就是页面加载太慢,导致元素加载不出来,代码在查找时找不到自然就会报错。对于这样及类似的问题,或只能使用等待加载的方法。
关于等待加载也有几种方法
1)隐式等待 from selenium import webdriver # 设置隐式等待时间为3s driver.implicitly_wait(3) 2)显示等待 from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as ec from selenium.webdriver.common.by import By # 等待元素可见 10s WebDriverWait(driver,10).until(ec.presence_of_element_located((By.ID,'code'))) # 等待元素可点击 10s WebDriverWait(driver,10).