深度学习pytorch训练代码模板(个人习惯) 来源:https://zhuanlan.zhihu.com/p/396666255
从参数定义,到网络模型定义,再到训练步骤,验证步骤,测试步骤,总结了一套较为直观的模板。目录如下:
导入包以及设置随机种子
以类的方式定义超参数
定义自己的模型
定义早停类(此步骤可以省略)
定义自己的数据集Dataset,DataLoader
实例化模型,设置loss,优化器等
开始训练以及调整lr
绘图
预测
一、导入包以及设置随机种子
import numpy as np import torch import torch.nn as nn import numpy as np import pandas as pd from torch.utils.data import DataLoader, Dataset from sklearn.model_selection import train_test_split import matplotlib.pyplot as plt import random seed = 42 torch.manual_seed(seed) np.random.seed(seed) random.seed(seed) 二、以类的方式定义超参数
class argparse(): pass args = argparse() args.epochs, args.learning_rate, args.patience = [30, 0.001, 4] args.hidden_size, args.input_size= [40, 30] args.
1.查看最近1000行,并实时更新 tailf error.log -n 1000 2.查看末尾1000行,不更新 cat error.log | tail -n 1000 3.查看头1000行,不更新 cat error.log | head -n 1000 4.根据关键字查询,只返回ThreadPoolExecutor相关行日志 cat error.log | grep 'ThreadPoolExecutor' 5.忽略大小写,返回关键词日志 grep -i 'http' error.log 6.查看时间段范围内日志 sed -n '/2022-07-26/,/2022-07-29/p' error.log
安装一个bluetooth man 进入终端: sudo apt-get install blueman 打开bluetooth manager,查看蓝牙设备的地址,记录下来 bluetoothctl pair [设备地址] connect [设备地址] 成功连接
《动手深度学习》2.5反向传播自动求导 反向传播理论推导pytorch代码实战初始定义基本量定义模型(构建计算图)保留一下训练前的预测值训练!!! 反向传播理论推导 从线性模型到多层神经网络,一点点理解反向传播机制
由于复杂网络涉及的权重过多,所以引入计算图和反向传播!
激活函数的引出:激活函数的存在是必要的!!!否则无论多少层的网络结构,一经化简合并就和单层网络效果是一样的!
forward和backward的一整套完整计算流程
最后,对最简单的线性模型进行完整计算过程演示
pytorch代码实战 pytorch里的数据类型tensor包含重要的两部分:data和grad。data是w,权重值;grad是loss对w的偏导值,或者说是梯度。 初始定义基本量 import torch x_data = [1.0,2.0,3.0] y_data = [2.0,4.0,6.0] w = torch.tensor([1.0]) w.requires_grad = True #因为默认的tensor不需要计算和保存grad 这里的 x_data,y_data 对应着3个样本(1.0,2.0),(2.0,4.0),(3.0,6.0)x.requires_grad_(True) 声明x是需要梯度的!在pytorch中,如果输入需要梯度,那么中间涉及的每一步参数的梯度都会被保存下来 定义模型(构建计算图) 训练自己每看到一个模型定义都能够把计算图给画出来!!! # 定义一个简单线性模型:y=x*w def forward(x): return x*w def loss(x,y): y_pred = forward(x) return (y_pred - y) ** 2 也就是构建了一个下图所示的计算图过程:
保留一下训练前的预测值 print("predict (before training)", 4, forward(4).item()) 训练!!! w = torch.tensor([1.0]) w.requires_grad = True #因为默认的tensor不需要计算和保存grad for epoch in range(100): for x, y in zip(x_data, y_data): l = loss(x, y)#这一步,计算loss其实就是在进行前馈运算,从头到loss走了一遭 l.
一、实验目的
1、了解VLAN原理
2、熟练掌握二层交换机VLAN的划分方法。
3、了解如何验证VLAN的划分。
二、应用环境
1、学校实验楼中有两个实验室位于同一个楼层,一个是计算机软件实验室,一个是多媒体实验室,两个实验室的信息端口都连接在一台交换机上。学校已经为实验楼分配了 固定的ip地址段,为了保证两个实验室的相对独立,就需要划分对应的VLAN,使交换机某些端口属于软件实验室,某些端口属于多媒体实验室,这样就能保证它们之间的数据互不干扰,也不影响各自的通信效率。
三、实验设备
1、神州数码DCN-CS6200交换机 1 台
2、PC机 1 台
3、交换机console线 1 根
4、直通网线 2 根
四、实验拓扑
使用一台交换机和两台PC机,还将其中的PC1作为控制台终端,使用console口配置方式;是两根网线分别将PC1和PC2连接到交换机的RJ-45接口上。
五、实验要求
1、使得vlan100的成员能够互相访问,vlan200的成员能够互相访问;vlan100和vlan200成员之间不能访问。
PC1、PC2的网络设置为:
2、PC1、PC2插在vlan100的成员端口1-8上,两台PC互相可以ping通。
3、PC1、PC2插艾vlan200的成员端口9-16上,两台PC互相可以ping通。
4、PC1插在vlan100的成员端口1-8上,PC2插在vlan200的成员端口9-16上,两台PC则能ping通。
六、实验步骤
第一步:交换机恢复出厂设置。
CS6200-28X-EI#set default !!清空当前配置 Are you sure? [Y/N] = y CS6200-28X-EI#write !!保存 Sep 15 20:00:19:000 2022 CS6200-28X-EI MODULE_CONFIG_SHELL/3/:Switch configuration has been set default! NULL(factory config) will be used as the startup-config file at the next time! CS6200-28X-EI#reload !!重启交换机 Process with reboot?
0 引子 组里新来研究生,常常在做小组报告时,不知所云。报告中slides 大段文字粘贴,报告没有重点
报告者没有理清思路,听众更是云里雾里。
故总结了一下,论文选择 及 阅读报告的内容提纲
1 论文选择范围 与自己研究主题相关的 A 类论文部分B类论文(这一类要筛选一下,在报告之前最好跟指导老师简单沟通一下,确认是否值得阅读报告) 2 组会报告的提纲要点 (1)研究问题: 介绍论文是为了解决什么样的研究主题(问题)。
(2)研究动机
阐述为什么要这个问题值得研究如果有Motivation Example,则结合示例阐述。 (3)作者提出的方法
方法框架总体介绍方法的各个 components 作用: 在整个方法框架中所起到的作用特色: 有哪些特别的地方 (4)实验设计
研究问题:
- 要说明 研究问题的 Motivation实验对象: 用的现成的数据集? 能否下载?自己构造数据集? 构造方法? 评测指标 评测指标含义,参考已有的指标?合理性论证?作者自己设计评测指标? 实验设置 数据集划分实验设计、步骤、参数设置(参数优化)方法(理由)实验环境 (5)实验结果
实验结果:
- 解释积极结果
- 解释负面结果(分析原因)
- (从不同的角度讨论)给出结论 (6)受到的启发
论文对你研究工作的启发:论文是否存在问题?怎么去解决?未来工作?
最近使用el-tabs组件遇到了一个问题:就是el-tabs中el-tab-pane是动态生成的,而且后续需要获取el-tab-pane中元素的ref,代码大概是下面的样子:
<el-tabs v-model="activeName" type="card" @tab-click="handleClick" > <el-tab-pane v-for="(item, index) in case_tabs" :label="item.name" :name="index.toString()" :key="index"> <TabList :ref="`tab${index}`"/> </el-tab-pane> </el-tabs> 这个使用场景是当切换tab时,要调用组件内部的的load方法。
handleClick(tab) { this.activeName = tab.index this.$refs[`tab${tab.index}`].load() } 看似没有毛病,但是点击切换时就报错了,提示this. r e f s [ ‘ t a b refs[`tab refs[‘tab{tab.index}`]是undefined。
这时就需要去搞明白这个ref到底是什么样的工作机制,vue官网查到以下内容:
ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
当 v-for 用于元素或组件的时候,引用信息将是包含 DOM 节点或组件实例的数组。
关于 ref 注册时间的重要说明:因为 ref 本身是作为渲染结果被创建的,在初始渲染的时候你不能访问它们 - 它们还不存在!$refs 也不是响应式的,因此你不应该试图用它在模板中做数据绑定。
可见,我们在使用v-for时应该把子组件的ref存放在一个数组中。
解决方案 <template> <el-tabs v-model="activeName" type="card" @tab-click="handleClick" > <el-tab-pane v-for="
本教程旨在说明如何基于pcl_recognition模块执行 3D 对象识别。具体而言,它解释了如何使用对应分组算法,以便将 3D 描述符匹配阶段之后获得的点对点对应关系集聚类到当前场景中存在的模型实例中。对于每个表示场景中可能的模型实例的聚类,对应分组算法还会输出转换矩阵,用于标识该模型在当前场景中的 6DOF 姿态估计。
#include <pcl/io/pcd_io.h> #include <pcl/point_cloud.h> #include <pcl/correspondence.h> #include <pcl/features/normal_3d_omp.h> #include <pcl/features/shot_omp.h> #include <pcl/features/board.h> #include <pcl/filters/uniform_sampling.h> #include <pcl/recognition/cg/hough_3d.h> #include <pcl/recognition/cg/geometric_consistency.h> #include <pcl/visualization/pcl_visualizer.h> #include <pcl/kdtree/kdtree_flann.h> #include <pcl/kdtree/impl/kdtree_flann.hpp> #include <pcl/common/transforms.h> #include <pcl/console/parse.h> typedef pcl::PointXYZRGBA PointType; typedef pcl::Normal NormalType; typedef pcl::ReferenceFrame RFType; typedef pcl::SHOT352 DescriptorType; std::string model_filename_; std::string scene_filename_; //Algorithm params bool show_keypoints_(false); bool show_correspondences_(false); bool use_cloud_resolution_(false); bool use_hough_(true); float model_ss_(0.01f); float scene_ss_(0.03f); float rf_rad_(0.015f); float descr_rad_(0.02f); float cg_size_(0.
首先是侧边栏根据不同的权限过滤,然后侧边栏能按照不同权限显示了。但是用户在url输入地址仍然能访问,所以需要鉴权
一.侧边栏过滤思路 1.通过路由的meta下的auth存储权限数组
const routes = [ { path: '/', redirect: isClient ? '/clientApp' : '/screen', meta: { title: '', auth: ['COLLECT_ADMIN', 'SECOND_CHECK', 'COLLECT', 'FIRST_CHECK', 'ADMIN', 'SURVEY_ADMIN'], icon: '', env: 'public', }, }, { path: '/Login', name: 'Login', component: () => import('../views/Login.vue'), meta: { title: '登录页', auth: ['COLLECT_ADMIN', 'SECOND_CHECK', 'COLLECT', 'FIRST_CHECK', 'ADMIN', 'SURVEY_ADMIN'], icon: '', env: 'public', }, }, { path: '/screen', name: 'Screen', component: () => import('../views/Screen'), meta: { title: '大屏', auth: ['COLLECT_ADMIN', 'SECOND_CHECK', 'COLLECT', 'FIRST_CHECK', 'ADMIN', 'SURVEY_ADMIN'], icon: '', env: 'web', }, }, { path: '/401', name: '401', component: () => import('.
目录 一、线性规划🎐例题🎐线性规划适用的典型赛题🎐如何用Matlab求解线性规划🎐lingo求解线性规划 二、非线性规划🎐线性规划适用的典型赛题🎐lingo求解非线性规划🎐Matlab求解 三、多目标规划🎐多目标规划基础实例🎐多目标规划适用的典型赛题🎐基于NSGA-II算法的gamultiobj函数求解多目标优化 线性规划,非线性规划,多目标规划都归于优化类模型 一、线性规划 🎐例题 张麻子既要攻碉楼又要追替身,他们一伙6人,总共1200发子弹;每有一人攻碉楼会给百姓带来40点士气值,每有一人追替身会给百姓带来30点士气值;攻碉楼每人需240发子弹,追替身每人需120发。
问攻碉楼和追替身各派几个人,能使百姓的士气值最大?
解析为:
注意:
线性规划就是在一组线性约束条件下,求线性目标函数的最大或最小值
"线性"意味着所有变量都是一次方
🎐线性规划适用的典型赛题 题目中提到"怎样安排/分配”"尽量多(少)” “最多(少)” "利润最大” “最合理” 等词;
生产安排:原材料、设备有限制,总利润最大
若生产两种机床,利润分别为XXX; A机器和B机器加工,有顺序要求,有不同损耗费用,不同的工作时间…;问题:怎样安排生产使得总利润最大?
投资收益:资产配置、组合投资、总收益最大(收益率、损失率可能不是线性了)
若总资金为M,有n种资产可以配置。每种资产的平均收益率…,风险损失率…,手续费…;
问题:设计组合投资方案,使得收益尽可能大(本质是多目标规划,可化简为一个目标的线性规划)
销售运输:产地、销地、产量、销量、运费,总运费最省
商品有m个产地和n个销地,需要从产地运到销地。各产地的产量…,各销地需求量…,由a产地运到b销地的运价xxx;问题:如何调运才能使总运费最省?
车辆安排:路线、起点终点、承载量、时间点、车次安排最合理(合理就是指最多/最少!)
不同种类的车辆有各自的承载量,工地各点之间要安排车辆运输。工地里有多条路线…满足用工需求的情况下…;问题:如何安排车辆能使产量尽可能大?
(注意:一般资料里所说的整数规划、0-1规划往往也默认为线性规划的特例)
🎐如何用Matlab求解线性规划 模型MATLAB求解: Linprog函数 注意:只能求最小值!
PS:matlab求线性规划要先把模型,弄出标准型。所以!线性规划嘛,都用lingo解。
求最大值:y的最大值等价于-y的最小值
x>=b,也等价于-x<=b
[x, fval] = linprog (f,A, b, Aeq, beq, Ib, ub)
f:目标函数的系数列向量
f = [-40; -30]
A:约束条件里的变量系数矩阵
b:约束条件里的常数量矩阵
Aeq:等式约束条件
beq:等式约束条件
lb:
ub: 已经在不等式约束里面写了就可以不写。
最后的到的x是一个矩阵。
✨若不存在不等式约束,用"[]”代替A和b: [x, fval ] = linprog (f,[],[], Aeq, beq, lb, ub)
说明:
(1)本篇博客内容:【前台,作家中心,查看粉丝列表,接口】;
目录
一:需求分析;
二:开发【前台,作家中心,查看粉丝列表,接口】;
1.在【api】接口工程的MyFansControllerApi接口中,定义一个接口;
2.在【user】用户服务的MyFansController类中,去实现这个接口;
3.在【user】用户服务的MyFansService接口中,定义一个分页查询粉丝列表的方法;
4.在【user】用户服务的MyFansServiceImpl类中,去实现分页查询粉丝列表的方法;
5.效果;
一:需求分析; 这儿说白了,就是去查询fans粉丝表;
二:开发【前台,作家中心,查看粉丝列表,接口】; 这个太简单了,自己直接就做了;
1.在【api】接口工程的MyFansControllerApi接口中,定义一个接口; /** * 分页查询粉丝列表 * @param writerId * @param page * @param pageSize * @return */ @ApiOperation(value = "分页查询粉丝列表", notes = "分页查询粉丝列表", httpMethod = "POST") @PostMapping("/queryAll") public GraceJSONResult list(@RequestParam String writerId, @RequestParam Integer page, @RequestParam Integer pageSize); 说明:
(1)需要和前端保持一致;
2.在【user】用户服务的MyFansController类中,去实现这个接口; /** * 分页查询粉丝列表 * @param writerId * @param page * @param pageSize * @return */ @Override public GraceJSONResult list(String writerId, Integer page, Integer pageSize) { //如果前端传的page为空,就给其一个默认值1; if (page == null) { page = COMMON_START_PAGE;//在BaseController中定义的常量; } //如果前端传的pageSize为空,就给其一个默认值10; if (pageSize == null) { pageSize = COMMON_PAGE_SIZE; } PagedGridResult pagedGridResult = myFansService.
点击关注,桓峰基因
桓峰基因公众号推出单细胞系列教程,有需要生信分析的老师可以联系我们!首选看下转录分析教程整理如下:
Topic 6. 克隆进化之 Canopy
Topic 7. 克隆进化之 Cardelino
Topic 8. 克隆进化之 RobustClone
SCS【1】今天开启单细胞之旅,述说单细胞测序的前世今生
SCS【2】单细胞转录组 之 cellranger
SCS【3】单细胞转录组数据 GEO 下载及读取
SCS【4】单细胞转录组数据可视化分析 (Seurat 4.0)
SCS【5】单细胞转录组数据可视化分析 (scater)
SCS【6】单细胞转录组之细胞类型自动注释 (SingleR)
SCS【7】单细胞转录组之轨迹分析 (Monocle 3) 聚类、分类和计数细胞
SCS【8】单细胞转录组之筛选标记基因 (Monocle 3)
SCS【9】单细胞转录组之构建细胞轨迹 (Monocle 3)
SCS【10】单细胞转录组之差异表达分析 (Monocle 3)
今天来说说单细胞转录组数据的细胞轨迹分析,学会这些分析结果,距离发文章就只差样本的选择了,有创新性的样本将成为文章的亮点,并不是分析内容了!
这期继续介绍 Monocle 3 软件包用于差异表达分析。
前 言 单细胞转录组测序(scRNA-seq)实验使我们能够发现新的细胞类型,并帮助我们了解它们是如何在发育过程中产生的。Monocle 3包提供了一个分析单细胞基因表达实验的工具包。
Monocle 3可以执行三种主要类型的分析:
聚类、分类和计数细胞。单细胞RNA-Seq实验允许发现新的(可能是罕见的)细胞亚型。
构建单细胞轨迹。在发育、疾病和整个生命过程中,细胞从一种状态过渡到另一种状态。Monocle 3可以发现这些转变。
差异表达分析。对新细胞类型和状态的描述,首先要与其他更容易理解的细胞进行比较。Monocle 3包括一个复杂的,但易于使用的表达系统。
工作流程图如下:
差异基因表达分析是RNA-Seq实验中的一项常见任务。Monocle可以帮助你找到细胞组之间表达差异的基因,并评估这些变化的统计意义。Monocle 3包含一个强大的系统,可以找到在不同类型的细胞中不同的基因,在不同的发育时间点收集的基因,或者以不同的方式被干扰的基因。
在Monocle中有两种差异分析方法:
回归分析:使用fit_models(),可以评估每个基因是否依赖于诸如时间、治疗等变量。
图自相关分析:使用 graph_test(),可以找到沿着轨迹或在簇之间变化的基因。
Monocle还具有寻找差异表达基因的协同调节模块的专门功能。Monocle还允许交互式地查询轨迹的特定 cluster或 partition (例如分支点),以寻找其中变化的基因。
数据读取 expression_matrix <- readRDS("
作者:vivo 互联网服务器团队- Chen Dongxing、Li Haoxuan、Chen Jinxia
随着业务的日渐复杂,性能优化俨然成为了每一位技术人的必修课。性能优化从何着手?如何从问题表象定位到性能瓶颈?如何验证优化措施是否有效?本文将介绍分享 vivo push 推荐项目中的性能调优实践,希望给大家提供一些借鉴和参考。
一、背景介绍
在 Push 推荐中,线上服务从 Kafka 接收需要触达用户的事件,之后为这些目标用户选出最合适的文章进行推送。服务由 Java 开发,CPU 密集计算型。
随着业务的不断发展,请求并发及模型计算量越来越大,导致工程上遇到了性能瓶颈,Kafka 消费出现严重的积压现象,无法及时完成目标用户的分发,业务增长诉求得不到满足,故亟需进行性能专项优化。
二、优化衡量指标和思路
我们的性能衡量指标是吞吐量 TPS ,由经典公式 TPS = 并发数 / 平均响应时间RT 可以知道,若需提高 TPS,可以有 2 种方式:
提高并发数,比如提升单机的并行线程数,或者横向扩容机器数;
降低平均响应时间 RT,包括应用线程(业务逻辑)执行时间,以及 JVM 本身的 GC 耗时。
实际情况中,我们的机器 CPU 利用率已经很高,达到 80% 以上,提升单机并发数的预期收益有限,故把主要精力投入到降低 RT 上。
下面将从 热点代码 和 JVM GC 两个方面进行详解,我们如何分析定位到性能瓶颈点,并使用 3 招将吞吐量提升 100% 。
三、热点代码优化篇
如何快速找到应用中最耗时的热点代码呢?借助阿里巴巴开源的 arthas 工具,我们获取到线上服务的 CPU 火焰图。
火焰图说明:火焰图是基于 perf 结果产生的 SVG 图片,用来展示 CPU 的调用栈。
1 描述 给出4个正整数,使用加、减、乘、除4种运算以及括号把4个数连接起来得到一个结果等于24的表达式。
注:这里加、减、乘、除以及括号的运算结果和运算优先级跟平常定义一致。
例如,对于5,5,5,1,可知 5× (5-1/5) = 24。又如,对于 1,1,4,2 无论如何都不能得到24
1.1 输入格式 在代码中的输入部分输入4个正整数。
1.2 输出格式 对于每一组测试数据,如果可以得到24,输出"YES"其算法;否则输出“NO”。
2 大致思路 将四个数字进行全排列,在他们之间添加运算符号,最后将数字和操作符进行拼接运算。
运算符我们需要进行排列组合,因为只有四个数字,所以只需要三个运算符,而且算法符可能会重复,比如三个都是+。
再遍历四个数字的全排列,对每一组数字而言,遍历所有组合的操作符。最后将数字和操作符进行拼接运算,就可以得到最终结果了。
3 知识点补充 1、首先我们对所有数字进行去全排列,这里我们使用 itertools.permutations 来帮助我们完成。
iertools.permutations 用法演示
import itertools a = int(input("请输入第1个数字:")) b = int(input("请输入第2个数字:")) c = int(input("请输入第3个数字:")) d = int(input("请输入第4个数字:")) my_list = [a, b, c, d] result = [c for c in itertools.permutations(my_list, 4)] for i, r in enumerate(result): if i % 4 == 0: print() print(r, end="
说明:
(1)本篇博客内容:【显示粉丝数、关注数】;
目录
一:需求分析;
二:实现【显示粉丝数、关注数】功能;
1.在AppUserVO实体类中,增加“粉丝数、关注数”两个属性;
2.在UserController类中,去完善【获得用户基本信息,接口】;
3.效果;
一:需求分析; 查看前端源码
……………………………………………………
即,这儿前端在处理“显示粉丝数、关注数”的逻辑,和在【31:第三章:开发通行证服务:14:开发【获得用户基本信息,接口】;】中的处理方式是一样的;
我们在这儿需要做的就是,完善一下【获取用户基本信息,接口】;让其,在获取用户基本信息的时候,增加对“粉丝数、关注数”的获取;
二:实现【显示粉丝数、关注数】功能; 1.在AppUserVO实体类中,增加“粉丝数、关注数”两个属性; 说明:
(1)这两个属性名别瞎写,需要和前端的需求保持一致;
2.在UserController类中,去完善【获得用户基本信息,接口】; 说明:
(1)在BaseController中,创建了一个共有方法:根据key,尝试从Redis中获取值;
/** * 工具方法:添加了一点附加逻辑,根据key,从Redis中获取值:这儿具体是,获取粉丝数或关注数 * @param key * @return */ public Integer getCountsFromRedis(String key) { //根据key,尝试从Redis中获取值; String countsStr = redisOperator.get(key); //很显然,如果一个用户是刚刚注册的,那么该用户不曾有过“关注别人,被比人关注”的操作,自然在Redis中不会有该用户的关注数或粉丝数信息 if (StringUtils.isBlank(countsStr)) { countsStr = "0"; } return Integer.valueOf(countsStr); } (2)逻辑分析:
3.效果;
ST7789-TFT屏幕驱动 & 整理有stm32/51单片机/arduino等驱动代码 前言关于ST7789stm32驱动引脚接线代码移植 文件复制 端口修改 显示函数 中文汉字数组 图片 其他单片机驱动51单片机arduino/ESP32 总结 前言 不久前我们收到用户反馈问题中,多次反馈各种不同型号的屏幕驱动不起来,从0开始编写代码花费大量时间,也有不少初次学习驱动屏幕代码编写经验过少等问题,为此我们决定以文章的形式发布到CSDN来分享相应的一些经验以及收集整理好的资料,希望可以帮助用户更加简单的学习或快速移植代码进行项目开发。
后续我们将陆续分享有关ST7789、GC9A01、ST7735、ILI9341等驱动IC的屏幕驱动案例。
还是老样子需要整理好的代码可以在评论区留言或私信邮箱!
关于ST7789 市面采用ST7789驱动IC的屏幕不算少见,本人有幸使用过的屏幕中有一款1.3寸和一款1.54寸的屏幕驱动芯片为ST7789,两者的分辨率均为240x240,网上搜集加上自己编写以及移植整理有stm32f10x、stm32f407、arduino、stc89c516、ESP32等单片机代码,需要整理好的代码可以在评论区留言或私信邮箱!
综合了解并观察屏幕一下的一些参数之后开始进行驱动。
硬件接口使用的 2.54mm 间距的排针接口,这使用杜邦线进行连接,需要设计到自己的PCB上高度也是刚好匹配上面的铜柱做定位使用的。
ST7789参数供电电压3.3~5.5V驱动ICST7789分辨率240x240尺寸1.3 / 1.54寸驱动接口4线SPI 产商在屏幕设计上添加了3.3V稳压芯片以及电平转换芯片,使得这款原本3.3V供电的裸屏可以兼容5V和3.3V的单片机,这也意味着arduino和51单片机的用户也可以驱动这款屏幕了,虽然51单片机性能很一般但总比不能驱动的好。
最后了解各个引脚功能之后就可以开始进行驱动
引脚名称引脚功能VCC电源正,3.3 - 5V,需要与通信电平一致GND电源负,地CS片选,低电平使能RST复位,低电平使能DC数据/命令选择,低电平命令,高电平数据SDASPI数据输入端口SCLSPI时钟信号输入端口BLK背光,悬空使能接地关闭,默认上拉至3.3V stm32驱动 引脚接线 代码方面先按照下表接好线烧录程序之后再对代码移植的关键部分进行说明
stm32f10xST77893V3VINGNDGNDCSPB6RSTPA6DCPA7SDAPA4SCLPA5BLKPB7 BLK背光引脚不用可以悬空不接
默认的代码烧录进行之后显示上面图片中大大的 优信电子logo,先把示例代码驱动起来,如果示例代码驱动不起来先检查一下接线供电方面的问题,不然后面代码改了半天没有用找问题就和我刚驱动的时候一样头皮发麻。
驱动成功之后用户可以开始移植代码。
代码移植 文件复制 将 lcd、lcd_init的C文件和h文件复制到自己的工程里面,这四个文件包含屏幕初始化以及驱动画点划线显示文字图像的代码。
另外还有两个文件为image.h和lcdfont.h,这两个文件分别存储显示图片数组与显示文字数组。
复制到自己工程中编译后会报错,因为缺少了pbdata.h中的毫秒级延时函数,可以把原工程中的ms延时函数复制过来也可以使用自己编写的,名称与下面的相同即可
void delay_ms(u16 a) 添加好文件到工程里面之后再次编译一般不会报错,如果仍然报错就只能看具体报错信息去修改了
和上面的接线不变,编写下面主函数先进行测试
int main(void) { LCD_Init(); LCD_Fill(0,0,LCD_W,LCD_H,WHITE); //填充为白色背景色 while(1) { LCD_ShowPicture(0,0,LCD_W,LCD_H,YXDZ_logo); //显示一张图片 } } 需要用户修改的接口一般有一下几个点
端口修改 lcdfont.h文件中包含对使用引脚的宏定义,修改其中的GPIO以及引脚即可修改使用的端口
//-----------------LCD端口定义---------------- #define LCD_SCLK_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_5)//SCL=SCLK #define LCD_SCLK_Set() GPIO_SetBits(GPIOA,GPIO_Pin_5) #define LCD_MOSI_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_4)//SDA=MOSI #define LCD_MOSI_Set() GPIO_SetBits(GPIOA,GPIO_Pin_4) #define LCD_RES_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_6)//RES #define LCD_RES_Set() GPIO_SetBits(GPIOA,GPIO_Pin_6) #define LCD_DC_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_7)//DC #define LCD_DC_Set() GPIO_SetBits(GPIOA,GPIO_Pin_7) #define LCD_CS_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_6)//CS #define LCD_CS_Set() GPIO_SetBits(GPIOB,GPIO_Pin_6) #define LCD_BLK_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_7)//BLK #define LCD_BLK_Set() GPIO_SetBits(GPIOB,GPIO_Pin_7) 但值得注意的是仅仅修改这里的宏定义是没办法使用的,在lcdfont.
将需要压缩的图片绘制在canvas,然后利用微信提供的canvasToTempFilePath()方法保存成一个图片,保存时可以根据所需指定生成图片的质量。
通过canvas配合这个接口,可以实现两种图片的压缩:1.声明好图片高度/宽度临界值,压缩图片的宽高;2.不改变图片的宽高,只改变图片的质量;
首先页面需要声明一个canvas画布:其中cWidth和cHeight分别是渲染的图片高度和宽度,根据上传的图片信息获取;-9999px是为了使画布偏离屏幕;
<canvas canvas-id="canvas" class="my-canvas" :style="{width:cWidth+'px',height:cHeight+'px'}"> </canvas> .canvas { position: absolute; left: -9999px; top: -9999px } 1.通过修改图片的宽高来压缩图片 通过修改宽高来压缩图片的原理是获取图片的宽高后(res.width/res.height),判断是否满足自己的最高宽/高度要求,如果不满足,则根据比例缩小,直到获取到满足要求的宽高,将其渲染到页面上,这里加一个setTimeout是因为canvas绘制需要一定的时间,需要等canvas绘制完成后将其通过canvasToTempFilePath方法导出;
wx.canvasToTempFilePath(Object object, Object this) | 微信开放文档
通过这种方法有两个弊端:
1.无法完全确定图片的高度,而且在一定情况下两张图片宽高差距比较大(宽高2049px和宽高2047px的两张图片),解决办法:
1.1 减小ratio的初始值,同时减小增长间隔:初始值1.2,增长间隔0.2(ratio += 0.2);
1.2 完全固定图片的高度或者宽度,等比例调整至固定的大小,弊端就是小图片会被拉长;
2.无法实时的判断图片是否渲染完毕(目前我是没找到方法,欢迎指导),尤其是渲染的图片宽高特别大的时候会特别耗时,所设置的延迟可能会导致导出的图片不全/拉伸等情况,解决办法:
2.1 这种修改图片的宽高方法,可以找到一个最大宽高所需渲染的时间,比这个宽高小的图片在当前时间内一定会渲染完成;如果是第二种方法,修改图片的质量,则需要预留一个比较充足的时间,但是特别大的图片可能还会有一样的问题。
async imgCompress(tempFilePaths, index) { let _this = this return new Promise((resolve, reject) => { wx.getImageInfo({ src: tempFilePaths, success: function(res) { let ratio = 2; let canvasWidth = res.width let canvasHeight = res.height while (canvasWidth > 1024 || canvasHeight > 1024) { canvasWidth = Math.
说明:
(1)本篇博客开发的内容:【查看是否已关注某用户,接口】、【关注,接口】、【取关,接口】;
(2)本篇博客就一个点:对于那些需要频繁写的小数据,也可以存到Redis中,直接在Redis中增改;
目录
一:粉丝功能,技术选择:利用Redis的"累加"、"累减"来统计用户的关注数和粉丝数;(从而消除使用聚合函数操作数据,给数据库带来的压力)
二:开发【假如当前登录用户是A,当A查看B的主页时,查询A是否已经关注B,接口】;
1.该部分,内容说明;
2.开发【查询当前登录用户,是否已经关注当前查看页面的作家,接口】;
(1)在【api】接口工程中,创建MyFansControllerApi接口,并定义【查询当前登录用户,是否已经关注当前查看页面的作家,接口】;
(2)在【user】用户服务中,创建MyFansController类,去实现【查询当前登录用户,是否已经关注当前查看页面的作家,接口】;
(3)在【user】用户服务中,创建MyFansService接口,定义一个查询当前登录用户是否关注的方法;然后,创建MyFansServiceImpl实现类,去实现这个方法;
3.效果;
三:开发【A用户关注B用户,A的关注数+1,B的粉丝数+1,接口】;
1.在【api】接口工程的MyFansControllerApi接口,定义【A用户关注B用户,A的关注数+1,B的粉丝数+1,接口】; 2.在【user】用户服务的MyFansController类中,去实现【A用户关注B用户,A的关注数数+1,B的粉丝数+1,接口】;
3.在【user】用户服务的MyFansService接口,定义一个方法;然后,在MyFansServiceImpl实现类,去实现这个方法;
4.效果;
四:开发【A用户取关B用户,A的关注数-1,B的粉丝数-1,接口】; 1.在【api】接口工程的MyFansControllerApi接口,定义【A用户取关B用户,A的关注数-1,B的粉丝数-1,接口】; 2.在【user】用户服务的MyFansController类中,去实现【A用户取关B用户,A的关注数-1,B的粉丝数-1,接口】;
3.在【user】用户服务的MyFansService接口,定义一个方法;然后,在MyFansServiceImpl实现类,去实现这个方法;
4.效果;
附加:【关注,接口】和【取关,接口】都需要,“用户登录、并且用户是激活状态”才能操作;所以,在【api】接口工程的InterceptorConfig类中,对其进行配置;
一:粉丝功能,技术选择:利用Redis的"累加"、"累减"来统计用户的关注数和粉丝数;(从而消除使用聚合函数操作数据,给数据库带来的压力) 已知,在MariaDB中有一个fans表;
(1)统计某个用户的关注数和粉丝数,直接的想法是count()的方式去查询fans表;
(2)但是,由于前台门户端的并发量将会很高;也将会有很多人查看别人的个人展示页;那么,就会频繁的count()查询fans表;
(3)而这是不好的(尤其是数据量很大的时候),数据库的压力会很大;(在【附加:数据的聚合函数,会给数据库造成很大压力;】中,对此进行了介绍)
(4)所以,针对这个具体的业务而言,我们会利用Redis来优化,减轻数据库压力;
(1)对于Redis来说,前面我们使用Redis存放过热点数据;即,都是redis这款nosql数据库,作为缓存来使用;
(2)但是,Redis本身就是一款nosql;我们,自然可以把其当成数据库来使用;
(3)某个用户的【关注数】、【粉丝数】的累加和类减,可以通过Redis来实现;(Redis具体处理任务的时候,是单线程的,所以其实安全的)
(4)Redis中,底层有INCR(对某个值加1)和DECR(对某个值减1)两个命令;
● 比如用户1001,可以在Redis中创建一个【1001:fans,fansNum】数据,记录用户的粉丝数;
● 如果有人关注了1001,那么这个值就加1;
● 如果有人取关了1001,那么这个值就减1;
● 用户的关注数,同理;
二:开发【假如当前登录用户是A,当A查看B的主页时,查询A是否已经关注B,接口】; 1.该部分,内容说明; 而【我是慕课网】是否关注【慕小健】,是需要去数据库表中查询的;
2.开发【查询当前登录用户,是否已经关注当前查看页面的作家,接口】; (1)在【api】接口工程中,创建MyFansControllerApi接口,并定义【查询当前登录用户,是否已经关注当前查看页面的作家,接口】; package com.imooc.api.controller.user; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @Api(value = "粉丝管理",tags = {"粉丝管理功能的controller"}) @RequestMapping("fans") //设置路由,这个是需要前后端约定好的; public interface MyFansControllerApi { /** * 假如当前登录用户是A,当A查看B的主页时,查询A是否已经关注B; * @param writerId * @param fanId * @return */ @ApiOperation(value = "
准备 Ubuntu云服务器(已安装宝塔),并解析一个域名主机记录Lsky Pro官方仓库下载lsky-pro.zipPicgo官方仓库下载PicGo-Setup-x.x.x-x64.exe并安装阅读Lsky Pro官方文档 关于Lsky部署官方文档很清晰,本篇文章重在说明如何部署Picgo(token申请和删除文档里没有过多介绍)以及面板邮箱提醒等
Lsky Pro环境准备 按官方文档中Lsky Pro 安装要求,在宝塔面板软件商店->已安装->MySQL x.x.x->设置->切换版本,确保MySQL5.7以上。另外PHP默认5.6,所以还需要安装PHP >= 8.0.2(如果旧版还有其它部署,考虑兼容,可以保留),关于官方文档要求的PHP扩展和函数,等报了错知道具体是哪再回来配置
安装Lsky Pro 1.在宝塔面板中添加新站点,数据库账号密码在导航栏数据库中查看
2.上传lsky-pro.zip到服务器Img_Bed目录下,设置目录权限777并应用到子目录,在ssh工具中解压缩,解压完成后再设置一次Img_Bed目录权限,修改新解压出的文件权限
cd /www/wwwroot/Img_Bed unzip lsky-pro-2.0.4.zip 3.设置网站根目录为public,添加伪静态
location / { try_files $uri $uri/ /index.php?$query_string; } 4.输入网站域名进入安装界面,此时跳出检测,在软件商店->已安装->PHP x.x->设置中根据需求安装扩展、删除禁用函数,然后再次进入,填写对应信息,数据库信息在宝塔面板导航的数据库中查看
5.安装成功后,再次输入域名,登录账号,接下来做一些必要的设置。左侧导航栏->系统设置,通用备案号如果有就填,控制关闭注册和游客上传功能,私人图床省的被别人滥用。邮件配置这个很重要,用于密码找回之类,以QQ邮箱为例,打开SMTP服务,申请授权码
其它配置就是配额相关的,根据自己需求配置
配置Picgo Picgo,既然搭建私有图床,一定用过其它服务商,所以这里不难,只是token官方阐述不多
1.申请token,方法很多,具体字段说明参考面板导航栏中接口,这里说两种
# 申请token命令二选一,删除token不会curl,所以就需要第二种办法借助站长工具 curl --location --request POST 'http://域名/api/v1/tokens' --form 'email="邮箱"' --form 'password="密码"' curl -d "Accept=application/json&email=邮箱&password=密码" http://域名/api/v1/tokens 站长工具或Postman添加token
删除token
2.配置picgo,下载插件lankong(源自picgo-plugin-lankong),Server即域名,token格式为Bearer空格token,Ignore certificate忽略证书,如果不能上传就勾选此项忽略证书,Sync Delete勾选表示picgo中的相册删除后图床同步删除
3.上传测试
最后推荐给图床域名申请一个SSL证书,因为有的浏览器不支持无证书的域名,如果链接可以访问但个人网站中无法插入,那就申请一个证书解决博客照片无法展示。兰空不支持全选相册,但有时候需要批量转移图片,macos上 command+a ,windows 上 alt+a,Issue #493
开发直播类的网页应用时,往往需要在开播前检测摄像头和麦克风是否正常,本文介绍一下浏览器如何获取到可用的摄像头和麦克风设备列表。
媒体接口 mediaDevices.getUserMedia()mediaDevices.enumerateDevices() 需要用到上面两个媒体接口,getUserMedia()用于获取用户授权,enumerateDevices()用于获取可用设备列表。
代码实现 async function openUserMedia(e) { // 1. 获取到设备授权 await navigator.mediaDevices.getUserMedia({video: true, audio: true}); // 2. 获取设备列表 navigator.mediaDevices.enumerateDevices() .then(function(devices) { devices.forEach(function(device) { console.log(device.kind + ": " + device.label + " id = " + device.deviceId); }); }) .catch(function(err) { console.log(err.name + ": " + err.message); }); } openUserMedia() 如果有一个或多个 MediaStream 处于活动状态或者获得了持久授权,将会输出类似下面的内容:
audioinput: 默认 - MacBook Air麦克风 (Built-in) id = default audioinput: MacBook Air麦克风 (Built-in) id = 343f8207e0b9ebc3f9a98cde134d2818e64b2141b3bd087c58974c727bdca8c0 videoinput: FaceTime HD Camera id = 5ce24d4798ba56b830bc8adc4bcc7171dbe0fcca481f739606190492b21a1e21 videoinput: OBS Virtual Camera (m-de:vice) id = 495bd88129048451bf9b0c5c9342f298c55fdaedf91b3cfe0470a4cbc36e4d26 audiooutput: 默认 - MacBook Air扬声器 (Built-in) id = default audiooutput: MSI PAG271P (HDMI) id = c20fbe0e2317c5f754d7e334acfeee6b39e7cd64fd37a3ed536142a7ec64f296 audiooutput: MacBook Air扬声器 (Built-in) id = cea14bbd0ab3b96fd22d84941c63aac1c6de60646744efa2d5bd20fa566b7600 可以看到有音频输入、音频输出、视频输入设备。
转自:
Java.lang.Class类 isAnnotationPresent()方法有什么功能呢?
下文讲述Class类中的isAnnotationPresent()方法的功能,如下所示:
isAnnotationPresent()方法的功能
java.lang.Class.isAnnotationPresent()方法的功能
用于检查对象是否存在指定注解
当存在指定注解时,则返回True,否则返回False
isAnnotationPresent()方法的语法
语法 public boolean isAnnotationPresent(Class<T> annotationClass) 参数 annotationClass:待获取注解的类型 返回值 当符合注解类型,则返回true,否则返回false 例:
isAnnotationPresent()方法的示例分享
package com.java.other; import org.junit.Test; public class other { /** * java265.com java.lang.Class 测试示例分享 * * @throws Exception * */ @Test public void test() throws Exception { Class c = Class.forName("java.util.HashMap"); Class c2 = Class.forName("org.springframework.web.bind.annotation.Mapping"); Class c3 = Class.forName("java.lang.annotation.Target"); System.out.println(c2.isAnnotationPresent(c2)); System.out.println(c2.isAnnotationPresent(c3)); } } -------运行以上代码,将输出以下信息----- false true
关于理论部分我看的是b站“霹雳吧啦Wz”的SSD理论讲解,作为入门小白表示能听懂,需要的同学可以自行观看
目录
1.训练环境
2.训练步骤
1.训练环境 我的环境是win11+anaconda+python3.6.13+pytorch1.10.2+cuda11.6
2.训练步骤 (1)下载SSD源码
可到github进行下载
GitHub - amdegroot/ssd.pytorch: A PyTorch Implementation of Single Shot MultiBox Detector
(2)下载模型文件
VGG16_reducedfc.pth预训练模型下载地址:https://s3.amazonaws.com/amdegroot-models/vgg16_reducedfc.pth
将下载的模型文件放置于ssd源码目录中 wights/vgg16_reducedfc.pth
(3)数据集准备
与大多数训练模型一样,ssd支持的训练格式为VOC和coco,这里采用voc2007作为演示,制作自己的数据集以及labimg的使用可自行观看yolo数据集标注软件安装+使用流程_道人兄的博客-CSDN博客_yolo数据集标注工具
voc2007的具体下载方式我也不多赘述,网络上百度也有,或者直接看我之前写的也有提到使用Faster—RCNN训练数据集流程(学习记录)_道人兄的博客-CSDN博客
将下载后的voc2007数据集放置于./data/VOCdevkit/中
然后到ssd.pytorch-master/data/中的voc0712.py进行修改其中的VOC_ROOT = osp.join(HOME, "data/VOCdevkit/"),他这里的HOME老是读取我的C盘位置,所以一直报错,我直接把数据集的绝对路径写上去了就没报错
将 voc0712.py文件中VOCDetection类的__init__函数,将image_sets修改为[('2007', 'train'), ('2007', 'val'),('2007','test')],修改后的结果如下。
def __init__(self, root, image_sets=[('2007', 'train'), ('2007', 'val'),('2007','test')], transform=None, target_transform=VOCAnnotationTransform(), dataset_name='VOC0712'): 其中如果是训练自己的数据集,记得修改voc0712.py文件中的VOC_CLASSES 变量。例如,将VOC_CLASSES修改为person类,注意如果只有一类则需要加方括号,修改后的结果如下。
VOC_CLASSES = [('person') 如果训练自己的数据集,还需要修改config.py文件中的voc字典变量。将其中的num_classes修改为2(以person为例)(背景类+你训练集的种类个数),第一次调试时可以将max_iter调小至1000,修改后的结果如下。
voc = { 'num_classes': 2, 'lr_steps': (80000, 100000, 120000), 'max_iter': 1000, 'feature_maps': [38, 19, 10, 5, 3, 1], 'min_dim': 300, 'steps': [8, 16, 32, 64, 100, 300], 'min_sizes': [30, 60, 111, 162, 213, 264], 'max_sizes': [60, 111, 162, 213, 264, 315], 'aspect_ratios': [[2], [2, 3], [2, 3], [2, 3], [2], [2]], 'variance': [0.
1、CreateConnectionThread 线程 1.1 线程创建 Druid连接池运行后,该线程大部分情况下都处于WAITING状态,通过 jstack -l PID 查看。
protected void createAndStartCreatorThread() { if (createScheduler == null) { String threadName = "Druid-ConnectionPool-Create-" + System.identityHashCode(this); //创建线程并启动 createConnectionThread = new CreateConnectionThread(threadName); createConnectionThread.start(); return; } initedLatch.countDown(); } 1.2 执行过程 public void run() { //利用循环,获取连接 for (;;) { try { //获取锁,可响应中断 lock.lockInterruptibly(); } catch (InterruptedException e2) { break; } try { boolean emptyWait = true; ... //判断是否能够创建连接,否则通过Condition条件锁将线程挂起 if (emptyWait) { // 必须存在线程等待,才创建连接 if (poolingCount >= notEmptyWaitThreadCount //等待的连接数大于线程池连接数,才创建 && (!
go test单元测试 目录 go test单元测试基本介绍细节介绍综合案例 基本介绍 go语言中自带有一个轻量级测试框架testing和自带的go test命令来实现单元测试和性能测试,testing框架和其他语言中的测试框架类似,可以基于这个框架写针对的相应函数的测试用例,也可以基于该框架写相应的压力测试用例。通过单元测试,可以解决如下问题:
1.确保每个函数可以运行,并且保证结果的正确性
2.确保写出的代码性能较好
3.单元测试能及时的发现程序设计或实现的逻辑错误,使问题即使暴露,便于问题的定位解决,而性能测试的重点在于发现程序设计上的一些问题,让程序能够在高并发的情况下还能保持稳定。
细节介绍 testing框架会自动导入xxx_test的文件,并且自动调用TestXxx的函数,其中函数名必须时大驼峰命名法。例如TestAdd()要将测试文件放在被测试的包相同的包内,测试文件将被排除在正常程序包外,但在运行go test命令时将包含测试文件通常情况TestXxx函数的参数是*testing.T,其中type T包含:
func (*T) Cleanup
Cleanup 注册要在测试(或子测试)及其所有子测试完成时调用的函数。清理函数将按上次添加、先调用的顺序调用。
func (*T) Deadline
截止时间报告测试二进制文件将超过 -timeout 标志指定的超时的时间。
如果 -timeout 标志指示“无超时”(0),则 ok 结果为假。
func (*T) Error
错误等效于“日志”,后跟“失败”。
func (*T) Errorf
错误 f 等效于 Logf 后跟失败。
func (*T) Fail
Fail 将函数标记为已失败,但继续执行。
func (*T) FailNow
FailNow 将函数标记为已失败,并通过调用运行时停止其执行。Goexit(然后运行当前gorutine中的所有延迟调用)。执行将在下一个测试或基准测试中继续。FailNow 必须从运行测试或基准测试函数的量程中调用,而不是从测试期间创建的其他量程调用。调用 FailNow 并不能阻止那些其他的gorutine。
func (*T) Failed
失败报告函数是否失败。
func (*T) Fatal
致命等同于日志,后跟失败。
func (*T) Fatalf
相当于log,后跟失败。
func (*T) Log
我们都知道,电脑可以划分多个区域来存储数据,例如C盘、D盘、E盘、F盘等,而不论是存储在哪个磁盘,都容易出现文件丢失的问题,那么电脑e盘文件夹删除了怎么恢复呢?下面小编分享一些方法,一起来看下吧!
方法一:撤销恢复
电脑e盘文件夹删除后可以采用马上撤销恢复方法。例如删除某个文件夹以后,在没有任何其他操作的情况下,在删除文件夹界面的空白位置使用鼠标右击,弹出“撤销删除”的选项,点击它,或者直接按ctrl+z撤销删除快捷方式,即可把不小心删除的文件夹恢复回来。
方法二:回收站恢复
删除文件夹以后如果还没有把回收站里面的数据全部清空或者删除,可以打开电脑桌面上的回收站,随后找到被自己删掉了的文件夹,右键单击这个文件夹选择还原,这样就能在原先的那个位置找到以前删掉了的文件夹了。
方法三:软件恢复
不论是e盘文件夹被永久删除,还是被回收站清空了,在没有备份数据的情况下,都能够尝试使用专业的数据恢复软件进行恢复,但是使用的前提是需要恢复的文件夹没有被覆盖掉,因此为了提高文件夹恢复率,我们应该尽快使用数据恢复软件来完成恢复,下面以云骑士数据恢复软件为例进行操作:
双击打开电脑上已经安装好的云骑士数据恢复软件,选择需要的恢复模式。
这里以场景模式下的误删除文件为例,选择需要恢复数据所在的位置,这里直接勾选“E盘”,并点击“开始扫描”。
等待软件扫描完成之后,可以在路径或已删除下找到所需的文件夹,选中文件夹以后在右侧会显示文件夹里的所有文件。
确认找到自己需要恢复的文件夹勾选后,点击软件右下角的“立即恢复”按钮,将其恢复到E盘以外的磁盘即可。
总结
以上就是关于删掉的e盘文件夹怎么恢复的问题,小编就为大家分享到这里了,如果您在使用电脑的时候也遇到类似的问题,建议您可以参照上述方法手动试试。
typora无法使用的解决方案 第一步:按Windows+R打开运行窗口,在输入框输入regedit,打开注册表管理器。
第二步:打开注册表,按以下路径展开
计算机\HKEY_CURRENT_USER\Software\Typora
第三步:在Typora上点右键,点权限选项,选择Administrtors,再把底下权限全部设置为拒绝即可。
必须选择Administrtors
前言
作者简介:不知名白帽,网络安全学习者。
博客主页:https://blog.csdn.net/m0_63127854?type=blog
Upload-labs专栏:https://blog.csdn.net/m0_63127854/category_11850783.html
网络安全交流社区:https://bbs.csdn.net/forums/angluoanquan
练习网站:upload-labs
注意: 能运行<?php phpinfo();?>
就能运行<?php eval($_POST['cmd'])?>一句话木马
本文使用<?php phpinfo();?>主要是为了简便
知识点 $_FILES[表单提交过来的name]
[name]:获取到的文件名
[type]: 获取到的文件类型(MIMETYPE)
[tmp_name]:文件临时存放的路径
[error]: 上传文件报错信息(为空则上传成功)
[size]:上传文件的大小
Move_uploaded_file(需要移动的文件,要移动到的位置)
Strrchr(指定字符串,匹配的字符) --指针指到指定的字符的位置,取之后的值
Trim() --去除字符串中的前后空格
Rtrim() --去除右空格
Ltrim() --去除左空格
Strtolower() --将字符串转为小写
Str_ireplace --(被转换的字符串,替换成的字符串,需要查找的字符串)
在需要查找的字符串中查找需要被替换的字符串,替换为指定的字符串
Pass-07 代码: $is_upload = false; $msg = null; if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini"); $file_name = $_FILES['upload_file']['name']; $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); //转换为小写 $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA if (!
该笔记使用 Python 3.9.12
简介 Django 是一个由 Python 编写的一个开放源代码的 Web 应用框架,具有强大的数据库功能和强大的后台功能
安装 Django 在终端中键入下面命令安装:
$ pip install Django ··· ··· ··· Installing collected packages: sqlparse, asgiref, Django Successfully installed Django-4.1.1 asgiref-3.5.2 sqlparse-0.4.2 查看当前 Django 版本:
$ django-admin --version 4.1.1 安装完成 Django 后,就可以开始使用管理工具 django-admin 了
$ django-admin Type 'django-admin help <subcommand>' for help on a specific subcommand. Available subcommands: [django] check compilemessages createcachetable dbshell diffsettings dumpdata flush inspectdb loaddata makemessages makemigrations migrate optimizemigration runserver sendtestemail shell showmigrations sqlflush sqlmigrate sqlsequencereset squashmigrations startapp startproject test testserver 创建项目 【一个额外的问题】 先说个目前看起来可能关系不大的问题。
一、token 验证登录流程 使用基于 Token 的身份验证方法,大概的流程是这样的:
客户端使用用户名跟密码请求登录服务端收到请求,去验证用户名与密码验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里客户端每次向服务端请求资源的时候需要带着服务端签发的 Token服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据 总的来说就是客户端在首次登陆以后,服务端再次接收http请求的时候,就只认token了,请求只要每次把token带上就行了,服务器端会拦截所有的请求,然后校验token的合法性,合法就放行,不合法就返回401(鉴权失败)。
二、最常用的鉴权是 JWT方案(JSON WEB TOKEN) JWT是什么?
JWT是Auth0提出的通过对JSON进行加密签名来实现授权验证的方案。就是登陆成功后将相关信息组成json对象,然后对这个对象进行某中方式的加密,返回给客户端,客户端在下次请求时带上这个token,服务端再收到请求时校验token合法性,其实也就是在校验请求的合法性。
JWT对象通常由三部分构成:
Headers: 包括类别(typ)、加密算法(alg)
{ "alg": "HS256", "typ": "JWT" } Claims :包括需要传递的用户信息
{ "sub": "1234567890", "name": "John Doe", "admin": true } Signature: 根据alg算法与私有秘钥进行加密得到的签名字串, 这一段是最重要的敏感信息,只能在服务端解密;
HMACSHA256( base64UrlEncode(Headers) + "." + base64UrlEncode(Claims), SECREATE_KEY ) 编码之后的JWT看起来是这样的一串字符:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ 三、 后端设计:nodejs+express+jwt-simple auth.js
let jwt = require('jwt-simple'); let secret = "wangyy"; let time = 10; module.
1. 业务背景 在业务研发过程中碰到条件范围查询或是设定截止日期,需要基于当前时间向前或是向后进行加减几天,但是因为可能涉及跨月或是跨小时并不能单纯的直接在月份上+1或是-1操作,针对这种情况JAVA提供了相关的API可以完成相关的功能,具体方法如下
2. 操作方法 // 获取当前时间 Date date = new Date(); Calendar calendar = new GregorianCalendar(); calendar.setTime(date); // 把日期往后增加一天,整数 往后推,负数往前移动 calendar.add(Calendar.DATE, 1); // 这个时间就是日期往后推一天的结果 date = calendar.getTime(); 3. 功能测试
目录
1 vue的两个特性
1.1 数据驱动视图
1.2 双向数据绑定 2 MVVM工作原理
3 vue 的指令
3.1 内容渲染指令
3.2 属性绑定指令
3.3 事件绑定指令
3.4 事件修饰符 3.5 按钮修饰符
3.6 双向数据绑定指令
3.7 条件渲染指令
3.8 列表渲染指令 4 vue 的生命周期和生命周期函数 4.1 生命周期&生命周期函数
4.2 组件生命周期函数的分类
4.3 生命周期函数特点
5 keep-alive
5.1 keep-alive的基本使用
5.2 keep-alive属性
6 计算属性和侦听器
6.1 侦听器
6.1.1 作用
6.1.2 侦听器的格式
6.2 计算属性
6.2.1 使用
6.2.2 注意
6.3 Computed 和 Watch 的区别
7 获取组件/元素——refs
7.1 ref的概念
7.2 使用ref引用组件实例
8 绑定Class
文章目录 一. 前言二. CubeMX配置三. ADC读取 一. 前言 ADC是指模数转化,即将模拟信号转化为数字信号。 世界的信号本质都是模拟信号,如速度、温度、声音,在本质上都是模拟的。但是微控制器和微处理器上运行的电子设备不能直接读取或者解释这些模拟值,因为它们只在0和1上运行。所以我们需要将这些模拟值转换成0和1,以便微控制器和微处理器能够理解它们。这就是我们所说的模拟信号转化为数字信号。与ADC相对应的是DAC,即将数字信号转化为模拟信号。
二. CubeMX配置 开发环境:Keil 、 CubeMX
软件版本:5.31 、6.2.1
使用芯片:STM32F103C8T6
开发语言:C
CubeMX的配置非常简单:Analog->ADCx->INx 。
此处选择多通道采集,选择ADC1 ,勾选IN1 、IN2 。配置如下:
由于是多通道采集,需开启Scan Conversion Mode 扫描模式 。需要多次读取,因此开启Continuous Conversion Mode 连续转换模式 。选配Rank,给IN1、IN2选择合适的采样通道和采样周期。 添加DMA通道 ,将模式改为Circular 循环模式 ,这样每次DMA传输成功后会主动开启下一次传输。
三. ADC读取 启动函数:
HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length) 将ADC用于遥杆的读取: 遥杆的本质是一个电位器,通过ADC采集变化的电压可以得到遥杆X、Y轴的遥杆值。按照上面的配置,在生成的Keil工程中加入如下代码可以便可以得到采集的遥杆值。
uint16_t Joystick_ADC[2]; HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&Joystick_ADC,2); 注意: 如果开启ADC的DMA接收后没办法继续运行主函数可能是因为设置的采样周期太短,频繁触发DMA接受中断导致的。可以在CubeMX中把Rank中通道的采样周期Samplink Time 设长一些,亲测有效。
Android凉了? 很多做Android开发的朋友们都知道,从15年开始,就不断的有人在唱衰Android,在知乎上,经常可以看到这种
还有这种:
我甚至都想跟着附和“没前景!没未来!快别搞Android了!Android凉了!”
第一次看我文章的小伙伴可以关注一下bugyinyin,每天更新各种技术干货。
为什么会这样? 从15年末开始,就已经隐约有听到风声传来“Android市场饱和”
到17年愈演愈烈“Android凉了!”
18年、19年则更多的是“互联网寒冬,Android凉凉,全部转行”之类的言论
那么为什么这么多人都在“劝退”Android开发呢?
首先我要排除那些不为人知的利益关系,比方说某些不可告人的PY交易……
怎么会有PY交易乱入?
明明是个正经的Android开发~
2015年是什么时候?IT正火,线下培训机构陆续开发线上课程
等等,什么?培训机构?
这样就说得过去的,当时的线下培训机构不要我多说了吧,我有幸听曾经报过的小伙描述过,当时的培训机构造就了一大批速成的初级Android开发进入市场,导致当时火热的市场迅速供大于求。怪不得从那个时候就开始Android凉了,也是从那个时候Android招聘的门槛开始慢慢的提高了。
通常来说,一线城市中的Android开发薪资/年限如下:
应届毕业初级工程师可以拿到7k; 工作2-3年中级工程师可以拿到15k; 工作3-5年高级工程师可以拿到30k; 工作5年以上的架构师可以拿到40k+。
…
你品,你细品……
你会发现,那些说“Android凉了”的、被优化的、转行的,普遍月薪是7-15k(10k以下的居多),也就是说,他们大多还处在初级工程师的阶段,强一些的也就半步踏入中级工程师……
到这里,肯定会有人说他开发5年8年技术又怎么怎么了
不要总说外界原因怎么怎么样,而忽视了从自身找问题!
你有想过吗?为什么同样开发3年、5年、8年,你只能10k徘徊,而别人都已经20k、30k、40k了?
学历确实很重要,但大家要搞清楚我们这行真正的核心竞争力到底是什么?
还不就是技术!
其实很多Android开发只是缺乏系统的进阶学习路线,在这我分享一位大佬收录整理的《Android开发核心知识点笔记》帮助大家学习提升进阶,如果你有需要的话,私信我【进阶】免费领取哦。
不要给自己对学习的懒惰找借口!不要因为自己菜而被优化就抱怨大环境怎么样!
而培训机构速成的初级开发找不到工作的话…他们又会大肆宣扬Android凉了…被裁…
就这么开始了“Android凉了”无穷无尽的恶性循环……
另外,还有某些培训机构为了卖课疯狂散播焦虑,给大家传播Android市场饱和了的情况,甚至是Android凉了的杜撰。
那大环境到底怎么样? 在我看来,大环境确实变了,但Android还远远没到凉凉的地步
Android系统——全球最高市场占有率
Android生态更是由Android系统衍生出来的一系列周边产品,说不好听点,恐怕你凉凉了,Android还没凉
那大环境究竟变了哪里呢?
其实Android的市场一直都是那样,变化不大,薪资水平、岗位数量都在
现在越来越多的急招岗位都涌出来了,不知道没人去的话公司会不会倒闭(/狗头)
尤其是高工以上,对于高工,目前市场上都是在抢人,许多公司都面临高薪都招不到人的惨况
架构师的话,不要我说了吧,就算是在某家大厂不想干了,也总能找到接盘的金主爸爸
我也问过HR朋友了,他们面试确实是很多人投递,一个月收到的简历估计有几百份,但整体水准偏低,符合要求的不超过百分之五,最后他发起的面试不超过5个,面试合格的一个也没有。
其实大家说的“Android凉了”只是Android市场经过了几年火爆之后的冷静
随着Android大火,前几年有很多人纷纷涌入Android行业,而大家的技术却都参差不齐
也就造成了企业提高录取门槛,同时也造成了以前一些浑水摸鱼的开发者被“刚毕业的大学生”替代
Android变了吗?变了,但也没变
变的是对Android开发曾经“上头”了一般的激情,其实你不是对Android开发有激情,你只是看到Android开发很火。毕竟……你都懒得提升自己的开发水平……你不是对Android开发有兴趣,你只是对Android开发的薪资感兴趣
并且,在我的了解中,还有今年被公司要求转岗Android的……
企业对Android开发人才的渴望,一直没变
Android凉了吗?答案是肯定的,没凉!
真正凉凉的,是那些菜却又不肯承认,不肯提升自己的人!
如何有效、全面、系统的提升? 学习一线大厂的各项技术,大厂是我们的技术先驱,不仅仅是各种技术,还有很多令你大开眼界的使用方法,学习这些有利于自己竞争力的提高,深入理解后也可以提升你的学习效率
定期面试,光学习了大厂的技术还不够,如何了解当下Android市场需要哪些技术呢?面试的目的不一定是为了找到好的工作,而是知道自己的优缺点是什么?知道市场需要什么样的人? 定期的面试可以让你了解当下市场需要哪些技术,也更加容易确定自身的短板在哪,同时,也可以更加有针对性的学习提升,并且在面试过程中遇到了你不会的点,你也可以借机向面试官提问,趁机学习了一波大厂的技术操作.
要是运气好,拿到了高薪Offer,岂不是更赚?
报名培训机构,我们对于培训机构总是褒贬不一,但是,不可置否,自己摸索和有人带你肯定是完全不一样的。多看大佬的学习笔记,学习大佬的设计思想 之前我跟一位大佬交流后,就拿到了他做的《Android开发核心知识点笔记》纯目录页都非常非常的长…感兴趣的朋友可以扫描下方二维码免费领取。
配合各种资料辅助学习,在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了 很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘.如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。
有需要的朋友扫描下方二维码免费领取。
最后,有段话想分享给大家: “如果你热爱,那么请继续热爱,你的付出终将获得与之匹配的回报,如果眼前觉得没有希望,不妨再坚持一会,‘今天很残酷,明天也很残酷,但是后天很美好’ ‘冬天都已经来了,春天还会远吗?’ ”
道理就是这个道理,但是“大道理大家都懂”,而那些成功的人,就是把这些道理运用到了工作和生活当中……
共勉!
学python的过程中遇到的模块导入问题造成了我很长时间的困顿,最近再重温一下模块的导入和包内模块导入,发现了一些新东西,所谓温故知新,确实如此,特来记录。 1. 模块的导入和环境变量 首先要清楚一点的是,Python的环境变量是解释器寻找文件模块的依据,环境变量第一条路径一般就是当前运行文件所在的路径,例如下面这个例子,我执行的文件是dao2.py,在test文件夹下,通过sys.path也能显示出来。
print(sys.path) 输入的环境变量列表第一条确实是当前运行文件目录\test文件夹。所以我们导包也应该尽量将包和模块放到与运行文件同一目录下,直接import导入即可,包和模块都可以通过环境变量找到。
如果是将包或模块放到了其他位置,那么通过sys.path.append()添加模块所在的目录到环境变量,也可以找到。
2. 包内模块导入 包内的导入涉及到__init__.py文件,相对导入以及绝对导入。
在文件夹中加入__init__.py文件之后,这个文件夹就变成了包,可以直接导入包来当做模块,具体知识点不再赘述,主要说说其中绝对导入和相对导入的问题。
问题1: 包内导入中经常碰到类似 ModuleNotFoundError: No module named ‘main.xxx’; ‘main’ is not a package这样的问题,发生这种问题的原因,一般是将包内的模块按照脚本模式去运行,但是在执行文件中使用了相对导入.xxx的形式,执行文件所在的目录就是环境变量的第一条路径,所以解决方法是直接使用import导入模块名或者用from xxx import绝对导入的方式,推荐用绝对导入,这时通过环境变量就可以找到要导入的模块名。举例如下:
# test1.py from .test2 import hello import sys print(sys.path) hello(3) 当前执行文件是test1.py,是haha包下的模块,按照脚本模式运行,不能用相对导入的形式 从test2.py中导入hello使用,test1和test2都在haha文件夹下,这里却使用了相对导入.test2的形式,那么结果就出现ModuleNotFoundError: No module named ‘main.xxx’; ‘main’ is not a package这样的问题。
问题2:还有一个问题就是一些博客说出现了ModuleNotFoundError: No module named ‘main.xxx’; ‘main’ is not a package这个问题可以使用绝对导入的形式解决:
# test1.py from haha.test2 import hello import sys print(sys.path) hello(3) 但是又会出现模块找不到的问题:
我想可能是一些博主改变了运行文件的路径才能成功,如果模块和执行文件还在一个目录下,那么加入了haha这个顶级包名,出现找不到haha的情况,问题依旧出在环境变量上。因为导入的haha这个顶级包名和环境变量中的路径重复,导致有问题,如果把包含haha这个目录的上一级目录test加到环境变量中,那么这个就不会出错了,例如下面这样:
sys.path.append(test_path) # test1.
人教版英语七年级上册的单词全部谢谢 。
义务教育教科书《英语(Goforit!)》七年级上册单词表(2013年6月第2版,2016年6月第4次印刷)StarterUnit1Goodmorning!good/ɡʊd/ adj.好的 p.S1morning/'mɔ:(r)nɪŋ/ n.早晨;上午 p.S1Goodmorning!
早上好 p.S1hi/haɪ/interj.(用于打招呼)嗨;喂 p.S1hello/hə'ləʊ/interj.你好;喂 p.S1afternoon/ˌɑ:ftər'nu:n/,/ˌæftər'nu:n/n.下午 p.S3Goodafternoon!
下午好!p.S3evening/'i:vnɪŋ/n.晚上;傍晚 p.S3Goodevening!晚上好!
p.S3how/haʊ/adv.怎样;如何 p.S3are/ɑ:(r);ə(r)/ v.是 p.S3you/ju:/pron. 你;你们 p.S3Howareyou?
你好吗?
p.S3I/aɪ/pron.我 p.S3am/æm/v.是 p.S3fine/faɪn/adj.健康的;美好的 p.S3thanks /θæŋks/interj.&n.感谢;谢谢 p.S3OK/əʊ'keɪ/ interj.&adv.好;可以p.S3HB/,eɪʧ''bi:/(铅笔芯)硬黑 p.S3CD/,si:'di:/ 光盘;激光唱片 p.S3BBC/,bi:bi:'si:/ 英语广播公司 p.S3Alice/'ælɪs/艾丽斯(女名)p.S1Bob/bɒb/鲍勃(男名)p,S1Cindy/'sindi/辛迪(女名)p.S1Dale/deɪl/戴尔(男名)p.S1Eric/'erɪk/埃里克(男名)p.S1Frank/fræŋk/弗兰克(男名)p.S1Grace/greɪs/格蕾丝(女名)p.S1Helen/'helən/海伦(女名)p.S1StarterUnit2What’sthisinEnglish?what/wɑ:t/,/wɒt/prep.&adj.什么 p.S5is/ɪz/ v.是 p.S5this/ðɪs/ pron.这;这个 p.S5in/ɪn/prep.(表示使用语言、材料等)用;以 p.S5English/'ɪŋɡlɪʃ/ n.英语adj.英格兰的;英语的 p.S5inEnglish用英语 p.S5map/mæp/ n.地图 p.S5cup/kʌp/ n.杯子 p.S5ruler/'ru:lə(r)/ n.尺;直尺 p.S5pen/pen/ n.笔;钢笔 p.S5orange/'ɒrɪnʤ/n.橙子 p.S5jacket/'ʤækɪt/ n.夹克衫;短上衣p.S5key/ki:/ n.钥匙 p.S5quilt/kwɪlt/n.被子;床罩 p.S5it/ɪt/ pron.它 p.S5a/eɪ;ə/(an/æn;/ən/)art.(用于单数可数名词前,表示未曾提到的)一(人、事、物)p.S5that/ðæt/pron.那;那个 p.S7spell/spel/v.用字母拼;拼写 p.S7please/pli:z/interj.(用于客气地请求或吩咐)请 p.S7NBA/,enbi:'eɪ/(美国)全球篮球协会 p.S6P/pi:/ 停车场;停车位 p.S6kg/,keɪ'ʤi:/千克;公斤p.S6StarterUnit3Whatcolorisit?color/'kʌlə(r)/n.(=colour)颜色 p.S9red/red/ adj.&n.红色(的) p.S9yellow/'jeləʊ/adj.&n.黄色(的) p.S9green/ɡri:n/adj.&n. 绿色(的) p.S9blue/blu:/ adj.
ECCV2022 | 人大提出轻量级基于注意力的特征融合机制,在多个公开数据集上有效!代码已开源! 【写在前面】 本文在文本到视频检索的新背景下,作者重新探讨了特征融合这一古老的课题。与以往的研究只考虑视频或文本一端的特征融合不同,本文的目标是在一个统一的框架内实现两端的特征融合。作者假设优化特征的凸组合比通过计算繁重的多头自注意建模它们的相关性更可取。作者提出轻量级注意特征融合(LAFF)。LAFF在早期和后期以及在视频和文本末端都进行特征融合,使其成为利用各种特征的强大方法。LAFF的可解释性可用于特征选择。在五个公共基准集(MSR-VTT、MSVD、TGIF、V ATEX和TRECVID A VS 2016-2020)上的广泛实验证明LAFF是文本到视频检索的新基准。
1. 论文和代码地址 Lightweight Attentional Feature Fusion: A New Baseline for Text-to-Video Retrieval
论文地址:https://arxiv.org/abs/2112.01832
代码地址:https://github.com/ruc-aimc-lab/laff
2. 动机 文本到视频检索是用一个特别的文本查询从很多未标记视频中检索对应视频的任务。视频和文本都必须嵌入到一个或多个跨模态的公共空间中,以便进行文本到视频的匹配。他的技术水平以不同的方法解决了这项任务,包括用于查询表示学习的新型网络,用于视频表示学习的多模态Transformer,用于可解释的跨模态匹配的混合空间学习,以及最近的以端到端方式学习文本和视频表示的CLIP2Video。另外,作者还研究了特征融合,这是文本到视频检索中一个重要但尚未充分开发的主题。
在给定以不同特征为代表的视频/文本样本的情况下,特征融合的目的是回答一个基本的研究问题,即**结合这些特征的最优方式是什么?**本文所说的最优是指融合将使检索性能最大化。同时对融合过程进行解释,解释个体特征的重要性。随着每一个特征的使用而引入额外的计算和存储开销,可解释性对聚合过程的选择至关重要,以平衡性能和成本。
特征融合本身并不新鲜。事实上,该主题已在多媒体内容分析和多模态或多视图图像分类等不同背景下进行了广泛研究。这些早期的努力集中在结合手工制作的特征上,因为已知这类特征是特定于领域的,存在语义差距问题,因此单独使用时不足以表示内容。虽然当前的深度学习特征已经比它们的前辈更强大,但似乎没有一个特征可以统治一切。关于物体和场景的黑暗知识在预训练的 2D 卷积神经网络(2D-CNN)中更好地承载,而 3D-CNN 更适合表示动作和动作。对于文本到视频的检索,在结合各种深度视频特征方面有一些初步努力,例如JE 、CE 和 MMT ,而 W2VV++ 和 SEA 显示了组合不同文本特征以获得更好查询表示的潜力。最近的 CLIP 系列,由于其端到端的学习范式,实际上缺乏利用现有特征的能力。因此,即使在深度学习时代,特征融合的需求依然强烈。
作为特征融合的一种方法,向量连接通常在早期组合特征时使用 。至于后期融合,并行学习多个特定于特征的公共空间,通过平均、经验加权 或专家混合 (MoE) 集成组合得到的相似性。随着特征数量的增加,向量连接会受到维度灾难的影响,而为每个特征构建公共空间缺乏特征间的交互。此外,之前的作品要么侧重于视频端,要么侧重于文本端。目前没有尝试开发一种统一的基于学习的方法,在文本到视频检索的上下文中对两端都有效,如下表。
人们可能会考虑通过多头自注意力(MHSA)进行特征融合,这是 Transformers 的基石。如下图(a) 所示,MHSA 通过将特定特征与来自所有其他特征的信息混合来转换特定特征,混合权重由称为 QKV 的自注意机制产生。请注意,该模块最初是为 NLP 任务开发的,其中利用元素相关性对于解决语义歧义至关重要。然而,由于由不同的 2D-CNN 和 3D-CNN 提取的视频特征是为了从不同方面描述视频内容,作者推测优化它们的组合优于对它们的相关性进行建模。此外,由 Softmax ( ( Q K T d v ) V ) \operatorname{Softmax}\left(\left(\frac{Q K^{T}}{\sqrt{d_{v}}}\right) V\right) Softmax((dv QKT)V)计算的 MHSA 中的 self-attention 在很大程度上取决于特征间的相关性。因此,它往往会产生一种群体效应,即彼此相关的特征将受到更多关注。因此,相关但相对较弱的特征将被过分强调。因此,尽管 MHSA 在不同环境中的流行率很高,但作者认为 MHSA 对于当前任务来说不是最佳的。
没有出现异常,多个AOP顺序执行
出现异常,多个AOP顺序执行
import cn.hutool.core.util.StrUtil; import org.apache.commons.lang3.StringUtils; /** * @author:BuBu * @Description 敏感信息屏蔽工具 * @Date: 2018年11月29日17:04:15 */ public final class DesensitizeUtil { public static void main(String[] args) { String name = "陈文"; String cer = "410105192201010011"; // System.out.println(chineseName(name)); // System.out.println(chineseName("陈一文")); // System.out.println(desStr(cer, 4, 11)); // System.out.println(mobilePhone("17600110011")); // System.out.println(identificationNum("410105192201010011")); System.out.println(bankCard("6222123456789234")); System.out.println(address("黑龙江省哈尔滨市松北区松浦街道教授家园")); System.out.println(address("浙江省杭州市西湖区文一路星光大道201B")); System.out.println(address("浙江省杭州市西湖区")); System.out.println(address("浙江杭州市西湖文一路星光大道201B")); System.out.println(address("黑龙江省哈尔滨市道里区新发镇机场路335号")); System.out.println(address("黑龙江省哈尔滨市双城区兰棱街道G1京哈高速")); System.out.println(address("吉林省长春市德惠市达家沟镇G1京哈高速")); System.out.println(address("吉林省长春市宽城区米沙子镇后石家")); System.out.println(address("吉林长春宽城米沙子后石家")); System.out.println(carPlateNumber("浙A12443")); System.out.println(businessLicense("1234567790099")); } public static String createStar(int num) { if (num < 1) { return "
2022年5月24日,经 Apache IoTDB 社区投票,刘明辉、刘旭鑫成为 Apache IoTDB Committer 。今天,我们为大家带来“二刘同学”与 Apache IoTDB 的故事。
1、Committer 刘明辉
清华大学软件学院研一学生,本科就读于厦门大学计算机系,2021年7月开始参与 Apache IoTDB 开源贡献。
主要贡献有:
SQL 解析重构、降采样聚合查询功能扩展、查询资源优化、C++ 客户端维护、查询逻辑计划生成等。
目前已经向 master 分支贡献70余个 PR,累积贡献度排名第 18 。
1.1 关于 Apache IoTDB 1.1.1 初识——IoTDB的契机是什么? 最早是在选择研究方向的过程中了解到 Apache IoTDB。这款高校自研数据库系统软件被捐赠到 Apache 软件基金会成为顶级项目,这种情况在国内非常少见,也因此引起了我的兴趣。
在本科阶段,我接触到的更多是一些算法方面的学习,尤其是近几年比较火的人工智能。人工智能固然神奇瑰丽,但相对于“炼丹”,我发现我更享受解决实际工程问题带来的成就感、满足感。而 IoTDB 既符合了我的兴趣,又足够“硬核”,能给我带来广阔的成长空间,因此我最终选择参与到 Apache IoTDB 这个项目中。
我是在2021年7月开始接触 IoTDB,并在7月13号合并了我的第一个 PR,正式成为了一名社区贡献者,开启了我与 IoTDB 的故事。
1.1.2 参与——有记忆犹新的故事吗? 让我记忆比较深刻的可能是最近几次的新分布式版本联调。各个模块的开发同学被组织在一起,焦急等待测试结果。中途有 bug 出现,大家就随时顶上。在大家的思维碰撞中,可以学习到其他同学解决问题的思路方法,社区伙伴之间的感情也更加深厚了,总之是段很难忘的经历。
1.1.3 成长——主要负责的内容和收获? 我在 Apache IoTDB 中主要负责查询引擎方面的工作。最大的收获就是让我从一个连 Java 和设计模式都不懂的小白成长成一个能够熟练参与开发、解决问题的 Committer,这离不开社区的培养,尤其是田原、祥威、宇荣等社区前辈对我细致耐心的指导。或许这就是开源的魅力所在吧。
1.2 关于开源社区 对开源有了什么新的认识?
——好的开源社区是源动力
最早我对开源的认识很简单,认为把代码公开到 Github 等代码托管平台就叫开源了。但在参与 Apache IoTDB 项目的过程中,我对开源也有了更深的认识——也就是常说的“社区大于代码”。在开源社区中,开发者可以接触到来自不同公司、高校,具有不同背景的同学,大家为了相同的目标共同努力、一起成长,这对开发者来说是很有吸引力的,也是一个开源软件能够持续健康发展的根本。我认为一个好的开源社区应该是开放透明的,社区的同学为了共同的目标进行平等的沟通协作,去感受社区乐于分享的氛围。
import java.util.function.Function; import java.util.stream.Collectors; Map<String, String> map = result.getData().stream().collect(Collectors.toMap(CustomerExtendDto::getCustomerCode, CustomerExtendDto::getCustomerName, (n1, n2) -> n1)); Map<String, SourceCodeRoute> existRouteUrlMap = bySourceCodeAndRouteUrlList.stream().collect(Collectors.toMap(SourceCodeRoute::getRouteUrl, Function.identity())); Map<String, CustomerWebDTO> customerMap = result.getData().stream().collect(Collectors.toMap(CustomerWebDTO::getCustomerCode, customerWebDTO -> customerWebDTO, (n1, n2) -> n1));
今天分享的主题是元数据治理实践,这是一项长期持续的工作,涉及多部门协作、多角色参与,链路长且复杂,要有完善的流程、成熟的平台、业务和技术部门共同参与,才能推进治理工作的有效展开。
1
背景说明
1.1 痛点问题
随着《“十四五”数字经济发展规划》的印发、数据治理相关法律法规的公布、数据治理高峰论坛的举办等等,都体现了数据治理的重要性。从国家宏观发展层面看,响应国家政府监管要求,数据治理是时代发展趋势。
另一方面,从企业发展和长远的战略规划来看,数据治理的痛点问题日渐突出,必须加快数据治理进程。企业面临的数据治理痛点可以总结如下:
质量问题:很多公司的数据部门启动数据治理的大背景就是数据质量存在问题。质量问题包括数据内容质量、元数据质量2方面。
(1)数据内容质量差:可能会影响业务分析和决策,数据内容质量差易导致数据问题后知后觉、数据可信度低、业务反馈意见大、数据部门压力大等;
(2)元数据质量差:会导致用户“找不到”、“看不懂”自己想要的数据。例如数据地图90%以上的用户都是IT技术人员,业务人员几乎很难使用。当表数量很大时,要找到一个自己想要的数据如大海捞针,即数据“找不到” ;数据地图78%的核心表都存在元数据信息缺失,尤其是业务元数据和管理元数据,用户找到数据但也难懂数据背后的含义,即数据“看不懂”问题。
安全问题:数据安全是一个企业的高压线,一旦数据泄露,对业务的影响非常之大,将造成重要影响。元数据缺失安全等级,就会导致数据在使用时,没有约束的依据和规则。
标准问题:没有标准则没有评判依据,杂乱无章的数据将是治理最大的困难。当公司业务部门比较多的时候,各业务部门、开发团队的数据标准不一致,数据代码、名称、口径重复,关键字段缺失等,导致数据打通和整合过程困难,无法进行数据流动和共享。
价值问题:数据资产只有被业务使用,才能体现出价值,否则将视为无效资产。而无效资产需要及时被发现、被治理,否则冗余的资产也会带来存储和管理成本。同时无效资产和有效资产混杂在一起,业务将很难识别哪些是有价值的资产,为业务使用带来的困难。
1.2 解决方案架构图
元数据治理是一项长期持续的工作,涉及多部门协作、多角色参与,链路长且复杂,需要有完善的流程、成熟的平台、业务和技术部门共同参与,才能推进治理工作的有效展开。元数据治理的解决方案架构图如下:
数据治理的最终愿景可以概括为三点:
流程方面:落地一套标准的数据治理规范流程
平台方面:沉淀一套全链路的数据治理工具体系
业务方面:定标准/保质量/抓安全/降成本/提价值
为了实现该愿景,我们将整个治理体系划分四层:
管理层:管理层主要是从集团层面来制定数据治理的组织架构、职责分配、制定流程,这是整个治理工作的基础前提,否则后续治理工作将无法展开。
标准层:标准层主要是定义整个数据治理过程中涉及到的各项标准,以及标准的落地评估。标准制定的内容主要包括模型设计规范、指标设计规范、模型开发规范、命名规则规范等等。
执行层:执行层则主要是各个产品模块的具体执行情况展示和分析,也是数据治理工作的重要内容来源。执行层包括元数据的资产全景、模型设计检测规范结果、质量分析报告、安全审计及访问控制、模型开发存储及计算资源情况等,通过执行层的数据结果可以反应当前存在哪些需要治理的数据和数据现状。
评价层:评价层则主要是针对执行层的结果,结合资产健康评估体系的规则,对目前待治理数据进行评分评价,指导数据治理工作人员进一步开展治理工作,并且通过治理工作台来查看整体治理进展。
1.3 元数据治理涉及的各产品间交互
元数据治理流程主要包括元数据采集、元数据注册、元数据治理、元数据发布、元数据使用。整条链路贯穿了各个子产品,包括数据源管理、数据质量、数据安全、数据标准、模型设计、数据资产目录及资产详情等,具体各产品间的交互关系及核心要素如下图所示:
1.4 名词解释
2
元数据治理流程介绍
2.1 存量元数据的治理流程
随着企业业务发展积累了大量的存量数据,数据可能分布在各个业务源系统中,涵盖多个数据源。这些数据若不加以有效利用,对于企业来说就是资源浪费且占据存储和管理成本,且如何从这些海量混杂的数据中,提取有价值、可业务复用的数据,也是数据治理要解决的问题。故存量数据的治理,是数据治理中的一大重点工作。整个元数据治理流程会涉及到IT运维团队、数据治理部门、各业务部门等协同推进完成。
存量元数据治理的业务流程图如下所示:
2.2 增量元数据的治理流程
增量元数据的治理流程和存量元数据的治理流程大部分相似,差别主要是新增数据的表物理模型还未创建,需要先经数据产品或数据开发进行元数据注册,此时主要是注册元数据的逻辑定义信息,经过注册审核后数据开发人员再去进行物理建模,这样建模得到的表更加标准和规范。数据开发人员物理建模后,治理人员再根据元数据信息完善度决定是否需要治理流程来补充元数据的其他信息。
增量元数据治理的业务流程图如下所示:
3
元数据治理产品案例实践
3.1 实践内容
3.1.1 案例场景描述
目标:通过一个简化的案例,介绍元数据基本的治理流程,该案例将介绍业务库存量表的元数据治理流程。
场景:某业务系统的MySQL库中存储了一张「客户信息表」,该表在实际业务中使用比较频繁,但是由于元数据缺失导致经常面临各种数据答疑、数据使用不规范等问题。故计划将该表采集到平台上进行治理,治理内容主要是完善表的业务信息、技术信息、管理信息等,以便将治理后的数据表呈现给用户,方便用户快速理解和使用表。
3.1.2 操作流程说明
为了实现上述案例的场景,我们需要完成以下事项:
(1)登记MySQL数据源,方便后续元数据使用;
(2)采集MySQL数据源中的「客户信息表」的元数据;
(3)「客户信息表」的元数据治理,包括元数据的安全、质量、标准、部门归属等信息;
(4)已治理的元数据表进行发布,发布后业务人员可以在资产目录中查看完整的元数据信息,以便业务使用。
3.2 操作步骤
第一步:登记数据源
在平台的数据源管理模块中,登记业务系统的MySQL数据源信息。登记内容主要包括数据源名称、负责人、数据源连接、用户名和密码等信息。
第二步:创建元数据采集任务
在元数据采集模块创建采集任务,采集上一步中登记的MySQL数据源中的「客户信息表」,根据实际业务场景需要设置采集的间隔周期。
第三步:申请元数据治理
元数据治理是整个操作实践过程中最重要,也是最复杂的一步。元数据治理一般会涉及到多部门间的协作治理,例如业务信息的补充完善需要业务部门专员参与治理,技术信息完善需要IT部门开发参与治理,最终治理的元数据在发布申请时需要治理部门进行最终审核确认。
上一步中采集的元数据表会在平台自动注册为一条元数据记录,此时元数据只有基本的物理信息例如表名、字段名、字段类型等,信息非常不完善。此时元数据是草稿状态,需要通过申请治理来派发治理工单给相关人员处理,如下图所示:
工单接收人接收到治理工单后,可以对元数据信息进行补充,包括表级和字段级的业务元数据、技术元数据等信息。表级元数据治理页面如下所示:
表级元数据信息分为基础信息、业务信息、技术信息,如果上述元数据内容还不够,还需要更多的元数据属性,系统也支持自定义属性及值域,以便业务灵活扩展元数据。
Tips:元数据治理页中,表的技术信息可以点击右侧的“扫描技术信息”按钮,触发一次元数据扫描功能。扫描后系统会自动将源库中的一些物理信息展示在页面上,方便用户确认最新表信息并覆盖填充。
接下来是字段的元数据治理页面,如下所示:
一、adapter是什么 属于结构模式(持有或继承被适配的类)。
对功能类进行包装,转换成客户端希望的样子,所以也叫包装模式。
实现比较直观,比较简单,就是加了一层封装。
二、adapter的使用场景 系统改造:功能在现有类中已实现,仅对外接口不符合要求,可通过adapter兼容。
三、adapter的实现 target:目标定义,客户端期望的样子。
adaptee:被适配者,已有的功能类。
adapter:适配器,封装adaptee为target。
注意:target的形态可以是interface、也可以是抽象类。
代码举例:
// target:目标接口定义 public interface Charger { public void charge(); } //adaptee:被适配者,已存在的实现了功能的类 public class Charge220v { public void charge() { System.out.println("220v charge工作了"); } } //adapter:适配器,利用现有类实现目标接口 public class ChargeAdapter implements Charger { private Charge220v charge220v; public ChargeAdapter(Charge220v charge220v) { this.charge220v = charge220v; } @Override public void charge() { charge220v.charge(); System.out.println("adapter 转换"); } } //client public class ClientMain { public static void main(String[] args) { Charger charger = new ChargeAdapter(new Charge220v()); charger.
当我们使用时间戳时,有时候需要得到一个对应的小时数才能继续编写,对于时间戳的运算其实很简单,将两个时间戳进行减法处理,得到时间差,使用时间差除以相对应的时间戳。
一小时的时间戳:3600000
一天的时间戳:86400000
一个月的时间戳:2592000000
一年的时间戳:31104000000
我这里是判断两个时间戳是否在24小时之内,代码如图所示。
java菜鸡一枚,望大佬勿喷,也渴望与志同道合的朋友相互交流讨论。
一、打开project目录,将jar、aar包粘贴进libs目录下。
二、jar包导入:选择jar包右键选择Add As library...
三、aar导入:打开build.gradle
在dependencies中添加: implementation files('libs\\lib.aar')
注:libs是存放包的位置,lib.arr是需要导入的jar/aar包名,以自己为准~
jar包也可以这样导入,但是第一种方法更方便!!
最后!!!!再Sync Now一下就导入成功啦!!!!
如果导入依赖之后找到的类文件,但是运行会闪退,在build.gradle(app)中,加入这行代码
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
想分割一部英文小说,使用nltk
with open ('AGameOfThrones.txt','rb') as f: text = f.read() 此处报错
TypeError: cannot use a string pattern on a bytes-like object 改为
f = open("AGameOfThrones.txt",encoding = "utf-8") text = f.read() cutwords1 = word_tokenize(text) 后成功。
目录
编辑
前端
1、点击新增用户按钮执行 handleAdd() 方法
2、添加用户表单校验:(这里明显是简介版本,还有很大的优化空间)
3、点击表单里的确 定按钮通过 submitForm() 方法 来提交表单内容实现增加用户:
后端
1、C层--控制层(Conroller层):Controller
2、M层--业务层(Model层):Service——Serviceimpl
3、M层--业务层(Model层):Mapper——Mapper.xml
4、V层--视图层(View层):在Controller里操作完返回前端去做具体的显示
整合mybatis连接数据库(druid连接池方式连接)
1、添加mybatis依赖和Druid依赖
2、配置好Datasource---在application-druid.yml中
3、配置Mybatis---在application.yml中
前端 1、点击新增用户按钮执行 handleAdd() 方法 <el-col :span="1.5"> <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['system:user:add']" >新增</el-button> </el-col> /** 新增按钮操作 */ handleAdd() { this.reset(); getUser().then(response => { this.postOptions = response.posts; this.roleOptions = response.roles; this.open = true; this.title = "添加用户"; this.form.password = this.initPassword; }); }, 2、添加用户表单校验:(这里明显是简介版本,还有很大的优化空间) // 表单校验 rules: { userName: [ { required: true, message: "
在Vue2中响应式数据是通过defineProperty来实现的,而在Vue3响应式数据是通过ES6的Proxy来实现的。Vue3中实现响应式数据的方法是ref和reactive。
defineProperty只能单一地监听已有属性的修改或者变化,无法检测到对象属性的新增或删除,而Proxy可以轻松实现 defineProperty无法监听属性值是数组类型的变化,而Proxy可以轻松实现 ref注意点 读取任何 ref 对象的值都必须通过 xxx.value普通变量使用 let 才可以修改值, ref 对象是个引用类型,可以在 const 定义的时候,直接通过 .value 来修改在数据修改时,可以使用 forEach、map、filter 等遍历函数来操作你的 ref 数组,或者直接重置 如果参数是对象类型,其实底层的本质还是reactive,系统会自动将ref转换为reactive,例如
ref(1) ===> reactive({value:1}) 使用方法:
<template> <h1>{{ name }}</h1> <h1>{{ age }}</h1> </template> <script> import { ref} from 'vue' export default { name: 'App', setup () { const name = ref('frank') const age = ref(18) const handleChange = () => { name.value = 'mike' age.value = 20 } return { name, age, handleChange } } } </script> reactive注意点 reactive 是继 ref 之后最常用的一个响应式 API 了,相对于 ref,它的局限性在于只适合对象、数组,他能够将复杂数据类型变为响应式数据 reactive的响应式是深层次的,底层本质是将传入的数据转换为Proxy对象在 vue3中,如果你使用 reactive 定义数组,必须只使用那些不会改变引用地址的操作,不要对通过 reactive 定义的对象进行解构,解构后得到的变量会失去响应性。 失去响应式:
Frame skipped from debugging during step-in. Note: may have been skipped because of "justMyCode" option (default == true). Try setting "justMyCode": false in the debug configuration (e.g., launch.json). 点开 .vscode/launch.json 看看,改成 false 即可
手机:pixel 6
系统:Android 12
HttpCanary高级版 想要无限制使用高级功能的可以参照我的这篇文章实战 逆向最新黄鸟抓包软件
HttpCanary证书的安装 之前我一直使用的Android 8,证书可以直接通过HttpCanary安装,但Android 12系统好像不可以了,提示信息如下:
分析了以下安卓的源码,在com.android.certinstaller.CredentialHelper类下的hasOnlyVpnAndAppsTrustAnchors方法是限制的证书安装的关键方法,源码如下:
如果这个证书用于应用和VPN则返回true,因此只要hook它让其永远返回false就绕过了CA证书安装的限制,我根据此原理写了一个名叫BypassCertLimit的Xposed模块,链接在文末。
我手机安装的是LSPosed,其使用步骤如下:
首先激活该模块
然后点击该模块进入目标软件的选择,点击右上方的三个点,再点击隐藏
取消系统应用的选择
然后搜索cert,找到证书安装程序并选择
最后强制停止HttpCanary让该模块生效,之后就能正常安装CA证书了,如图:
至此证书已经安装在了用户凭据中了,但安卓7.0以后,安卓不信任用户安装的证书,所以抓https时无法解码请求,对于第三方应用,需要将证书添加为系统证书
那么如何添加呢?其核心步骤就是把证书移动到/system/etc/security/cacerts/路径下,这就需要重新挂载/system为可读可写,可是android 12不允许挂载该目录的,root用户也不可以,解决方案见下文。
把用户凭据移动至系统凭据 该解决方法采用了Magisk模块,我安装的Magisk版本为v25.1,这个版本已经不支持在线安装模块了,因此我使用了FoxMagiskModuleManager进行了替代,链接:https://github.com/Fox2Code/FoxMagiskModuleManager
移动证书的模块是movecert,链接:https://github.com/Magisk-Modules-Repo/movecert,下载zip包后移动到/sdcard/Download路径下,使用FoxMagiskModuleManager从本地进行安装,这个模块不能直接通过Magisk进行安装,我已经试过了,安装之后重启,用户证书就全部移动到系统证书里了
安装包:
BypassCertLimit
FoxMmm-0.5.4.apk
movecert-1.9