python-NLP:1中文分词
文章目录
- 规则分词
- 正向最大匹配法
- 逆向最大匹配法
- 双向最大匹配法
- 统计分词
- 语言模型
- HMM模型
- jieba分词
- 分词
- 关键词提取
- 词性标注
规则分词
基于规则的分词是一种机械分词方法,主要是通过维护词典,在切分语句时,将语句的每个字符串与词表中的词进行逐一匹配,找到则切分,否则不予切分。
按照匹配切分的方式,主要有正向最大匹配法、逆向最大匹配法以及双向最大匹配法三种方法。
正向最大匹配法
基本思想为:假设分词词典中的最长词有i个汉字字符,则用被处理文档的当前字串中的前i个字作为匹配字段,查找字典。若字典中存在这样的一个i字词,则匹配成功,匹配字段被作为一个词切分出来。如果词典中找不到这样的一个i字词,则匹配失败,将匹配字段中的最后一个字去掉,对剩下的字串重新进行匹配处理。如此进行下去,直到匹配成功,即切分出一个词或剩余字串的长度为零为止。这样就完成了一轮匹配,然后取下一个i字字串进行匹配处理,直到文档被扫描完为止。
其算法描述如下:
1)从左向右取待切分汉语句的m个字符作为匹配字段,m为机器词典中最长词条的字符数。
2)查找机器词典并进行匹配。若匹配成功,则将这个匹配字段作为一个词切分出来。若匹配不成功,则将这个匹配字段的最后一个字去掉,剩下的字符串作为新的匹配字段,进行再次匹配,重复以上过程,直到切分出所有词为止。
比如我们现在有个词典,最长词的长度为5,词典中存在“南京市长”和“长江大桥”两个词。现采用正向最大匹配对句子“南京市长江大桥”进行分词,那么首先从句子中取出前五个字“南京市长江”,发现词典中没有该词,于是缩小长度,取前4个字“南京、市长”,词典中存在该词,于是该词被确认切分。再将剩下的“江大桥”按照同样方式切分,得到“江”“大桥”,最终分为“南京市长”“江”“大桥”3个词。显然,这种结果还不是我们想要的。

#正向最大匹配
class MM(object):def __init__(self, dic_path):self.dictionary = set()self.maximum = 0#读取词典with open(dic_path, 'r', encoding='utf8') as f:for line in f:line = line.strip()if not line:continueself.dictionary.add(line)if len(line) > self.maximum:self.maximum = len(line)def cut(self, text):result = []index = 0while index <len(text):word = Nonefor size in range(self.maximum, 0, -1):#先选取最长词,然后-1....if index + size > len(text): #当前索引+size>文本长度continue#退出本次for循环,不执行下面代码。执行size-1piece = text[index:index+size]#匹配的字段if piece in self.dictionary:#匹配成功word = pieceresult.append(word)index += size #break#退出for循环if word is None:index += 1return result[::]def main():text = "南京市长江大桥"tokenizer =MM('大桥文本.txt')print(tokenizer.cut(text))main()
运行结果
[‘南京市长’, ‘大桥’]
逆向最大匹配法
逆向最大匹配(ReverseMaximum Match Method,RMM法)的基本原理与MM法相同,不同的是分词切分的方向与MM法相反。逆向最大匹配法从被处理文档的末端开始匹配扫描,每次取最末端的i个字符(i为词典中最长词数)作为匹配字段,若匹配失败,则去掉匹配字段最前面的一个字,继续匹配。相应地,它使用的分词词典是逆序词典,其中的每个词条都将按逆序方式存放。在实际处理时,先将文档进行倒排处理,生成逆序文档。然后,根据逆序词典,对逆序文档用正向最大匹配法处理即可。
由于汉语中偏正结构较多,若从后向前匹配,可以适当提高精确度。所以,逆向最大匹配法比正向最大匹配法的误差要小。统计结果表明,单纯使用正向最大匹配的错误率为1/169,单纯使用逆向最大匹配的错误率为1/245。比如之前的“南京市长江大桥”,按照逆向最大匹配,最终得到“南京市”“长江大桥”。当然,如此切分并不代表完全正确,可能有个叫“江大桥”的“南京市长”也说不定。
# 逆向最大匹配
class IMM(object):def __init__(self, dic_path):self.dictionary = set()self.maximum = 0# 读取词典with open(dic_path, 'r', encoding='utf8') as f:for line in f:line = line.strip()if not line:continueself.dictionary.add(line)if len(line) > self.maximum:self.maximum = len(line)def cut(self, text):result = []index = len(text)while index > 0:word = Nonefor size in range(self.maximum, 0, -1):if index - size < 0:continuepiece = text[(index - size):index]if piece in self.dictionary:word = pieceresult.append(word)index -= sizebreakif word is None:index -= 1return result[::-1]def main():text = "南京市长江大桥"tokenizer = IMM('大桥文本.txt')print(tokenizer.cut(text))
main()
运行结果
[‘南京市’, ‘长江大桥’]
双向最大匹配法
双向最大匹配法(Bi-directction Matching method)是将正向最大匹配法得到的分词结果和逆向最大匹配法得到的结果进行比较,然后按照最大匹配原则,选取词数切分最少的作为结果。据SunM.S.和Benjamin K.T.(1995)的研究表明,中文中90.0%左右的句子,正向最大匹配法和逆向最大匹配法完全重合且正确,只有大概9.0%的句子两种切分方法得到的结果不一样,但其中必有一个是正确的(歧义检测成功),只有不到1.0%的句子,使用正向最大匹配法和逆向最大匹配法的切分虽重合却是错的,或者正向最大匹配法和逆向最大匹配法切分不同但两个都不对(歧义检测失败)。这正是双向最大匹配法在实用中文信息处理系统中得以广泛使用的原因。
前面举例的“南京市长江大桥”,采用该方法,中间产生“南京市/长江/大桥”和“南京市/长江大桥”两种结果,最终选取词数较少的“南京市/长江大桥”这一结果。
统计分词
随着大规模语料库的建立,统计机器学习方法的研究和发展,基于统计的中文分词算法渐渐成为主流。
其主要思想是把每个词看做是由词的最小单位的各个字组成的,如果相连的字在不同的文本中出现的次数越多,就证明这相连的字很可能就是一个词。因此我们就可以利用字与字相邻出现的频率来反应成词的可靠度,统计语料中相邻共现的各个字的组合的频度,当组合频度高于某一个临界值时,我们便可认为此字组可能会构成一个词语。
基于统计的分词,一般要做如下两步操作:
1)建立统计语言模型。
2)对句子进行单词划分,然后对划分结果进行概率计算,获得概率最大的分词方式。这里就用到了统计学习算法,如隐含马尔可夫(HMM)、条件随机场(CRF)等。
下面针对其中的一些相关技术做简要介绍。
语言模型
语言模型在信息检索、机器翻译、语音识别中承担着重要的任务。用概率论的专业术语描述语言模型就是:为长度为m的字符串确定其概率分布P(ω1, ω2,*…,∞m),其中ω1到ωm依次表示文本中的各个词语。一般采用链式法则计算其概率值,如式所示:

观察上式易知,当文本过长时,公式右部从第三项起的每一项计算难度都很大。为解决该问题,有人提出n元模型(n-gram model)降低该计算难度。所谓n元模型就是在估算条件概率时,忽略距离大于等于n的上文词的影响,因此 P(ω¡|ω1,ω₂,…,ωi-1) 的计算可简化为:

当n=1时称为一元模型(unigrammodel),此时整个句子的概率可表示为:P(ω),ω2,0m) = P(ω1)P(w2)…P(ωm)观察可知,在一元语言模型中,整个句子的概率等于各个词语概率的乘积。言下之意就是各个词之间都是相互独立的,这无疑是完全损失了句中的词序信息。所以一元模型的效果并不理想。
当n=2时称为二元模型(bigram model),变为P(ωi|ω1,ω2,…,ωi-1)=P(ω¡|W¡-1)。当n=3时称为三元模型(trigram model),变为 P(ω¡|ω1,ω2, …", ωi-1) =P(w¡|W¡-2,ωi-1)。显然当n≥2时,该模型是可以保留一定的词序信息的,而且n越大,保留的词序信息越丰富,但计算成本也呈指数级增长。一般使用频率计数的比例来计算n元条件概率,如式所示:

式中 count(ωi-(n-1), …, ωi-1) 表示词语ω i-(n-1), …, ωi-1在语料库中出现的总次数。
由此可见,当n越大时,模型包含的词序信息越丰富,同时计算量随之增大。与此同时,长度越长的文本序列出现的次数也会减少,如按照上式估计n元条件概率时,就会出现分子分母为零的情况。因此,一般在n元模型中需要配合相应的平滑算法解决该问题,如拉普拉斯平滑算法等。
HMM模型
隐含马尔可夫模型(HMM)是将分词作为字在字串中的序列标注任务来实现的。其基本思路是:每个字在构造一个特定的词语时都占据着一个确定的构词位置(即词位),现规定每个字最多只有四个构词位置:即B(词首)、M(词中)、E(词尾)和S(单独成词),那么下面句子1)的分词结果就可以直接表示成如2)所示的逐字标注形式:
1)中文/分词/是/文本处理/不可或缺/的/一步!
2)中/B文/E分/B词/E是/S文/B本/M处/M理/E不/B可/M或/M缺/E的/S一/B步/E!/S
----
class HMM(object):def __init__(self):"""方法:初始化参数"""import os# 主要是用于存取算法中间结果,不用每次都训练模型self.model_file = 'hmm_model.pkl'# 状态值集合self.state_list = ['B', 'M', 'E', 'S']# 参数加载,用于判断是否需要重新加载model_fileself.load_para = Falsedef try_load_model(self, trained):"""方法:用于加载已计算的中间结果,当需要重新训练时,需初始化清空结果输入:trained :是否已经训练好"""if trained:import picklewith open(self.model_file, 'rb') as f:self.A_dic = pickle.load(f)self.B_dic = pickle.load(f)self.Pi_dic = pickle.load(f)self.load_para = Trueelse:# 状态转移概率(状态->状态的条件概率)self.A_dic = {}# 发射概率(状态->词语的条件概率)self.B_dic = {}# 状态的初始概率self.Pi_dic = {}self.load_para = Falsedef train(self, path):"""方法:计算转移概率、发射概率以及初始概率输入:path:训练材料路径"""# 重置几个概率矩阵self.try_load_model(False)# 统计状态出现次数,求p(o)Count_dic = {}# 初始化参数def init_parameters():for state in self.state_list:self.A_dic[state] = {s: 0.0 for s in self.state_list}self.Pi_dic[state] = 0.0self.B_dic[state] = {}Count_dic[state] = 0def makeLabel(text):"""方法:为训练材料每个词划BMES输入:text:一个词输出:out_text:划好的一个BMES列表"""out_text = []if len(text) == 1:out_text.append('S')else:out_text += ['B'] + ['M'] * (len(text) - 2) + ['E']return out_textinit_parameters()line_num = -1# 观察者集合,主要是字以及标点等words = set()with open(path, encoding='utf8') as f:for line in f:line_num += 1line = line.strip()if not line:continueword_list = [i for i in line if i != ' ']words |= set(word_list) # 更新字的集合linelist = line.split()line_state = []for w in linelist:line_state.extend(makeLabel(w))assert len(word_list) == len(line_state)for k, v in enumerate(line_state):Count_dic[v] += 1if k == 0:self.Pi_dic[v] += 1 # 每个句子的第一个字的状态,用于计算初始状态概率else:self.A_dic[line_state[k - 1]][v] += 1 # 计算转移概率self.B_dic[line_state[k]][word_list[k]] = \self.B_dic[line_state[k]].get(word_list[k], 0) + 1.0 # 计算发射概率self.Pi_dic = {k: v * 1.0 / line_num for k, v in self.Pi_dic.items()}self.A_dic = {k: {k1: v1 / Count_dic[k] for k1, v1 in v.items()}for k, v in self.A_dic.items()}# 加1平滑self.B_dic = {k: {k1: (v1 + 1) / Count_dic[k] for k1, v1 in v.items()}for k, v in self.B_dic.items()}# 序列化import picklewith open(self.model_file, 'wb') as f:pickle.dump(self.A_dic, f)pickle.dump(self.B_dic, f)pickle.dump(self.Pi_dic, f)return selfdef viterbi(self, text, states, start_p, trans_p, emit_p):"""方法:维特比算法,寻找最优路径,即最大可能的分词方案输入:text:文本states:状态集start_p:第一个字的各状态的可能trans_p:转移概率emit_p:发射概率输出:prob:概率path:划分方案"""V = [{}] # 路径图path = {}for y in states: # 初始化第一个字的各状态的可能性V[0][y] = start_p[y] * emit_p[y].get(text[0], 0)path[y] = [y]for t in range(1, len(text)): # 每一个字V.append({})newpath = {}# 检验训练的发射概率矩阵中是否有该字neverSeen = text[t] not in emit_p['S'].keys() and \text[t] not in emit_p['M'].keys() and \text[t] not in emit_p['E'].keys() and \text[t] not in emit_p['B'].keys()for y in states: # 每个字的每个状态的可能emitP = emit_p[y].get(text[t], 0) if not neverSeen else 1.0 # 设置未知字单独成词# y0上一个字可能的状态,然后算出当前字最可能的状态,prob则是最大可能,state是上一个字的状态(prob, state) = max([(V[t - 1][y0] * trans_p[y0].get(y, 0) *emitP, y0)for y0 in states if V[t - 1][y0] > 0])V[t][y] = probnewpath[y] = path[state] + [y] # 更新路径path = newpathif emit_p['M'].get(text[-1], 0) > emit_p['S'].get(text[-1], 0): # 最后一个字是词中的可能大于单独成词的可能(prob, state) = max([(V[len(text) - 1][y], y) for y in ('E', 'M')])else: # 否则就直接选最大可能的那条路(prob, state) = max([(V[len(text) - 1][y], y) for y in states])return (prob, path[state])# 用维特比算法分词,并输出def cut(self, text):import osif not self.load_para:self.try_load_model(os.path.exists(self.model_file))prob, pos_list = self.viterbi(text, self.state_list, self.Pi_dic, self.A_dic, self.B_dic)begin, next = 0, 0for i, char in enumerate(text):pos = pos_list[i]if pos == 'B':begin = ielif pos == 'E':yield text[begin: i + 1]next = i + 1elif pos == 'S':yield charnext = i + 1if next < len(text):yield text[next:]hmm = HMM()
hmm.train('HMM模型训练.txt')text = '南京市长江大桥'
res = hmm.cut(text)
print(text)
print(str(list(res)))
HMM训练数据集
jieba分词
分词
import jiebasent = '中文分词是文本处理不可或缺的一步!'
seg_list = jieba.cut(sent, cut_all=True)
print('全模式:', '/ ' .join(seg_list))
seg_list = jieba.cut(sent, cut_all=False)
print('精确模式:', '/ '.join(seg_list))
seg_list = jieba.cut(sent)
print('默认精确模式:', '/ '.join(seg_list))
seg_list = jieba.cut_for_search(sent)
print('搜索引擎模式', '/ '.join(seg_list))import jieba.posseg as psg
sent = '中文分词是文本处理不可或缺的一步!'
seg_list = psg.cut(sent)#标注词性
print(' '.join(['{0}/{1}'.format(w, t) for w, t in seg_list]))
运行结果
加载自定义词典
import jiebasent = 'jieba分词非常好用,可以自定义金融词典!'
seg_list = jieba.cut(sent)
print('加载词典前:', '/ '.join(seg_list))jieba.load_userdict('user_dict.txt')
seg_list = jieba.cut(sent)
print('加载词典后:', '/ '.join(seg_list))
关键词提取
关键词提取使用jieba中的analyse模块,基于两种不同的算法,提供了两个不同的方法。
1.基于TF-IDF算法的关键词提取
from jieba import analysetest_content="""
变压器中性点的接地方式变化后其保护应相应调整,即是变压器中性点接地运行时,投入中性点零序过流保护,停用中性点零序过压保护及间隔零序过流保护;变压器中性点不接地运行时,投入中性点零序过压保护及间隔零序保护,停用中性点零序过流保护,否则有可能造成保护误动作。
"""
key_word = analyse.extract_tags(test_content, topK=5)
print('[key_word]:', list(key_word))
key_word = analyse.extract_tags(test_content, topK=5, withWeight=True)
print('[key_word]:', list(key_word))
key_word = analyse.extract_tags(test_content, topK=5, withWeight=True,allowPOS="n")
print('[key_word]:', list(key_word))
extract_tags()方法有四个参数,sentence为待提取的文本;topK为返回最大权重关键词的个数,默认值为20;withWeight表示是否返回权重,是的话返回(word, weight)的list,默认为False;allowPOS为筛选指定词性的词,默认为空,即不筛选。
2.基于TextRank算法的关键词提取
from jieba import analysetest_content="""
变压器中性点的接地方式变化后其保护应相应调整,即是变压器中性点接地运行时,投入中性点零序过流保护,停用中性点零序过压保护及间隔零序过流保护;变压器中性点不接地运行时,投入中性点零序过压保护及间隔零序保护,停用中性点零序过流保护,否则有可能造成保护误动作。
"""
key_word = analyse.textrank(test_content, topK=3)
print('[key_word]:', list(key_word))
allow = ['ns', 'n', 'vn', 'v', 'a', 'm', 'c']
key_word = analyse.textrank(test_content, topK=3, allowPOS=allow)
print('[key_word]:', list(key_word))
textrank()方法与extract_tags()方法用法相似,需要注意的是allowPOS有默认值(‘ns’, ‘n’, ‘vn’, ‘v’),默认筛选这四种词性的词,可以自己设置。其他参数都与extract_tags()方法相同。
词性标注
词性标注使用jieba中的posseg模块,标注分词后每个词的词性,采用和ictclas兼容的标记法。
from jieba import posseg
test_content="""
变压器停、送电操作时,应先将该变压器中性点接地,对于调度要求不接地的变压器,在投入系统后应拉开中性点接地刀闸。
"""
pos_word = posseg.lcut(test_content)
print(pos_word)
[pair(‘\n’, ‘x’), pair(‘变压器’, ‘n’), pair(‘停’, ‘v’), pair(‘、’, ‘x’), pair(‘送电’, ‘v’), pair(‘操作’, ‘v’), pair(‘时’, ‘n’), pair(‘,’, ‘x’), pair(‘应先’, ‘vn’), pair(‘将’, ‘d’), pair(‘该’, ‘r’), pair(‘变压器’, ‘n’), pair(‘中性点’, ‘n’), pair(‘接地’, ‘v’), pair(‘,’, ‘x’), pair(‘对于’, ‘p’), pair(‘调度’, ‘n’), pair(‘要求’, ‘v’), pair(‘不’, ‘d’), pair(‘接地’, ‘v’), pair(‘的’, ‘uj’), pair(‘变压器’, ‘n’), pair(‘,’, ‘x’), pair(‘在’, ‘p’), pair(‘投入’, ‘v’), pair(‘系统’, ‘n’), pair(‘后’, ‘f’), pair(‘应’, ‘v’), pair(‘拉开’, ‘v’), pair(‘中性点’, ‘n’), pair(‘接地’, ‘v’), pair(‘刀闸’, ‘n’), pair(‘。’, ‘x’), pair(‘\n’, ‘x’)]
posseg.lcut()有两个参数,sentence和HMM。


相关文章:
python-NLP:1中文分词
文章目录 规则分词正向最大匹配法逆向最大匹配法双向最大匹配法 统计分词语言模型HMM模型 jieba分词分词关键词提取词性标注 规则分词 基于规则的分词是一种机械分词方法,主要是通过维护词典,在切分语句时,将语句的每个字符串与词表中的词进行…...
iOS 开发包管理之CocoaPods
CocoaPods(Objective-C 时期,支持Objective-C和swift),CocoaPods下载第三方库源代码后会将其编译成静态库.a 文件 或动态库框架.framework 文件 的形式,并将它们添加到项目中,建立依赖关系,这种…...
Windows搭建RTMP视频流服务器
参考了一篇文章,见文末。 博客中nginx下载地址失效,附上一个有效的地址: Index of /download/ 另外,在搭建过程中,遇到的问题总结如下: 1 两个压缩包下载解压并重命名后,需要 将nginx-rtmp…...
VS2019安装MFC组件
VS2019支持的MFC版本是mfc140 ~ mfc142版本,它兼容VS2015、VS2017之前的老版本程序。 一、MFC的历史版本 MFC的历史版本如下: IDE发布时间工具集版本MSC_VERMSVCMFC版本dllVisual C6.01998V601200MSVC6.06.0mfc42.dll、mfcce400.dllVisual Studio 2002…...
Python学习—open函数,json与pickle知识点,Os模块详解
目录 1. Open函数 2.json与pickle模块 json模块 1. json.dumps() 2. json.dump() 3. json.loads() 4. json.load() pickle 模块 1. pickle.dumps() 2. pickle.dump() 3. pickle.loads() 4. pickle.load() 3.Os模块 1. Open函数 在Python中,open() 函数…...
基于SSM的高考志愿选择辅助系统
基于SSM的高考志愿选择辅助系统的设计与实现~ 开发语言:Java数据库:MySQL技术:SpringSpringMVCMyBatis工具:IDEA/Ecilpse、Navicat、Maven 系统展示 前台 前台首页 院校展示 后台 后台首页 学校管理 摘要 随着高考制度的不断完…...
引领小模型潮流!OpenAI发布功能强大且成本低的GPT-4o mini
GPT-4o mini的成本比GPT-3.5 Turbo低了超过60%,其聊天表现优于Google的Gemini Flash和Anthropic的Claude Haiku。该模型从周四开始对ChatGPT的免费用户、ChatGPT Plus用户和团队订阅用户开放,并将在下周向企业用户开放。OpenAI计划未来将图像、视频和音频…...
【考研数学】线代满分经验分享+备考复盘
我一战二战复习都听了李永乐的线代课,二战的时候只听了一遍强化,个人感觉没有很乱,永乐大帝的课逻辑还是很清晰的。 以下是我听向量这一章后根据听课内容和讲义例题总结的部分思维导图,永乐大帝讲课的时候也会特意点到线代前后联…...
Java项目:基于SSM框架实现的海鲜自助餐厅系统【ssm+B/S架构+源码+数据库+毕业论文】
一、项目简介 本项目是一套基于SSM框架实现的海鲜自助餐厅系统 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse或者idea 确保可以运行! 该系统功能完善、界面美观、操作简单、功能…...
前端面试题日常练-day97 【Less】
题目 希望这些选择题能够帮助您进行前端面试的准备,答案在文末 在Less中,以下哪个功能用于处理文本字间距? a) letter-spacing() b) word-spacing() c) text-spacing() d) space-between() Less中的Variables可以存储哪些类型的值ÿ…...
压缩视频大小的方法 怎么减少视频内存大小 几个简单方法
随着4K、8K高清视频的流行,我们越来越容易遇到视频文件体积过大,导致存储空间不足、传输速度缓慢等问题。视频压缩成为解决这一问题的有效途径,但如何在减小文件大小的同时,保证视频质量不受影响呢?本文将为你揭晓答案…...
JVM:GraalVM
文章目录 一、介绍1、什么是GraalVM:2、GraalVM版本 二、两种使用模式 一、介绍 1、什么是GraalVM: GraalVM是Oracle官方推出的一款高性能JDK,使用它享受比OpenJDK或者OracleJDK更好的性能。GraalVM的官网地址:https://www.graa…...
海外营销推广:快速创建维基百科(wiki)词条-大舍传媒
一、维基百科的永久留存问题 许多企业和个人关心维基百科是否能永久留存。实际上,只要企业和个人的行为没有引起维基百科管理方的反感,词条就可以长期保存。如果有恶意行为或被投诉,维基百科可能会对词条进行删除或修改。 二、创建维基百科…...
【HarmonyOS】HarmonyOS NEXT学习日记:五、交互与状态管理
【HarmonyOS】HarmonyOS NEXT学习日记:五、交互与状态管理 在之前我们已经学习了页面布局相关的知识,绘制静态页面已经问题不大。那么今天来学习一下如何让页面动起来、并且结合所学完成一个代码实例。 交互 如果是为移动端开发应用,那么交…...
处理uniapp刷新后,点击返回按钮跳转到登录页的问题
在使用uniapp的原生返回的按钮时,如果没有刷新会正常返回到对应的页面,如果刷新后会在当前页反复横跳,或者跳转到登录页。那个时候我第一个想法时:使用浏览器的history.back()方法。因为浏览器刷新后还是可以通过右上角的返回按钮…...
工厂方法模式java
文章目录 1. 概念2. 示例3. 代码示例 1. 概念 定义: 工厂方法模式又叫工厂模式,通过定义工厂父类创建对象的公共接口,而子类负责创建具体的对象 作用: 由工厂的子类来决定创建哪一个对象 缺点: 工厂一旦需要生成新的东西就需要修改代码,违背的开放封闭原则 2. 示例 3. 代码示…...
java模拟多ip请求【搬代码】
java模拟多ip请求 package url_demo;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.URL; import java.net.URLConnection; import java.util.Random;public class HttpUtilTest…...
微软史诗级的蓝屏
本周经历了微软的蓝屏,一直到周末还在加班处理公司的问题。 个人终端受到的影响较大,服务器上也受到了影响。因为蓝屏的事情导致不少麻烦,据同事说因为蓝屏的问题,MGH 的手术安排也受到了影响。 目前我们也在着手处理有部署 Wind…...
HALCON数据结构
一、HALCON数据结构简介 1、HALCON中有两类参数:图形参数和控制参数。 2、HALCON算子参数中,图形输入参数、图形输出参数、控制输入参数和控制输出参数。 3、图形参数有:图像(image)、区域(region)和轮廓(XLD) 4、控制参数有:…...
数据库系统概论:事务与并发一致性问题
随着网络应用的普及,数据库并发问题变得越来越重要。数据库并发指的是多个用户或进程同时访问和操作数据库的能力。它是数据库系统性能优化的重要方面,旨在提高系统的吞吐量和响应时间,以满足多用户同时访问数据库的需求。然而,这…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
