基于 chinese-roberta-wwm-ext 微调训练中文命名实体识别任务

一、模型和数据集介绍

1.1 预训练模型

chinese-roberta-wwm-ext 是基于 RoBERTa 架构下开发,其中 wwm 代表 Whole Word Masking,即对整个词进行掩码处理,通过这种方式,模型能够更好地理解上下文和语义关联,提高中文文本处理的准确性和效果。

与原始的 BERT 模型相比,chinese-roberta-wwm-ext 在训练数据规模和训练步数上做了一些调整,以进一步提升模型的性能和鲁棒性。并且在大规模无监督语料库上进行了预训练,使其具备强大的语言理解和生成能力。它能够广泛应用于各种自然语言处理任务,如文本分类、命名实体识别、情感分析等。我们可以使用这个模型作为基础,在不同的任务上进行微调和迁移学习,以实现更准确、高效的中文文本处理。

huggingface地址:https://huggingface.co/hfl/chinese-roberta-wwm-ext

进到 huggingface 中下载预训练模型:

在这里插入图片描述

1.2 数据集

数据集采用 CLUENER(中文语言理解测评基准)2020数据集

进入下面链接下载数据集:

https://www.cluebenchmarks.com/introduce.html

在这里插入图片描述

数据分为10个标签类别,分别为: 地址(address),书名(book),公司(company),游戏(game),政府(goverment),电影(movie),姓名(name),组织机构(organization),职位(position),景点(scene

数据实例如下:

{"text": "浙商银行企业信贷部叶老桂博士则从另一个角度对五道门槛进行了解读。叶老桂认为,对目前国内商业银行而言,", "label": {"name": {"叶老桂": [[9, 11]]}, "company": {"浙商银行": [[0, 3]]}}}
{"text": "生生不息CSOL生化狂潮让你填弹狂扫", "label": {"game": {"CSOL": [[4, 7]]}}}
{"text": "那不勒斯vs锡耶纳以及桑普vs热那亚之上呢?", "label": {"organization": {"那不勒斯": [[0, 3]], "锡耶纳": [[6, 8]], "桑普": [[11, 12]], "热那亚": [[15, 17]]}}}
{"text": "加勒比海盗3:世界尽头》的去年同期成绩死死甩在身后,后者则即将赶超《变形金刚》,", "label": {"movie": {"加勒比海盗3:世界尽头》": [[0, 11]], "《变形金刚》": [[33, 38]]}}}
{"text": "布鲁京斯研究所桑顿中国中心研究部主任李成说,东亚的和平与安全,是美国的“核心利益”之一。", "label": {"address": {"美国": [[32, 33]]}, "organization": {"布鲁京斯研究所桑顿中国中心": [[0, 12]]}, "name": {"李成": [[18, 19]]}, "position": {"研究部主任": [[13, 17]]}}}
{"text": "目前主赞助商暂时空缺,他们的球衣上印的是“unicef”(联合国儿童基金会),是公益性质的广告;", "label": {"organization": {"unicef": [[21, 26]], "联合国儿童基金会": [[29, 36]]}}}
{"text": "此数据换算成亚洲盘罗马客场可让平半低水。", "label": {"organization": {"罗马": [[9, 10]]}}}
{"text": "你们是最棒的!#英雄联盟d学sanchez创作的原声王", "label": {"game": {"英雄联盟": [[8, 11]]}}}
{"text": "除了吴湖帆时现精彩,吴待秋、吴子深、冯超然已然归入二三流了,", "label": {"name": {"吴湖帆": [[2, 4]], "吴待秋": [[10, 12]], "吴子深": [[14, 16]], "冯超然": [[18, 20]]}}}
{"text": "在豪门被多线作战拖累时,正是他们悄悄追赶上来的大好时机。重新找回全队的凝聚力是拉科赢球的资本。", "label": {"organization": {"拉科": [[39, 40]]}}}

首先将数据集转换成 BIO 标注格式:

import json# 将数据转为  BIO 标注形式
def dimension_label(path, save_path, labels_path=None):label_dict = ['O']with open(save_path, "a", encoding="utf-8") as w:with open(path, "r", encoding="utf-8") as r:for line in r:line = json.loads(line)text = line['text']label = line['label']text_label = ['O'] * len(text)for label_key in label:  # 遍历实体标签B_label = "B-" + label_keyI_label = "I-" + label_keyif B_label not in label_dict:label_dict.append(B_label)if I_label not in label_dict:label_dict.append(I_label)label_item = label[label_key]for entity in label_item:  # 遍历实体position = label_item[entity]start = position[0][0]end = position[0][1]text_label[start] = B_labelfor i in range(start + 1, end + 1):text_label[i] = I_labelline = {"text": text,"label": text_label}line = json.dumps(line, ensure_ascii=False)w.write(line + "\n")w.flush()if labels_path:  # 保存 label ,后续训练和预测时使用label_map = {}for i,label in enumerate(label_dict):label_map[label] = iwith open(labels_path, "w", encoding="utf-8") as w:labels = json.dumps(label_map, ensure_ascii=False)w.write(labels + "\n")w.flush()if __name__ == '__main__':path = "./cluener_public/dev.json"save_path = "./data/dev.json"dimension_label(path, save_path)path = "./cluener_public/train.json"save_path = "./data/train.json"labels_path = "./data/labels.json"dimension_label(path, save_path, labels_path)

转换后的格式如下所示:

{"text": "浙商银行企业信贷部叶老桂博士则从另一个角度对五道门槛进行了解读。叶老桂认为,对目前国内商业银行而言,", "label": ["B-company", "I-company", "I-company", "I-company", "O", "O", "O", "O", "O", "B-name", "I-name", "I-name", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O"]}
{"text": "生生不息CSOL生化狂潮让你填弹狂扫", "label": ["O", "O", "O", "O", "B-game", "I-game", "I-game", "I-game", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O"]}
{"text": "那不勒斯vs锡耶纳以及桑普vs热那亚之上呢?", "label": ["B-organization", "I-organization", "I-organization", "I-organization", "O", "O", "B-organization", "I-organization", "I-organization", "O", "O", "B-organization", "I-organization", "O", "O", "B-organization", "I-organization", "I-organization", "O", "O", "O", "O"]}
{"text": "加勒比海盗3:世界尽头》的去年同期成绩死死甩在身后,后者则即将赶超《变形金刚》,", "label": ["B-movie", "I-movie", "I-movie", "I-movie", "I-movie", "I-movie", "I-movie", "I-movie", "I-movie", "I-movie", "I-movie", "I-movie", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "B-movie", "I-movie", "I-movie", "I-movie", "I-movie", "I-movie", "O"]}
{"text": "布鲁京斯研究所桑顿中国中心研究部主任李成说,东亚的和平与安全,是美国的“核心利益”之一。", "label": ["B-organization", "I-organization", "I-organization", "I-organization", "I-organization", "I-organization", "I-organization", "I-organization", "I-organization", "I-organization", "I-organization", "I-organization", "I-organization", "B-position", "I-position", "I-position", "I-position", "I-position", "B-name", "I-name", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "B-address", "I-address", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O"]}
{"text": "目前主赞助商暂时空缺,他们的球衣上印的是“unicef”(联合国儿童基金会),是公益性质的广告;", "label": ["O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "B-organization", "I-organization", "I-organization", "I-organization", "I-organization", "I-organization", "O", "O", "B-organization", "I-organization", "I-organization", "I-organization", "I-organization", "I-organization", "I-organization", "I-organization", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O"]}
{"text": "此数据换算成亚洲盘罗马客场可让平半低水。", "label": ["O", "O", "O", "O", "O", "O", "O", "O", "O", "B-organization", "I-organization", "O", "O", "O", "O", "O", "O", "O", "O", "O"]}
{"text": "你们是最棒的!#英雄联盟d学sanchez创作的原声王", "label": ["O", "O", "O", "O", "O", "O", "O", "O", "B-game", "I-game", "I-game", "I-game", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O"]}
{"text": "除了吴湖帆时现精彩,吴待秋、吴子深、冯超然已然归入二三流了,", "label": ["O", "O", "B-name", "I-name", "I-name", "O", "O", "O", "O", "O", "B-name", "I-name", "I-name", "O", "B-name", "I-name", "I-name", "O", "B-name", "I-name", "I-name", "O", "O", "O", "O", "O", "O", "O", "O", "O"]}
{"text": "在豪门被多线作战拖累时,正是他们悄悄追赶上来的大好时机。重新找回全队的凝聚力是拉科赢球的资本。", "label": ["O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "B-organization", "I-organization", "O", "O", "O", "O", "O", "O"]}

labels.json 标签如下:

{"O": 0, "B-name": 1, "I-name": 2, "B-company": 3, "I-company": 4, "B-game": 5, "I-game": 6, "B-organization": 7, "I-organization": 8, "B-movie": 9, "I-movie": 10, "B-address": 11, "I-address": 12, "B-position": 13, "I-position": 14, "B-government": 15, "I-government": 16, "B-scene": 17, "I-scene": 18, "B-book": 19, "I-book": 20}

二、模型微调训练

2.1 处理数据集构建 Dataset

ner_datasets.py

from torch.utils.data import Dataset, DataLoader
import torch
import jsonclass NERDataset(Dataset):def __init__(self, tokenizer, file_path, labels_map, max_length=300):self.tokenizer = tokenizerself.max_length = max_lengthself.labels_map = labels_mapself.text_data = []self.label_data = []with open(file_path, "r", encoding="utf-8") as r:for line in r:line = json.loads(line)text = line['text']label = line['label']self.text_data.append(text)self.label_data.append(label)def __len__(self):return len(self.text_data)def __getitem__(self, idx):text = self.text_data[idx]labels = self.label_data[idx]# 使用分词器对句子进行处理inputs = self.tokenizer.encode_plus(text,None,add_special_tokens=True,padding='max_length',truncation=True,max_length=self.max_length,return_tensors='pt')input_ids = inputs['input_ids'].squeeze()attention_mask = inputs['attention_mask'].squeeze()# 将标签转换为数字编码label_ids = [self.labels_map[l] for l in labels]if len(label_ids) > self.max_length:label_ids = label_ids[0:self.max_length]if len(label_ids) < self.max_length:# 标签填充到最大长度label_ids.extend([0] * (self.max_length - len(label_ids)))return {'input_ids': input_ids,'attention_mask': attention_mask,'labels': torch.LongTensor(label_ids)}

2.2 模型迭代训练

import torch
from torch.utils.data import Dataset, DataLoader
from transformers import AutoTokenizer, AutoModelForTokenClassification
from ner_datasets import NERDataset
from tqdm import tqdm
import json
import time, sys
import numpy as np
from sklearn.metrics import f1_scoredef train(epoch, model, device, loader, optimizer, gradient_accumulation_steps):model.train()time1 = time.time()for index, data in enumerate(tqdm(loader, file=sys.stdout, desc="Train Epoch: " + str(epoch))):input_ids = data['input_ids'].to(device)attention_mask = data['attention_mask'].to(device)labels = data['labels'].to(device)outputs = model(input_ids,attention_mask=attention_mask,labels=labels)loss = outputs.loss# 反向传播,计算当前梯度loss.backward()# 梯度累积步数if (index % gradient_accumulation_steps == 0 and index != 0) or index == len(loader) - 1:# 更新网络参数optimizer.step()# 清空过往梯度optimizer.zero_grad()# 100轮打印一次 lossif index % 100 == 0 or index == len(loader) - 1:time2 = time.time()tqdm.write(f"{index}, epoch: {epoch} -loss: {str(loss)} ; each step's time spent: {(str(float(time2 - time1) / float(index + 0.0001)))}")def validate(model, device, loader):model.eval()acc = 0f1 = 0with torch.no_grad():for _, data in enumerate(tqdm(loader, file=sys.stdout, desc="Validation Data")):input_ids = data['input_ids'].to(device)attention_mask = data['attention_mask'].to(device)labels = data['labels']outputs = model(input_ids, attention_mask=attention_mask)_, predicted_labels = torch.max(outputs.logits, dim=2)predicted_labels = predicted_labels.detach().cpu().numpy().tolist()true_labels = labels.detach().cpu().numpy().tolist()predicted_labels_flat = [label for sublist in predicted_labels for label in sublist]true_labels_flat = [label for sublist in true_labels for label in sublist]accuracy = (np.array(predicted_labels_flat) == np.array(true_labels_flat)).mean()acc = acc + accuracyf1score = f1_score(true_labels_flat, predicted_labels_flat, average='macro')f1 = f1 + f1scorereturn acc / len(loader), f1 / len(loader)def main():labels_path = "./data/labels.json"model_name = 'D:\\AIGC\\model\\chinese-roberta-wwm-ext'train_json_path = "./data/train.json"val_json_path = "./data/dev.json"max_length = 300epochs = 5batch_size = 1lr = 1e-4gradient_accumulation_steps = 16model_output_dir = "output"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')# 加载labelwith open(labels_path, "r", encoding="utf-8") as r:labels_map = json.loads(r.read())# 加载分词器和模型tokenizer = AutoTokenizer.from_pretrained(model_name)model = AutoModelForTokenClassification.from_pretrained(model_name, num_labels=len(labels_map))model.to(device)# 加载数据print("Start Load Train Data...")train_dataset = NERDataset(tokenizer, train_json_path, labels_map, max_length)train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)print("Start Load Validation Data...")val_dataset = NERDataset(tokenizer, val_json_path, labels_map, max_length)val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False)# 定义优化器和损失函数optimizer = torch.optim.AdamW(model.parameters(), lr=lr)print("Start Training...")best_acc = 0.0for epoch in range(epochs):train(epoch, model, device, train_loader, optimizer, gradient_accumulation_steps)print("Start Validation...")acc, f1 = validate(model, device, val_loader)print(f"Validation : acc: {acc} , f1: {f1}")if best_acc < acc: # 保存准确率最高的模型print("Save Model To ", model_output_dir)model.save_pretrained(model_output_dir)tokenizer.save_pretrained(model_output_dir)best_acc = accif __name__ == '__main__':main()

运行之后可以看到训练进度:

在这里插入图片描述

训练中可以看到验证集的准确率和f1 指标,并保存一个准确率最高的模型。
在这里插入图片描述

训练完成后,可以看到最后一轮的 acc: 0.988304790270546 , f1: 0.7567446800115455,在 output 下可以看到保存的模型文件:

在这里插入图片描述

三、模型测试

from transformers import AutoTokenizer, AutoModelForTokenClassification
import torch
import json# 解析实体
def post_processing(outputs, text, labels_map):_, predicted_labels = torch.max(outputs.logits, dim=2)predicted_labels = predicted_labels.detach().cpu().numpy()predicted_tags = [labels_map[label_id] for label_id in predicted_labels[0]]result = {}entity = ""type = ""for index, word_token in enumerate(text):tag = predicted_tags[index]if tag.startswith("B-"):type = tag.split("-")[1]if entity:if type not in result:result[type] = []result[type].append(entity)entity = word_tokenelif tag.startswith("I-"):type = tag.split("-")[1]if entity:entity += word_tokenelse:if entity:if type not in result:result[type] = []result[type].append(entity)entity = ""return resultdef main():labels_path = "./data/labels.json"model_name = './output'max_length = 300device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')# 加载labellabels_map = {}with open(labels_path, "r", encoding="utf-8") as r:labels = json.loads(r.read())for label in labels:label_id = labels[label]labels_map[label_id] = label# 加载分词器和模型tokenizer = AutoTokenizer.from_pretrained(model_name)model = AutoModelForTokenClassification.from_pretrained(model_name, num_labels=len(labels_map))model.to(device)while True:text = input("请输入:")if not text or text == '':continueif text == 'q':breakencoded_input = tokenizer(text, padding="max_length", truncation=True, max_length=max_length)input_ids = torch.tensor([encoded_input['input_ids']]).to(device)attention_mask = torch.tensor([encoded_input['attention_mask']]).to(device)outputs = model(input_ids, attention_mask=attention_mask)result = post_processing(outputs, text, labels_map)print(result)if __name__ == '__main__':main()

输入:根据北京市住房和城乡建设委员会总体工作部署,市建委调配给东城区118套房源,99户家庭全部来到现场

识别结果:

{'government': ['北京市住房和城乡建设委员会'], 'address': ['东城区']}

输入:为星际争霸2冠军颁奖的嘉宾是来自上海新闻出版局副局长陈丽女士。最后,为魔兽争霸3项目冠军—

识别结果:

{'game': ['星际争霸2', '魔兽争霸3'], 'position': ['上海新闻出版局'], 'name': ['副局长', '陈丽']}

输入:作出对成钢违纪辞退处理决定,并开具了退工单。今年8月,公安机关以不应当追究刑事责任为由

识别结果:

{'name': ['成钢'], 'government': ['公安机关']}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据仓库Hive(林子雨课程慕课)

文章目录 9.数据仓库Hive9.1 数据仓库的概念9.2 Hive简介9.3 SQL语句转换为MapReduce作业的基本原理9.4 Impla9.4.1 Impala简介9.4.2 Impala系统架构9.4.3 Impala查询执行过程9.4.4 Impala与Hive的比较 9.5 Hive的安装和基本操作9.5.1 Hive安装9.5.2 Hive基本操作 9.数据仓库Hi…

黑马点评-05缓存穿透问题及其解决方案,缓存空字符串或使用布隆过滤器

缓存穿透问题(缓存空) 缓存穿透的解决方案 缓存穿透(数据穿透缓存直击数据库): 缓存穿透是指客户端请求访问缓存中和数据库中都不存在的数据,此时缓存永远不会生效并且用户的请求都会打到数据库 数据库能够承载的并发不如Redis这么高&#xff0c;如果大量的请求同时访问这种…

十大排序算法Java实现及时间复杂度

文章目录 十大排序算法选择排序冒泡排序插入排序希尔排序快速排序归并排序堆排序计数排序基数排序桶排序时间复杂度 参考资料 十大排序算法 选择排序 原理 从待排序的数据元素中找出最小或最大的一个元素&#xff0c;存放在序列的起始位置&#xff0c; 然后再从剩余的未排序元…

C++类和对象(下)

目录 一、初始化列表 二、单参构造参数和explicit关键字 三、匿名对象 四、static成员 五、友元 六、内部类 一、初始化列表 之前我们在构造函数中写得还不错&#xff0c;也没发现什么问题&#xff0c;为什么C还有搞一个初始化列表呢&#xff1f; 如下这段代码&#x…

mars3d的api文档关于addDynamicPosition查找使用说明

示例链接&#xff1a;功能示例(Vue版) | Mars3D三维可视化平台 | 火星科技 api地址&#xff1a;Mars3D三维可视化平台 | 火星科技 说明&#xff1a; 1.用户反馈不知道如何搜索这个属性的用法 说明&#xff1a; 1. 示例代码中的graphic.addDynamicPosition()说明这个addDynam…

基本微信小程序的二手车交易平台

项目介绍 首先,论文一开始便是清楚的论述了小程序的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了小程序的需求基础上需要进一步地设计系统,主要包罗软件架构模式、整体功能模块、数…

@MultipartConfig注解

前言&#xff1a; 在学习Javaweb的Servlet文件上传和下载的过程中&#xff0c;我们会遇到一个特殊的注解---MultipartConfig。 MultipartConfig的适用情况&#xff1a; 1.文件上传: 当您的应用程序需要接收用户上传的文件时&#xff0c;可以在相应的 Servlet 上使用 Multipart…

Jmeter连接mysql数据库详细步骤

一、一般平常工作中使用jmeter 连接数据库的作用 主要包括&#xff1a; 1、本身对数据库进行测试&#xff08;功能、性能测试&#xff09;时会需要使用jmeter连接数据库 2、功能测试时&#xff0c;测试出来的结果需要和数据库中的数据进行对比是否正确一致。这时候可以通过j…

C++ 位图与布隆过滤器

目录 前言位图场景演示应用场景模拟实现问题例题 布隆过滤器例子理解应用 例题 前言 位图与布隆过滤器是用来在海量数据中判断一个数据在不在的问题的数据结构&#xff0c;这种数据结构在存储空间上大大的优于红黑树、哈希等数据结构 位图 我们为了处理一个数据在海量数据中…

SQL开发笔记之专栏介绍

Sql是用于访问和处理数据库的标准计算机语言&#xff0c;使用SQL访问和处理数据系统中的数据&#xff0c;这类数据库包括&#xff1a;Mysql、PostgresSql、Oracle、Sybase、DB2等等&#xff0c;数据库无非围绕着“增删改查”的核心业务进行开发。并且目前绝大多数的后端程序开发…

很烦的Node报错积累

目录 1. 卡在sill idealTree buildDeps2、Node Sass老是安装不上的问题3、unable to resolve dependency tree4、nvm相关命令5、设置淘宝镜像等基操5.1 镜像 5.2 npm清理缓存6、Browserslist: caniuse-lite is outdated loader 1. 卡在sill idealTree buildDeps 参考&#xf…

国际通用的Bug管理工具推荐:多款工具助力项目开发与管理

国际通用的bug管理工具有&#xff1a;1、Zoho Projects&#xff1b;2、Tracup&#xff1b;3、Bugtags&#xff1b;4、QC(QualityCenter)&#xff1b;5、Bugzilla&#xff1b;6、EasyBUG&#xff1b;7、Mantis&#xff1b;8、WebIssues。Zoho Projects拥有专业的缺陷管理模块&am…

复数的三角形式与指数形式

See https://blog.csdn.net/u011089570/article/details/102685877

深入了解基数排序:原理、性能分析与 Java 实现

基数排序&#xff08;Radix Sort&#xff09;是一种非比较性排序算法&#xff0c;它根据元素的每个位上的值来进行排序。基数排序适用于整数或字符串等数据类型的排序。本文将详细介绍基数排序的原理、性能分析及java实现。 基数排序原理 基数排序的基本原理是按照低位先排序&…

android 固定进度环形刷新效果

android 固定进度无限旋转的环形效果 效果图 Activity 中使用 val rotation: ObjectAnimator ObjectAnimator.ofFloat(progressBar, "rotation", 0f, 360f) rotation.duration 000 // 旋转持续时间为2秒 rotation.repeatCount ObjectAnimator.INFINITE // 设置为…

保姆式教程:MAC安装Android studio(包括安装JDK,Android SDK),解决gradle下载慢的问题

文章目录 参考文章安装JDK并配置环境变量安装JDK配置JDK相关的环境变量 Android studio 安装下载Android studiogradle下载慢解决方法 安装Android SDK选择jdk版本安装SDK并配置环境变量 参考文章 原文链接 原文链接 安装JDK并配置环境变量 安装JDK 下载地址 下载后双击安装…

优化|优化处理可再生希尔伯特核空间的非参数回归中的协变量偏移

原文&#xff1a;Optimally tackling covariate shift in RKHS-based nonparametric regression. The Annals of Statistics, 51(2), pp.738-761, 2023.​ 原文作者&#xff1a;Cong Ma, Reese Pathak, Martin J. Wainwright​ 论文解读者&#xff1a;赵进 编者按&#xff1a; …

mac上安装mysql

下载地址&#xff1a;https://downloads.mysql.com/archives/community/ 可以选择dmg安装包&#xff0c;也可以选择tar包。 1、dmg安装包&#xff1a; 1.1&#xff09;安装&#xff1a; 类似windows的exe&#xff0c;直接next即可。 注意&#xff1a;安装完成之后会弹出一个…

redis 哨兵 sentinel(一)配置

sentinel巡查监控后台master主机是否故障&#xff0c;如果故障根据投票数自动将某一个从库转换为新主库&#xff0c;继续对外服务 sentinel 哨兵的功能 监控 监控主从redis库运行是否正常消息通知 哨兵可以将故障转移的结果发送给客户端故障转移 如果master异常&#xff0c;则…

解锁远程联机模式:使用MCSM面板搭建我的世界服务器,并实现内网穿透公网访问

文章目录 前言1.Mcsmanager安装2.创建Minecraft服务器3.本地测试联机4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射内网端口 5.远程联机测试6. 配置固定远程联机端口地址6.1 保留一个固定TCP地址6.2 配置固定TCP地址 7. 使用固定公网地址远程联机 前言 MCSManager是一个…