【机器学习】条件随机场

9ebfcb85efd66aa26a59c3c77bd33d09.png

61004cef5665b7762da54a22b19b7267.png

一、马尔可夫随机场

1.1 概率图模型

2fa34b7842df69414a029ad73c12041f.png

5e0716207fd0d2554f889782b01c2075.png

什么是有向图模型和无向图模型?

b01e088901863b5f9c7f7aafe2e5316c.png

5a38c04e2f86c92b7a07e639b54822e0.png

babd77f7be9ebd9c8f36aed70b7bdc8f.png

b8bc7af81b0534da0a677599566701fc.png

https://www.jianshu.com/p/dabbc78471d7 团、极大团、最大团 - 简书 (jianshu.com)

be006be39a95dd7f307f8ff6a74a40ce.png

1.2 马尔可夫随机场

da9285359d34a87bd28e1600c232c99c.png

db0554f6bac739e89091b536e10b3444.png

0f4cd1eea192fdcb7314e7d607060057.png

7c3601278c3aec89a41e915adcc65527.png

二、条件随机场概述

2.1 条件随机场简介

条件随机场(Conditional Random Field,简称 CRF)是一种用于序列标注(sequence labeling)的概率模型。它是马尔可夫随机场(Markov Random Field,简称 MRF)的一种扩展,可以用无向图来表示输入序列和输出序列之间的条件依赖关系。条件随机场的每个节点对应一个输出标签,每条无向边表示两个相邻标签之间的相关性,每个节点的概率分布由输入序列和相邻节点的取值共同决定。

条件随机场的主要优点是:

  • 它可以利用丰富的特征来描述输入序列和输出序列之间的复杂关系,而不受马尔可夫假设的限制。

  • 它可以在全局范围内对输出序列进行建模,而不是局部地对每个输出标签进行建模,从而避免了标注偏置(Label Bias)问题。

  • 它可以通过无向图来表示输出序列的依赖结构,而不是有向图,从而避免了循环依赖(Cyclic Dependency)问题。

条件随机场的主要缺点是:

  • 它的训练和预测过程都比较耗时,特别是当特征的个数和标签的个数很大时,计算归一化因子和最优序列的代价很高。

  • 它的特征选择和权重调整都需要人工干预,没有自动化的方法来确定最优的特征组合和权重分配。

  • 它的模型参数和特征函数都是固定的,不能随着数据的变化而自适应地更新和调整。

2.2 线性链条件随机场(LCCRF)

4c54242f148d13bc836f15c38bff3508.png

线性链条件随机场的每个节点对应一个输出标签,每条无向边表示两个相邻标签之间的相关性,每个节点的概率分布由输入序列和相邻节点的取值共同决定。

1310e023d7b16551452e95e8643ff696.png

694148c20c3ef96b0f9b7d134e943444.png

c6599ea4e96673ee56dbd0e8672eb419.png

19a298c9829f8504f9678321808d3f14.png

要建立条件随机场,需要定义特征函数集,因为特征函数是条件随机场的核心组成部分,它们用于描述输入序列和输出序列之间的关系,从而决定了条件随机场的概率模型和图结构。

特征函数集可以分为两类:转移特征函数和状态特征函数。转移特征函数表示两个相邻标签之间的特征,状态特征函数表示一个标签的特征。特征函数可以包含输入序列和位置的信息,也可以包含其他的信息,如词性、词典、语法等。特征函数的选择取决于具体的应用场景和数据特点,一般需要根据经验和实验来确定。

特征函数集的大小和多样性影响了条件随机场的模型复杂度和表达能力,一般来说,特征函数越多越丰富,条件随机场的性能越好,但也会增加计算的代价和过拟合的风险。因此,特征函数集的定义需要平衡特征的有效性和效率,以达到最佳的效果。

模型训练完成后,每一个特征函数有一个权重,这个权重表示该特征函数对标注序列的评分和概率的贡献程度。特征函数的权重可以通过最大似然估计(Maximum Likelihood Estimation,简称 MLE)或最大后验估计(Maximum A Posteriori,简称 MAP)来求解,这两种方法都是基于训练数据来优化对数似然函数或对数后验概率的方法,可以用梯度下降(Gradient Descent)或拟牛顿法(Quasi-Newton Method)等优化算法来实现。

8873f9a0e4e80ee4fd6caa596d633250.png

三、推断算法

42467c8706ff426246245e38ab29dca8.png

03e5207c13ec25b1d0c48a6b235b3681.png

四、训练算法

采用最大似然估计训练条件随机场

2c6436e383e6d87014aa796539809a81.png

最大似然估计L-BFGS求解

f9d01609ff137b5ef7d02cd5de9f6e1b.png

采用最大后验估计训练条件随机场

8cf5c7d8cdff37a69ea5df1f7e040683.png

五、应用场景

00e8e3b7f0371a16c22f75d863d92a8c.png

72c63944ed1341072d019e06eb114360.png

六、示例:NER-命名实体识别

bc4297cb91b2a1a0ec1212a08fac360f.png

129c6cf4a49b820a2b90330dc7e0e6e7.png

068ceb28cd9a8ae1590e9c7ac43e0f4d.png

这是一个基于条件随机场(CRF)的中文命名实体识别代码实现。主要步骤如下:

  1. CorpusProcess类:

  • 实现了语料的预处理,包括全半角转换、合并分词、转换词性标签等

  • 初始化了字序列、词性序列、标签序列

  • 提取特征

  1. CRF_NER类:

  • 初始化CRF模型的参数

  • 训练模型:使用训练集训练CRF模型

  • 预测:加载模型,对输入句子进行词性标注和命名实体识别

  1. 主要依赖库:

  • sklearn_crfsuite:条件随机场模型

  • joblib:模型保存和加载

  1. 训练过程:

  • 使用人民日报1998年语料进行训练

  • 训练好的模型保存为model.pkl

  1. 使用方式:

  • 直接加载模型预测,无需重新训练

  • 输入汉字句子,输出识别的命名实体

  1. 评价:

  • 实现了中文命名实体识别的条件随机场模型

  • 语料预处理和特征提取设计合理

  • 模型训练和预测流程清晰

  • 对中文分词、词性标注和命名实体识别任务提供了很好的参考

综上所述,这是一份比较完整和典型的基于CRF的中文NER实现,内容充实,代码结构清晰,可以很好地帮助理解CRF在NER任务中的应用和实现过程。

输出结果:

0ca8864119498ee5ddc40dac1454590d.png

源码

import re # 导入正则表达式模块
import sklearn_crfsuite # 导入条件随机场模块
from sklearn_crfsuite import metrics # 导入评估指标模块
import joblib # 导入模型保存和加载模块




class CorpusProcess(object): # 定义一个语料处理类


    def __init__(self): # 初始化方法
        """初始化"""
        self.train_corpus_path ="1980_01.txt" # 训练语料的路径
        self.process_corpus_path ="result-rmrb.txt" # 处理后的语料的路径
        self._maps = {u't': u'T', u'nr': u'PER', u'ns': u'ORG', u'nt': u'LOC'} # 词性标注和实体标注的映射关系


    def read_corpus_from_file(self, file_path): # 定义一个从文件中读取语料的方法
        """读取语料"""
        f = open(file_path, 'r', encoding='utf-8') # 以只读模式打开文件
        lines = f.readlines() # 读取所有行
        f.close() # 关闭文件
        return lines # 返回读取的内容


    def write_corpus_to_file(self, data, file_path): # 定义一个将语料写入文件的方法
        """写语料"""
        f = open(file_path, 'wb') # 以二进制写入模式打开文件
        f.write(data) # 写入数据
        f.close() # 关闭文件


    def q_to_b(self, q_str): # 定义一个将全角字符转换为半角字符的方法
        """全角转半角"""
        b_str = "" # 初始化一个空字符串
        for uchar in q_str: # 遍历全角字符串中的每个字符
            inside_code = ord(uchar) # 获取字符的 Unicode 编码
            if inside_code == 12288:  # 如果是全角空格,直接转换为半角空格
                inside_code = 32
            elif 65374 >= inside_code >= 65281:  # 如果是其他全角字符(除空格),根据关系转化为半角字符
                inside_code -= 65248
            b_str += chr(inside_code) # 将转换后的字符拼接到半角字符串中
        return b_str # 返回半角字符串


    def b_to_q(self, b_str): # 定义一个将半角字符转换为全角字符的方法
        """半角转全角"""
        q_str = "" # 初始化一个空字符串
        for uchar in b_str: # 遍历半角字符串中的每个字符
            inside_code = ord(uchar) # 获取字符的 Unicode 编码
            if inside_code == 32:  # 如果是半角空格,直接转化为全角空格
                inside_code = 12288
            elif 126 >= inside_code >= 32:  # 如果是其他半角字符(除空格),根据关系转化为全角字符
                inside_code += 65248
            q_str += chr(inside_code) # 将转换后的字符拼接到全角字符串中
        return q_str # 返回全角字符串


    def pre_process(self): # 定义一个语料预处理的方法
        """语料预处理 """
        lines = self.read_corpus_from_file(self.train_corpus_path) # 从训练语料的路径读取语料
        new_lines = [] # 初始化一个空列表,用于存储处理后的语料
        for line in lines: # 遍历每一行语料
            words = self.q_to_b(line.strip()).split(u'  ') # 将全角字符转换为半角字符,并去除首尾空格,然后按空格分割成词
            pro_words = self.process_t(words) # 处理时间词
            pro_words = self.process_nr(pro_words) # 处理人名
            pro_words = self.process_k(pro_words) # 处理大粒度分词
            new_lines.append('  '.join(pro_words[1:])) # 将处理后的词拼接成一行,并添加到新的语料列表中
        self.write_corpus_to_file(data='\n'.join(new_lines).encode('utf-8'), file_path=self.process_corpus_path) # 将新的语料列表写入到处理后的语料的路径


    def process_k(self, words): # 定义一个处理大粒度分词的方法
        """处理大粒度分词,合并语料库中括号中的大粒度分词,类似:[国家/n  环保局/n]nt """
        pro_words = [] # 初始化一个空列表,用于存储处理后的词
        index = 0 # 初始化一个索引,用于遍历词列表
        temp = u'' # 初始化一个空字符串,用于存储括号中的词
        while True: # 循环直到遍历完所有词或者遇到空词
            word = words[index] if index < len(words) else u'' # 获取当前索引对应的词,如果索引超出词列表的长度,就返回空字符串
            if u'[' in word: # 如果词中包含左括号
                temp += re.sub(pattern=u'/[a-zA-Z]*', repl=u'', string=word.replace(u'[', u'')) # 去除词性标注,并去除左括号,然后添加到临时字符串中
            elif u']' in word: # 如果词中包含右括号
                w = word.split(u']') # 按右括号分割词
                temp += re.sub(pattern=u'/[a-zA-Z]*', repl=u'', string=w[0]) # 去除词性标注,并添加到临时字符串中
                pro_words.append(temp + u'/' + w[1]) # 将临时字符串和右括号后的词性标注拼接起来,并添加到处理后的词列表中
                temp = u'' # 清空临时字符串
            elif temp: # 如果临时字符串不为空
                temp += re.sub(pattern=u'/[a-zA-Z]*', repl=u'', string=word) # 去除词性标注,并添加到临时字符串中
            elif word: # 如果词不为空
                pro_words.append(word) # 直接添加到处理后的词列表中
            else: # 如果词为空,表示遍历完所有词
                break # 跳出循环
            index += 1 # 索引加一
        return pro_words # 返回处理后的词列表
    
    def process_nr(self, words):
        """ 处理姓名,合并语料库分开标注的姓和名,类似:温/nr  家宝/nr"""
        pro_words = [] # 初始化一个空列表,用于存储处理后的词
        index = 0 # 初始化一个索引,用于遍历词列表
        while True: # 循环直到遍历完所有词或者遇到空词
            word = words[index] if index < len(words) else u'' # 获取当前索引对应的词,如果索引超出词列表的长度,就返回空字符串
            if u'/nr' in word: # 如果词中包含人名词性标注
                next_index = index + 1 # 获取下一个索引
                if next_index < len(words) and u'/nr' in words[next_index]: # 如果下一个词也包含人名词性标注
                    pro_words.append(word.replace(u'/nr', u'') + words[next_index]) # 去除词性标注,并将两个词合并为一个词,添加到处理后的词列表中
                    index = next_index # 更新索引为下一个索引
                else: # 如果下一个词不包含人名词性标注
                    pro_words.append(word) # 直接添加当前词到处理后的词列表中
            elif word: # 如果词不为空
                pro_words.append(word) # 直接添加当前词到处理后的词列表中
            else: # 如果词为空,表示遍历完所有词
                break # 跳出循环
            index += 1 # 索引加一
        return pro_words # 返回处理后的词列表


    def process_t(self, words):
        """处理时间,合并语料库分开标注的时间词,类似:(/w  一九九七年/t  十二月/t  三十一日/t  )/w   """
        pro_words = [] # 初始化一个空列表,用于存储处理后的词
        index = 0 # 初始化一个索引,用于遍历词列表
        temp = u'' # 初始化一个空字符串,用于存储时间词
        while True: # 循环直到遍历完所有词或者遇到空词
            word = words[index] if index < len(words) else u'' # 获取当前索引对应的词,如果索引超出词列表的长度,就返回空字符串
            if u'/t' in word: # 如果词中包含时间词性标注
                temp = temp.replace(u'/t', u'') + word # 去除词性标注,并将词添加到临时字符串中
            elif temp: # 如果临时字符串不为空
                pro_words.append(temp) # 将临时字符串添加到处理后的词列表中
                pro_words.append(word) # 将当前词添加到处理后的词列表中
                temp = u'' # 清空临时字符串
            elif word: # 如果词不为空
                pro_words.append(word) # 直接添加当前词到处理后的词列表中
            else: # 如果词为空,表示遍历完所有词
                break # 跳出循环
            index += 1 # 索引加一
        return pro_words # 返回处理后的词列表


    def pos_to_tag(self, p):
        """由词性提取标签"""
        t = self._maps.get(p, None) # 根据词性在映射关系中查找对应的标签,如果没有找到,就返回 None
        return t if t else u'O' # 如果找到了标签,就返回标签,否则返回 O


    def tag_perform(self, tag, index):
        """标签使用BIO模式"""
        if index == 0 and tag != u'O': # 如果是第一个词并且标签不是 O
            return u'B_{}'.format(tag) # 返回 B_标签
        elif tag != u'O': # 如果不是第一个词并且标签不是 O
            return u'I_{}'.format(tag) # 返回 I_标签
        else: # 如果标签是 O
            return tag # 返回 O


    def pos_perform(self, pos):
        """去除词性携带的标签先验知识"""
        if pos in self._maps.keys() and pos != u't': # 如果词性在映射关系的键中并且不是时间词
            return u'n' # 返回 n
        else: # 否则
            return pos # 返回原词性


    def initialize(self):
        """初始化 """
        lines = self.read_corpus_from_file(self.process_corpus_path) # 从处理后的语料的路径读取语料
        words_list = [line.strip().split('  ') for line in lines if line.strip()] # 将每一行语料去除首尾空格,并按空格分割成词,存储到一个列表中
        del lines # 删除语料变量,释放内存
        self.init_sequence(words_list) # 调用初始化字序列、词性序列、标记序列的方法


    def init_sequence(self, words_list):
        """初始化字序列、词性序列、标记序列 """
        words_seq = [[word.split(u'/')[0] for word in words] for words in words_list] # 将每个词按 / 分割,取第一个元素作为字,存储到一个列表中
        pos_seq = [[word.split(u'/')[1] for word in words] for words in words_list] # 将每个词按 / 分割,取第二个元素作为词性,存储到一个列表中
        tag_seq = [[self.pos_to_tag(p) for p in pos] for pos in pos_seq] # 将每个词性转换为对应的标签,存储到一个列表中
        self.pos_seq = [[[pos_seq[index][i] for _ in range(len(words_seq[index][i]))]
                         for i in range(len(pos_seq[index]))] for index in range(len(pos_seq))] # 将每个词性复制为与字相同的个数,存储到一个列表中
        self.tag_seq = [[[self.tag_perform(tag_seq[index][i], w) for w in range(len(words_seq[index][i]))]
                         for i in range(len(tag_seq[index]))] for index in range(len(tag_seq))] # 将每个标签按 BIO 模式转换,并复制为与字相同的个数,存储到一个列表中
        self.pos_seq = [[u'un'] + [self.pos_perform(p) for pos in pos_seq for p in pos] + [u'un'] for pos_seq in
                        self.pos_seq] # 将每个词性去除先验知识,并在首尾添加 un 标记,存储到一个列表中
        self.tag_seq = [[t for tag in tag_seq for t in tag] for tag_seq in self.tag_seq] # 将每个标签展平为一维列表,存储到一个列表中
        self.word_seq = [[u'<BOS>'] + [w for word in word_seq for w in word] + [u'<EOS>'] for word_seq in words_seq] # 将每个字展平为一维列表,并在首尾添加 <BOS> 和 <EOS> 标记,存储到一个列表中


    def extract_feature(self, word_grams):
        """特征选取"""
        features, feature_list = [], [] # 初始化两个空列表,用于存储特征和特征列表
        for index in range(len(word_grams)): # 遍历每个字窗口的索引
            for i in range(len(word_grams[index])): # 遍历每个字窗口中的每个字的索引
                word_gram = word_grams[index][i] # 获取当前字窗口中的当前字
                feature = {u'w-1': word_gram[0], u'w': word_gram[1], u'w+1': word_gram[2], # 构造一个特征字典,包含当前字的前一个字、当前字、后一个字,以及它们的组合
                           u'w-1:w': word_gram[0] + word_gram[1], u'w:w+1': word_gram[1] + word_gram[2],
                           # u'p-1': self.pos_seq[index][i], u'p': self.pos_seq[index][i+1], # 注释掉的部分是词性特征,这里不使用
                           # u'p+1': self.pos_seq[index][i+2],
                           # u'p-1:p': self.pos_seq[index][i]+self.pos_seq[index][i+1],
                           # u'p:p+1': self.pos_seq[index][i+1]+self.pos_seq[index][i+2],
                           u'bias': 1.0} # 添加一个偏置项,用于增加模型的灵活性
                feature_list.append(feature) # 将特征字典添加到特征列表中
            features.append(feature_list) # 将特征列表添加到特征中
            feature_list = [] # 清空特征列表,用于下一个字窗口
        return features # 返回特征


    def segment_by_window(self, words_list=None, window=3):
        """窗口切分"""
        words = [] # 初始化一个空列表,用于存储字窗口
        begin, end = 0, window # 初始化开始和结束的索引,分别为 0 和窗口大小
        for _ in range(1, len(words_list)): # 遍历字列表的长度
            if end > len(words_list): break # 如果结束的索引超出了字列表的长度,就跳出循环
            words.append(words_list[begin:end]) # 将字列表中从开始到结束的部分添加到字窗口中
            begin = begin + 1 # 更新开始的索引为原来加一
            end = end + 1 # 更新结束的索引为原来加一
        return words # 返回字窗口


    def generator(self):
        """训练数据"""
        word_grams = [self.segment_by_window(word_list) for word_list in self.word_seq] # 将每个字序列按窗口切分,得到字窗口
        features = self.extract_feature(word_grams) # 提取字窗口的特征
        return features, self.tag_seq # 返回特征和标签序列


class CRF_NER(object): # 定义一个命名实体识别的类
    def __init__(self): # 初始化方法
        """初始化参数"""
        self.algorithm = "lbfgs" # 指定优化算法为 LBFGS
        self.c1 = "0.1" # 指定正则化系数 c1
        self.c2 = "0.1" # 指定正则化系数 c2
        self.max_iterations = 100 # 指定最大迭代次数
        self.model_path ="model.pkl" # 指定模型保存的路径
        self.corpus = CorpusProcess()  # 创建一个语料处理的实例
        self.corpus.pre_process()  # 对语料进行预处理
        self.corpus.initialize()  # 初始化语料
        self.model = None # 初始化模型为 None


    def initialize_model(self): # 定义一个初始化模型的方法
        """初始化"""
        algorithm = self.algorithm # 获取优化算法
        c1 = float(self.c1) # 获取正则化系数 c1
        c2 = float(self.c2) # 获取正则化系数 c2
        max_iterations = int(self.max_iterations) # 获取最大迭代次数
        self.model = sklearn_crfsuite.CRF(algorithm=algorithm, c1=c1, c2=c2, # 创建一个条件随机场的模型,传入相应的参数
                                          max_iterations=max_iterations, all_possible_transitions=True)


    def train(self): # 定义一个训练模型的方法
        """训练"""
        self.initialize_model() # 调用初始化模型的方法
        x, y = self.corpus.generator() # 从语料中生成特征和标签
        x_train, y_train = x[500:], y[500:] # 将后 500 个样本作为训练集
        x_test, y_test = x[:500], y[:500] # 将前 500 个样本作为测试集
        self.model.fit(x_train, y_train) # 用训练集拟合模型
        labels = list(self.model.classes_) # 获取模型的所有标签
        labels.remove('O') # 移除 O 标签,表示非实体
        y_predict = self.model.predict(x_test) # 用模型对测试集进行预测
        metrics.flat_f1_score(y_test, y_predict, average='weighted', labels=labels) # 计算加权平均的 F1 分数,只考虑实体标签
        sorted_labels = sorted(labels, key=lambda name: (name[1:], name[0])) # 对标签按照 BIO 模式进行排序
        print(metrics.flat_classification_report(y_test, y_predict, labels=sorted_labels, digits=3)) # 打印分类报告,包括精确度、召回率、F1 分数等指标
        self.save_model() # 调用保存模型的方法


    def predict(self, sentence): # 定义一个预测方法,输入一个句子,输出实体
        """预测"""
        self.load_model() # 调用加载模型的方法
        u_sent = self.corpus.q_to_b(sentence) # 将句子中的全角字符转换为半角字符
        word_lists = [[u'<BOS>'] + [c for c in u_sent] + [u'<EOS>']] # 将句子中的每个字作为一个词,并在首尾添加特殊标记
        word_grams = [self.corpus.segment_by_window(word_list) for word_list in word_lists] # 将每个词按照窗口切分,得到字窗口
        features = self.corpus.extract_feature(word_grams) # 提取字窗口的特征
        y_predict = self.model.predict(features) # 用模型对特征进行预测,得到标签
        entity = u'' # 初始化一个空字符串,用于存储实体
        for index in range(len(y_predict[0])): # 遍历每个预测的标签的索引
            if y_predict[0][index] != u'O': # 如果标签不是 O,表示是实体
                if index > 0 and y_predict[0][index][-1] != y_predict[0][index - 1][-1]: # 如果不是第一个字,并且当前标签的实体类型和前一个标签的实体类型不同
                    entity += u' ' # 在实体字符串中添加一个空格,用于分隔不同的实体
                entity += u_sent[index] # 在实体字符串中添加当前字
            elif entity[-1] != u' ': # 如果标签是 O,表示不是实体,并且实体字符串的最后一个字符不是空格
                entity += u' ' # 在实体字符串中添加一个空格,用于分隔不同的实体
        return entity # 返回实体字符串


    def load_model(self): # 定义一个加载模型的方法
        """加载模型 """
        self.model = joblib.load(self.model_path) # 从模型保存的路径加载模型


    def save_model(self): # 定义一个保存模型的方法
        """保存模型"""
        joblib.dump(self.model, self.model_path) # 将模型保存到指定的路径




if __name__=="__main__": # 如果是主程序


    ner = CRF_NER() # 创建一个命名实体识别的实例
    #训练模型,当训练完毕后,就可以直接加载模型参数,不用再次训练了
    #mode=ner.train() # 调用训练模型的方法,这里注释掉,表示不用再次训练


    result1=ner.predict(u'新华社北京十二月三十一日电(中央人民广播电台记者刘振英、新华社记者张宿堂)今天是一九九七年的最后一天。') # 调用预测方法,输入一个句子
    print(result1) # 打印预测的结果
    result2=ner.predict(u'中国,我爱你。') # 调用预测方法,输入另一个句子
    print(result2) # 打印预测的结果

参考网址:

https://www.jianshu.com/p/7fa260e91382

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/321351.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

EMC VNXe / Unity存储系统如何找回密码

开始之前&#xff0c;先简单说说&#xff0c;EMC的VNXe存储之间的关系。 EMC的VNXe和Unity存储的操作系统OS是一样的&#xff0c;当然不是完全一样&#xff0c;但是架构是一样的&#xff0c;先推出的产品是VNXe&#xff0c;然后在这个基础上演进到了Unity&#xff0c;Unity XT…

(菜鸟自学)搭建虚拟渗透实验室——安装Kali Linux

安装Kali Linux Kali Linux 是一种基于 Debian 的专为渗透测试和网络安全应用而设计的开源操作系统。它提供了广泛的渗透测试工具和安全审计工具&#xff0c;使安全专业人员和黑客可以评估和增强网络的安全性。 安装KaliLinux可参考我的另一篇文章《Kali Linux的下载安装以及基…

MySQL的多版本并发控制(MVCC)

MVCC MVCC&#xff0c;是Multiversion Concurrency Control的缩写&#xff0c;翻译过来是多版本并发控制&#xff0c;和数据库锁样&#xff0c;他也是一种并发控制的解决方案 我们知道&#xff0c;在数据库中&#xff0c;对数据的操作主要有2种&#xff0c;分别是读和写&…

Pushmall智能AI数字名片— —SCRM客户资源管理系统

推贴数字AI名片说明&#xff1a; **Pushmall智能AI数字名片&#xff1a;**基于靠谱人脉的地理位置服务&#xff0c;资源查询&#xff0c;数字名片定制服务、企业名片&#xff1a;相互引荐、提供需求&#xff1b;建人脉群、客户群&#xff0c;及简介、短视频、宣传文档、电子图…

逸学Docker【java工程师基础】3.1安装Jenkins

1.下载镜像 docker pull jenkins/jenkins:lts 2.运行容器 docker run -d -u root -p 8080:8080 -p 50000:50000 -v /var/jenkins_home:/var/jenkins_home -v /etc/localtime:/etc/localtime --name jenkins jenkins/jenkins:lts 3.要启动名为 jenkins 的 Docker 容器 docker st…

Logstash应用-同步ES(elasticsearch)到HDFS

1.场景分析 现有需求需要将elasticsearch的备份至hdfs存储&#xff0c;根据以上需求&#xff0c;使用logstash按照天级别进行数据的同步 2.重难点 数据采集存在时间漂移问题&#xff0c;数据保存时使用的是采集时间而不是数据生成时间采用webhdfs无法对文件大小进行设置解决…

Codeforces Round 768 (Div. 1) D. Flipping Range(思维题 等价类性质 dp)

题目 思路来源 官方题解 洛谷题解 题解 可操作的最短区间长度肯定是gcd&#xff0c;记为g&#xff0c;然后考虑如何dp 考虑g个等价类&#xff0c;每个等价类i,ig,i2*g,... 每次翻转长度为g的区间&#xff0c;会同时影响到g个等价类总的翻转的奇偶性&#xff0c; 性质一&…

叉车车载终端定制_基于MT6762安卓核心板的车载终端设备方案

叉车车载终端是一款专为叉车车载场景设计的4英寸Android车载平板电脑。它采用了高能低耗的8核ARM架构处理器和交互开放的Android 12操作系统&#xff0c;算力表现强大。此外&#xff0c;该产品还具备丰富的Wi-Fi-5、4G LTE和蓝牙等通讯功能&#xff0c;可选配外部车载蘑菇天线&…

记录centos7.9 离线安装fastllm 编译遇到的问题

centos7.9 安装fastllm 编译步骤 Step1安装cmake: 参考: https://bitsanddragons.wordpress.com/2022/09/19/error-cmake-3-1-or-higher-is-required-you-are-running-version-on-centos-7-x/ ​ 问题1&#xff1a;/lib64/libstdc.so.6: version GLIBCXX_3.4.20‘ not found …

C语言程序设计——程序流程控制方法(二)

循环结构 while语句 while(表达式){代码块; }do{代码块; }while(表达式)while语句分为do-while和while两种&#xff0c;区别在于循环之前是不是先执行一次循环的内容&#xff0c;可以类似于i和i的关系&#xff0c;本质上来讲是相同的。当表达式为真时&#xff0c;则会执行一次…

常用的排序算法

该文章笔记结合菜鸟教程的排序算法&#xff0c;如果后面认识有改动或者完善再继续 最近笔试很多题目都考察过了基本的排序算法&#xff0c;尤其是快排、冒泡、选择&#xff0c;大家在这一方面一定要注意下。 一. 总述 1. 时间复杂度 详细介绍 1. 冒泡排序 冒泡排序重复地走…

大白菜U盘安装系统-戴尔电脑

1. 把U盘插入电脑&#xff0c;启动盘去大白菜官网找&#xff0c;镜像可以去微软官网下&#xff0c;想要专业版的网上找资源。 2. 重启电脑&#xff0c;等出现log之后狂按F12&#xff0c;进入BOSS模式。 3. 选择UEFI...也就是下面白色的&#xff0c;按下回车。 4. 选第一个 5.…

生成学习全景:从基础理论到GANs技术实战

本文全面探讨了生成学习的理论与实践&#xff0c;包括对生成学习与判别学习的比较、详细解析GANs、VAEs及自回归模型的工作原理与结构&#xff0c;并通过实战案例展示了GAN模型在PyTorch中的实现。 关注TechLead&#xff0c;分享AI全维度知识。作者拥有10年互联网服务架构、AI产…

基于java的SSM框架实现在线投稿网站系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架Vue实现在线投稿网站系统演示 摘要 随着计算机技术的飞速发展&#xff0c;稿件也已进入信息化时代。为了使稿件管理更高效、更科学&#xff0c;决定开发投稿审稿系统。 本文采用自顶向下的结构化的系统分析方法&#xff0c;阐述了一个功能全面的投稿审稿系统…

Open3D 两片点云的最小/最大距离(23)

Open3D 两片点云的最小/最大距离(23) 一、效果展示二、使用步骤1.代码三、cloudcompare量距小工具一、效果展示 算法与实际量测的结果保持一致,输出最近距离和对应点 二、使用步骤 1.代码 import open3d as o3d import numpy as np# 读取点云数据 cloud_2 = o3d.io.re…

性能瓶颈分析定位

用vmstat、sar、iostat检测是否是CPU瓶颈 用free、vmstat检测是否是内存瓶颈 用iostat、dmesg 检测是否是磁盘I/O瓶颈 用netstat检测是否是网络带宽瓶颈 1 首先进行OS层面的检查确认 首先要确认当前到底是哪些进程引起的负载高&#xff0c;以及这些进程卡在什么地方&#x…

软件需求分析报告—word

技术要求 1.1接口要求 1.2可靠性&#xff0c;稳定性&#xff0c;安全性&#xff0c;先进性&#xff0c;拓展性&#xff0c;性能&#xff0c;响应。 2.系统安全需求 2.1物理设计安全 2.2系统安全设计 2.3网络安全设计 2.4应用安全设计 2.5用户安全管理 进主页获取更多资料

目前目标跟踪算法研究202308

目标跟踪算法综述——附各算法源码和论文 概述 TBD&#xff08;two-shot&#xff09;&#xff1a;SORT、DeepSORT、StrongSORT、ByteTrack、OC-SORT JDE&#xff08;one-shot&#xff09;&#xff1a;BoT-SORT、 0 MutiSORT(多目标跟踪策略) 0.1 trackdetection 训练一个网…

Java基础语法

1.第一份程序 1.1.代码编写 /*块注释 HelloWord.java 内部 *//**文档注释 * 作者&#xff1a;limou3434 */ public class HelloWord {public static void main(String[] args){System.out.println("Hello Word!");//打印“Hello Word!”} }直接上代码&#xff0c;上…

工具篇--SpringCloud--openFeign--Feign.builder()自定义客户端

文章目录 前言一、自定义客户端&#xff1a;1.1 定义外部接口类&#xff1a;1.2 接口代理类生成&#xff1a;1.3 方法的远程调用&#xff1a; 二、Feign.builder()自定义客户端原理&#xff1a;2.1 FeignClientFactoryBean2.2 客户端的配置设置&#xff1a;2.3 代理类的生成&am…
最新文章