上海图书馆开放数据竞赛 中文期刊论文自动分类(PaddleNLP)

一.项目介绍

1.1 项目背景

上海图书馆开放数据竞赛自2016年起已成功举办6届,凝聚了一批数据创客团队,收获了大量优秀作品和创意。第七届上海图书馆开放数据竞赛将继续为参赛者提供更加丰富和海量的历史人文数据,并新增算法竞赛,以“传承再造,连接共生”为主题,面向全球征集优秀移动应用产品原型及算法。

1.2 项目简介

中文期刊论文自动(四级类目)分类任务本质是一项具有长尾分布的单标签分类任务,基于百度融合大规模知识的ERNIE 3.0(即文心)系列预训练模型、PaddlePaddle深度学习开发框架和AI Studio实践平台,采用特征选择、数据增强、学习率Warmup策略、模型集成等训练策略,在验证集准确率 (Accuracy)评价指标值可达0.78624。因参评比赛中,故模型集成部分暂未对外开放,可私信交流。

算法模型基本架构:1. 加载文本数据;2. 数据进行预处理,将数据转换成id的形式,放入到dataloader中,用于训练过程中给模型提供批量的数据;3. 经过ERNIE /BERT/RoBERTa等模型训练,得到每条文本对应每个标签(单标签多分类)的概率,通常概率最大的标签即作为该文本的标签;4. 解析成文本对应的标签。

二. 中文期刊论文自动(四级类目)数据分析和处理

2.1 读取并处理数据集

本次评测样本数据集约98万余条,包括id、题名、关键词、刊名、分类号和摘要等条目。综合参考《中国图书馆分类法(第五版)使用手册》相应内容,实现“测试数据分类到四级”的要求。经过大量实验(结果记录如下),“题名+关键词+刊名+摘要(记topic+ keyword+ journal+ abstract)”作为特征数据来源,在验证集效果最佳。

# 读取数据
import pandas as pd
import numpy as npfile_name = 'pmk20102011.xlsx'
data = pd.read_excel(file_name)
data.head(5)
data.info()
book_id=data.pop('分类号')
book_id=book_id.str.split('[(|./]', expand=True).iloc[:,0]
data.insert(5,'类别',book_id)# book_id=data.pop('分类号')
# book_id=book_id.str.split('[-(|./]', expand=True).iloc[:,0]
# data.insert(5,'类别',book_id)
data.head(5)
data["题名"] = data["题名"].astype(str)
data["题名"] = data["题名"].apply(lambda x: x.replace('\t',''))
data["题名"] = data["题名"].apply(lambda x: x.replace('\n',''))
data["题名"] = data["题名"].apply(lambda x: x.replace('\u3000',''))
data["题名"] = data["题名"].apply(lambda x: x.replace('\xa0',''))
data["题名"] = data["题名"].apply(lambda x: x.replace('\r',''))data["摘要"] = data["摘要"].astype(str)
data["摘要"] = data["摘要"].apply(lambda x: x.replace('\t',''))
data["摘要"] = data["摘要"].apply(lambda x: x.replace('\n',''))
data["摘要"] = data["摘要"].apply(lambda x: x.replace('\u3000',''))
data["摘要"] = data["摘要"].apply(lambda x: x.replace('\xa0',''))
data["摘要"] = data["摘要"].apply(lambda x: x.replace('\r',''))data["关键词"] = data["关键词"].astype(str)
data["关键词"] = data["关键词"].apply(lambda x: x.replace('\t',''))
data["关键词"] = data["关键词"].apply(lambda x: x.replace('\n',''))
data["关键词"] = data["关键词"].apply(lambda x: x.replace('\u3000',''))
data["关键词"] = data["关键词"].apply(lambda x: x.replace('\xa0',''))
data["关键词"] = data["关键词"].apply(lambda x: x.replace('\r',''))data["刊名"] = data["刊名"].astype(str)
data["刊名"] = data["刊名"].apply(lambda x: x.replace('\t',''))
data["刊名"] = data["刊名"].apply(lambda x: x.replace('\n',''))
data["刊名"] = data["刊名"].apply(lambda x: x.replace('\u3000',''))
data["刊名"] = data["刊名"].apply(lambda x: x.replace('\xa0',''))
data["刊名"] = data["刊名"].apply(lambda x: x.replace('\r',''))data["类别"] = data["类别"].astype(str)
data["类别"] = data["类别"].apply(lambda x: x.replace('\t',''))
data["类别"] = data["类别"].apply(lambda x: x.replace('\n',''))
data["类别"] = data["类别"].apply(lambda x: x.replace('\u3000',''))
data["类别"] = data["类别"].apply(lambda x: x.replace('\xa0',''))
data["类别"] = data["类别"].apply(lambda x: x.replace('\r',''))data['text_a'] = data['题名'] + data["关键词"] + data["刊名"]
data['text_b'] = data['摘要']
data['label'] = data['类别']
journal_data = data[['text_a', 'text_b', 'label']]

2.2 数据分析EDA

# 查看数据前5条
journal_data.head(5)
# 查看总数据文件信息,可以看出共计有984118条数据
journal_data.info()
# 统计题名text_a+text_b文本长度,便于确定总文本最大截断长度(未数据增强)
(journal_data['text_a'].map(len)+journal_data['text_b'].map(len)).describe()
# 统计数据集中类别标签的分布情况
journal_data['label'].value_counts()
# 可视化类别标签分布情况
%matplotlib inline
journal_data['label'].value_counts(normalize=True).plot(kind='line');
#保存预处理后的数据
journal_data.to_csv('topic_keyword_journal_abstract+0906.csv', index=False)

参考 NLPCDA——中文数据增强工具 介绍和方法 链接 。针对样本长尾分布的问题,参考相关文档资料,使用随机同义词替换、等价字替换、随机置换邻近的字和随机字删除等数据增强方法组合,来实现长尾部分数据增加约12倍(可调整增强文本个数create_num和文本改变率change_rate参数)。

注:仅提供数据增强后数据集(‘topic_keyword_journal_abstract+.csv’ 和 ‘topic_keyword_journal_abstract++.csv’,区别在于是否将“总论复分符号(-)”分割9230/8745),请自行按链接介绍和方法探索。

# 查看当前挂载的数据集目录, 该目录下的变更重启环境后会自动还原
# View dataset directory. This directory will be recovered automatically after resetting environment.
# 读取数据
import pandas as pd
import numpy as npfile_name = 'data/data167752/topic_keyword_journal_abstract+.csv' # 数据增强
journal_data = pd.read_csv(file_name)
journal_data
journal_data["text_a"] = journal_data["text_a"].astype(str)
journal_data["text_a"] = journal_data["text_a"].apply(lambda x: x.replace('\t',''))
journal_data["text_a"] = journal_data["text_a"].apply(lambda x: x.replace('\n',''))
journal_data["text_a"] = journal_data["text_a"].apply(lambda x: x.replace('\u3000',''))
journal_data["text_a"] = journal_data["text_a"].apply(lambda x: x.replace('\xa0',''))
journal_data["text_a"] = journal_data["text_a"].apply(lambda x: x.replace('\r',''))journal_data["text_b"] = journal_data["text_b"].astype(str)
journal_data["text_b"] = journal_data["text_b"].apply(lambda x: x.replace('\t',''))
journal_data["text_b"] = journal_data["text_b"].apply(lambda x: x.replace('\n',''))
journal_data["text_b"] = journal_data["text_b"].apply(lambda x: x.replace('\u3000',''))
journal_data["text_b"] = journal_data["text_b"].apply(lambda x: x.replace('\xa0',''))
journal_data["text_b"] = journal_data["text_b"].apply(lambda x: x.replace('\r',''))
# 统计数据集中类别标签的分布情况
journal_data['label'].value_counts()
# 定义要进行分类的类别
label_list=list(journal_data.label.unique())
# print(sorted(label_list))
# 统计题名text_a+text_b文本长度,便于确定总文本最大截断长度(未数据增强)
(journal_data["text_a"].str.len()+journal_data["text_b"].str.len()).describe()
# 对处理后的数据进行存储,格式统一为text_a[\t]text_b[\t]labelfrom sklearn.model_selection import train_test_splittrain, valid = train_test_split(journal_data, test_size=0.2, random_state=80471)
train.to_csv('train.csv', index=False, header=True, sep='\t')
valid.to_csv('valid.csv', index=False, header=True, sep='\t')

三.基于PaddleNLP构建中文期刊论文自动分类模型

3.1 前置环境准备

# 下载最新的paddlenlp
!pip install --upgrade paddlenlp
# 导入所需的第三方库
import math
import numpy as np
import os
import collections
from functools import partial
import random
import time
import inspect
import importlib
from tqdm import tqdm
import paddle
import paddle.nn as nn
import paddle.nn.functional as F
from paddle.io import IterableDataset, DataLoader, BatchSampler
from paddle.utils.download import get_path_from_url
from paddle.dataset.common import md5file# 导入paddlenlp相关的包
import paddlenlp as ppnlp
from paddlenlp.transformers import *
from paddlenlp.datasets import MapDataset
from paddlenlp.datasets import DatasetBuilder
from paddlenlp.data import JiebaTokenizer, Pad, Stack, Tuple, Vocab

3.2 定义要进行微调的预训练模型

此次使用ERNIE 系列模型,该模型目前在中文领域上效果较优。

同时预训练模型一般“大力出奇迹”,选用大的预训练模型往往可以取得比base模型(BERT)更优的效果。

# 批处理大小,显存如若不足的话可以适当改小该值
batch_size = 196# 文本序列最大截断长度,需要根据文本具体长度进行确定,不超过512
max_seq_length = 256# 定义训练过程中的最大学习率
learning_rate = 5e-5# 训练轮次
epochs = 12# 学习率预热比例
warmup_proportion = 0.1# 学习率衰减比例
decay_proportion = 0.2# 权重衰减系数,类似模型正则项策略,避免模型过拟合
weight_decay = 0.01# 只需指定想要使用的模型名称和文本分类的类别数即可完成Fine-tune网络定义,通过在预训练模型后拼接上一个全连接网络(Full Connected)进行分类# 设置想要使用模型的名称# ernie-3.0-xbase-zh
# ernie-3.0-base-zh
# ernie-3.0-medium-zh
# ernie-3.0-mini-zh
# ernie-3.0-micro-zh
# ernie-3.0-nano-zhmodel_name = "ernie-3.0-medium-zh"
model = AutoModelForSequenceClassification.from_pretrained(model_name, num_classes=len(label_list))tokenizer = AutoTokenizer.from_pretrained(model_name)# 此次需要注意,要修改使用其他模型的话,需要修改下AutoModelForSequenceClassification和AutoTokenizer,具体修改可以查看paddlenlp的api文档

3.3 数据读取和预处理

# 定义数据集对应文件及其文件存储格式
class JournalData(DatasetBuilder):SPLITS = {'train': 'train.csv',  # 训练集'dev': 'valid.csv',    # 验证集'test': 'valid.csv',    # 测试集}def _get_data(self, mode, **kwargs):filename = self.SPLITS[mode]return filenamedef _read(self, filename):"""读取数据"""with open(filename, 'r', encoding='utf-8') as f:head = Nonefor line in f:data = line.strip().split("\t")    # 以'\t'分隔各列if not head:head = dataelse:text_a, text_b, label = datayield {"text_a": text_a,"text_b": text_b, "label": label}  # 数据的格式:text_a,labeldef get_labels(self):return label_list   # 类别标签
# 定义数据集加载函数
def load_dataset(name=None,data_files=None,splits=None,lazy=None,**kwargs):reader_cls = JournalDataif not name:reader_instance = reader_cls(lazy=lazy, **kwargs)else:reader_instance = reader_cls(lazy=lazy, name=name, **kwargs)datasets = reader_instance.read_datasets(data_files=data_files, splits=splits)return datasets
# 加载训练、验证集和测试集
train_ds, dev_ds, test_ds = load_dataset(splits=["train", "dev", "test"])
# 定义数据加载和处理函数
def convert_example(example, tokenizer, max_seq_length=512, is_test=False,is_pair=True):if is_pair:text = example["text_a"]text_pair = example["text_b"]else:text = example["text"]text_pair = Noneencoded_inputs = tokenizer(text=text,text_pair=text_pair,max_seq_len=max_seq_length)input_ids = encoded_inputs["input_ids"]token_type_ids = encoded_inputs["token_type_ids"]if is_test:return input_ids, token_type_idslabel = np.array([example["label"]], dtype="int64")return input_ids, token_type_ids, label# 数据加载函数dataloader
def create_dataloader(dataset,mode='train',batch_size=1,batchify_fn=None,trans_fn=None):if trans_fn:dataset = dataset.map(trans_fn)shuffle = True if mode == 'train' else Falseif mode == 'train':batch_sampler = paddle.io.DistributedBatchSampler(dataset, batch_size=batch_size, shuffle=shuffle)else:batch_sampler = paddle.io.BatchSampler(dataset, batch_size=batch_size, shuffle=shuffle)return paddle.io.DataLoader(dataset=dataset,batch_sampler=batch_sampler,collate_fn=batchify_fn,return_list=True)
# 将数据处理成模型可读入的数据格式
trans_func = partial(convert_example,tokenizer=tokenizer,max_seq_length=max_seq_length)batchify_fn = lambda samples, fn=Tuple(Pad(axis=0, pad_val=tokenizer.pad_token_id),  # input_idsPad(axis=0, pad_val=tokenizer.pad_token_type_id),  # token_type_idsStack()  # labels
): [data for data in fn(samples)]# 训练集迭代器
train_data_loader = create_dataloader(train_ds,mode='train',batch_size=batch_size,batchify_fn=batchify_fn,trans_fn=trans_func)# 验证集迭代器
dev_data_loader = create_dataloader(dev_ds,mode='dev',batch_size=batch_size,batchify_fn=batchify_fn,trans_fn=trans_func)# 测试集迭代器
test_data_loader = create_dataloader(test_ds, mode='test', batch_size=batch_size, batchify_fn=batchify_fn, trans_fn=trans_func)

3.4 设置Fine-Tune优化策略,接入评价指标

适用于ERNIE/BERT这类Transformer模型的学习率为Warmup的动态学习率。paddlenlp.transformers.optimization

学习率WarmUp设置 可参考 学习率可视化实验 PaddleNLP库的学习率Warmup可视化(新)

# 定义超参,loss,优化器等max_steps = len(train_data_loader) * epochslr_scheduler = LinearDecayWithWarmup(learning_rate=learning_rate, total_steps=max_steps, warmup=warmup_proportion)
# lr_scheduler = CosineDecayWithWarmup(learning_rate=learning_rate, total_steps=max_steps, warmup=warmup_proportion)# warmup_step=max_steps*warmup_proportion
# decay_step=max_steps*(1-decay_proportion)
# lr_scheduler = CosineAnnealingWithWarmupDecay(max_lr=learning_rate, min_lr=1e-7, warmup_step=warmup_step, decay_step=decay_step)# AdamW优化器
optimizer = paddle.optimizer.AdamW(learning_rate=lr_scheduler,parameters=model.parameters(),weight_decay=weight_decay,apply_decay_param_fun=lambda x: x in [p.name for n, p in model.named_parameters()if not any(nd in n for nd in ["bias", "norm"])])criterion = paddle.nn.loss.CrossEntropyLoss()  # 交叉熵损失函数metric = paddle.metric.Accuracy()  # accuracy评价指标

3.5 模型训练与评估

ps:模型训练时,可以通过在终端输入nvdia-smi命令或者通过点击底部‘性能监控’选项查看显存的占用情况,适当调整好batchsize。

# 定义模型训练验证评估函数
@paddle.no_grad()
def evaluate(model, criterion, metric, data_loader):"""Given a dataset, it evals model and computes the metric.Args:model(obj:`paddle.nn.Layer`): A model to classify texts.data_loader(obj:`paddle.io.DataLoader`): The dataset loader which generates batches.criterion(obj:`paddle.nn.Layer`): It can compute the loss.metric(obj:`paddle.metric.Metric`): The evaluation metric."""model.eval()metric.reset()for batch in tqdm(data_loader):input_ids, token_type_ids, labels = batchlogits = model(input_ids, token_type_ids)correct = metric.compute(logits, labels)metric.update(correct)accuracy = metric.accumulate()model.train()return accuracy  # 返回准确率
def do_train(model, train_data_loader, dev_data_loader, criterion, metric, optimizer, lr_scheduler):model.train()max_accuracy=0save_dir = "./checkpoint/" + model_namefor epoch in range(1, epochs + 1):with tqdm(total=len(train_data_loader)) as pbar:for step, batch in enumerate(train_data_loader, start=1):input_ids, token_type_ids, labels = batchlogits = model(input_ids, token_type_ids)loss = criterion(logits, labels)loss.backward()optimizer.step()lr_scheduler.step()optimizer.clear_grad()pbar.set_postfix({'loss' : '%.5f' % (loss.numpy())})pbar.update(1)accuracy = evaluate(model, criterion, metric, dev_data_loader)print("Epoch: %d, Accuracy: %.5f" % (epoch, accuracy))if not os.path.exists(save_dir):os.makedirs(save_dir)  ## 递归创建print("Epoch: %d, Accuracy: %.5f" % (epoch, accuracy), file=open(save_dir +'/best_model_log.txt', 'a'))if accuracy >= max_accuracy:max_accuracy = accuracy save_param_path = os.path.join(save_dir, 'best_model.pdparams')paddle.save(model.state_dict(), save_param_path)tokenizer.save_pretrained(save_dir)                save_param_path = os.path.join(save_dir, 'last_model.pdparams')paddle.save(model.state_dict(), save_param_path)
# 或可直接使用预训练模型结果参数(如后)
# do_train(model, train_data_loader, dev_data_loader, criterion, metric, optimizer, lr_scheduler)

3.6 模型预测

说明:提供 ernie-3.0-medium-zh 和 ernie-3.0-xbase-zh 模型训练结果参数,需解压。

# !unzip -o data/data167752/JournalBsetModel.zip -d work/
# 类别和id转换
label_list=list(journal_data.label.unique())
label_map = { idx: label_text for idx, label_text in enumerate(label_list)
}
# print(label_map)
@paddle.no_grad()
def predict_dev(model, label_map, dev_data_loader):y_pred=[]model.eval()for batch in tqdm(dev_data_loader):input_ids, token_type_ids, labels = batchlogits = model(input_ids, token_type_ids)probs = F.softmax(logits, axis= 1)preds = paddle.argmax(probs, axis=1).numpy()preds = preds.tolist()pred_labels = [label_map[i] for i in preds]y_pred.extend(pred_labels)return y_predparams_path="./work/JournalBsetModel/0.75868plus+medium+lr1/best_model.pdparams"
state_dict = paddle.load(params_path)
model.set_dict(state_dict)
print("Loaded parameters from %s" % params_path)
preds=predict_dev(model, label_map, dev_data_loader)
dev_preds = pd.DataFrame(np.array(preds))
dev_preds.index.name = 'Id'
dev_preds.to_csv("0.75868plus+medium+lr1"+'_dev_pred.csv', sep = ',', header = ['Label'], index = True)
from sklearn.metrics import accuracy_score
labels = valid.label.tolist()  #获得验证集标签
accuracy_score(labels, preds)  #验证集准确率 (Accuracy)评价指标值

四、模型集成

参考:竞赛上分Trick-结果融合

注:可根据参考文档自行进行模型集成,不提供各单个模型预测结果,仅提供 多结果投票融合集成 预测结果。

4.1.多结果投票融合

主要使用于当预测结果为具体的类别而非概率时,基于少数服从多数的原则选择集体同意的类别。分为等权融合和加权投票融合两种。

4.2.多结果平均融合

平均融合常用于输出结果为概率分数时,通过采用多个个体模型预测值的平均降低过拟合。分为普通平均、几何平均和排名平均三种。

!unzip -o data/data168061/EnsembleResults.zip -d .
Archive:  data/data168061/EnsembleResults.zipcreating: ./EnsembleResults/creating: ./EnsembleResults/topic_keyword_journal_abstract+/inflating: ./EnsembleResults/topic_keyword_journal_abstract+/+dev_pred_results.csv  inflating: ./EnsembleResults/topic_keyword_journal_abstract+/+valid.csv  inflating: ./EnsembleResults/topic_keyword_journal_abstract+/0.76363plus+base+lr1_dev_pred.csv  inflating: ./EnsembleResults/topic_keyword_journal_abstract+/0.76641plus+base+lr3_dev_pred.csv  inflating: ./EnsembleResults/topic_keyword_journal_abstract+/0.76944plus+base+lr5_dev_pred.csv  inflating: ./EnsembleResults/topic_keyword_journal_abstract+/0.77067plus+xbase+lr3_dev_pred.csv  inflating: ./EnsembleResults/topic_keyword_journal_abstract+/0.77456plus+xbase+lr3_dev_pred.csv  inflating: ./EnsembleResults/topic_keyword_journal_abstract+/0.77463plus+xbase+lr5_dev_pred.csv  inflating: ./EnsembleResults/topic_keyword_journal_abstract+/0.77491plus+xbase+lr3_dev_pred.csv  inflating: ./EnsembleResults/topic_keyword_journal_abstract+/no0.76455plus+bert+lr1_dev_pred.csv  creating: ./EnsembleResults/topic_keyword_journal_abstract++/inflating: ./EnsembleResults/topic_keyword_journal_abstract++/++dev_pred_results.csv  inflating: ./EnsembleResults/topic_keyword_journal_abstract++/++valid.csv  inflating: ./EnsembleResults/topic_keyword_journal_abstract++/0.76351plus++base+lr1_dev_pred.csv  inflating: ./EnsembleResults/topic_keyword_journal_abstract++/0.76474plus++base+lr5_dev_pred.csv  inflating: ./EnsembleResults/topic_keyword_journal_abstract++/0.76489plus++base+lr3_dev_pred.csv  inflating: ./EnsembleResults/topic_keyword_journal_abstract++/0.77273plus++xbase+lr3_dev_pred.csv  inflating: ./EnsembleResults/topic_keyword_journal_abstract++/0.77278plus++xbase+lr3_dev_pred.csv  inflating: ./EnsembleResults/topic_keyword_journal_abstract++/0.77292plus++xbase+lr1_dev_pred.csv  inflating: ./EnsembleResults/topic_keyword_journal_abstract++/0.77356plus++xbase+lr3_dev_pred.csv
# 需特别注意代码中对id索引列默认从小到大进行排序,若提交格式要求不能打乱索引格式的话需要对索引做下重新排序。
# 同时需注意在使用整合的代码时,多结果格式上需要设置首列用于索引列!若无id列的话可以手动为其添加index列生成结果时再去除。
import pandas as pd
dev_pred_results = pd.read_csv('EnsembleResults/topic_keyword_journal_abstract+/+dev_pred_results.csv')  #集成模型对验证集的预测结果,以topic_keyword_journal_abstract+为例
dev_pred_results = dev_pred_results.sort_values(by='Id')valid_data = pd.read_csv('EnsembleResults/topic_keyword_journal_abstract+/+valid.csv', sep='\t') # 读取验证集数据
from sklearn.metrics import accuracy_score
labels = valid_data.label.tolist()  #获得验证集标签
preds = dev_pred_results.Label.tolist()  #获得集成模型对验证集的预测标签
对验证集的预测结果,以topic_keyword_journal_abstract+为例
dev_pred_results = dev_pred_results.sort_values(by='Id')valid_data = pd.read_csv('EnsembleResults/topic_keyword_journal_abstract+/+valid.csv', sep='\t') # 读取验证集数据
from sklearn.metrics import accuracy_score
labels = valid_data.label.tolist()  #获得验证集标签
preds = dev_pred_results.Label.tolist()  #获得集成模型对验证集的预测标签
accuracy_score(labels, preds)  #验证集准确率 (Accuracy)评价指标值
0.7862438380623374

参考文献

  1. 百度飞桨 PaddlePaddle 深度学习框架 https://www.paddlepaddle.org.cn
  2. Sun Y, Wang S, Feng S, et al. Ernie 3.0: Large-scale knowledge enhanced pre-training for language understanding and generation[J]. arXiv preprint arXiv:2107.02137, 2021.
  3. NLP Chinese Data Augmentation 一键中文数据增强工具 https://github.com/425776024/nlpcda
  4. https://github.com/MLWave/Kaggle-Ensemble-Guide
  5. 国家图书馆《中国图书馆分类法》委员会. 《中国图书馆分类法》第五版使用手册[J]. 国家图书馆出版社, 2012.
    此文章为搬运
    原项目链接

【上图开放数据竞赛】中文期刊论文自动分类Baseline相关推荐

  1. 中文期刊论文使用Endnote和Word导入GBT 7714-2015标准格式参考文献详细教程

    国内的毕业论文和各种中文期刊论文的参考文献基本都要求使用GBT 7714-2015标准格式,但什么是GBT 7714-2015标准格式?如何使用EndNote和Word导入GBT 7714-2015标 ...

  2. 从零开始用 LaTeX 排版一篇中文期刊论文 - 前言篇

    从零开始用 LaTeX 排版一篇中文期刊论文 - 前言篇 LaTeX\LaTeXLATE​X 的优缺点及入门建议 优点 缺点 入门建议 软件安装与使用 Tex Live 和 TexStudio是什么? ...

  3. ei会议被检索的时间一般多久,中文期刊论文有doi吗

    目录 ei会议被检索的时间一般多久 中文期刊论文有doi吗 中文期刊论文没有oi怎么办

  4. 从零开始用 LaTeX 排版一篇中文期刊论文 - (二)<更新中>

    从零开始用 LaTeX 排版一篇中文期刊论文 - (二)<更新中> 数学公式 数学符号 一般符号 特殊符号 上下标 右侧上下标 垂直上下标 公式环境 一般公式 分段函数或方程组 矩阵 条目 ...

  5. zotero中文期刊论文题录中姓名被逗号分开

    zotero中文期刊论文题录中姓名被逗号分开,可以通过茉莉花插件进行合并,具体操作如下: 1.选中需要合并姓名的题录,可多选: 2.鼠标右击,选择"小工具": 3.选择" ...

  6. 共治共创视角下的开放数据发展:趋势、挑战和反思

    按:本文修改版刊发于<大数据>期刊,2016, Vol. 2(2) 1.  前言 开放数据运动的兴起,一般来说,被认为起始于2009年data.gov的启动.作为政府透明化工作的重要一步, ...

  7. 超9成SCI论文发在国外!中文期刊到底差在哪?

    来源 | 科学网 撰文 | 卜叶 编辑 | 宗华 学术界不投中文期刊的原因是什么?这一老生常谈的问题,最近再次出现在某知识问答平台热榜.短短两周,便吸引了180个回答,浏览量超过34万. 中文期刊到底 ...

  8. 全世界都在说中国话?2022国际大数据竞赛首次以“中文”命题

    8月10日, IKCEST第四届"一带一路"国际大数据竞赛暨第八届百度&西安交大大数据竞赛(以下简称"国际大数据竞赛")正式启动,本届赛题聚焦" ...

  9. python教育学_使用Python处理教育学领域的数据——以某篇期刊论文为例

    Python是数据处理的常用语言,当然也可以用在教育学领域.下面以一篇期刊论文--为例,阐述使用Python处理教育学领域数据的思路和过程.为什么用这篇期刊文章呢,因为这篇文章的数据处理是我做的,比较 ...

最新文章

  1. 子域名/目录暴力工具Gobuster
  2. 2019 校招 ,下一个“神”人,在哪里?
  3. 【最全最详细】publiccmsCSS和JS引入无效的解决方法
  4. 作业帮口算批改怎么开 作业帮口算批改如何用
  5. udp打洞没反应_这8种酒精饮料:1亿人在喝,你还没听过
  6. mysql建表后添加约束_MYSQL建表完成之后添加约束
  7. android sp缓存,Android sharedPreference设置缓存时间
  8. 基于八叉树的区域增长点云分割算法
  9. 计算机主机组装图,自己如何组装电脑主机?diy电脑组装教程图解详细步骤+装机心得(5)...
  10. app商城开发要多少钱_价格透明_讲讲行业收费套路_OctShop
  11. AutoVue教程:如何在64位Linux上安装AutoVue
  12. 哈哈,美食是生活的重要组成啊,自己烹调鲍鱼
  13. iOS各版本发布时间汇总
  14. VBS 请求WebAPI接口_从零开始实现简单的webapi框架【Golang 入门系列十一】
  15. Error response from daemon: Get https://192.168.x.x/v2/: x509: cannot validate certificate for
  16. 等式约束优化(可行点)
  17. 欧洲共同语言参考标准英语c1,美国小学英语3年级语言知识对标欧洲共同语言参考标准CEFR...
  18. 静静默默,习惯一个人
  19. mysql树状结构查询子节点和父节点
  20. 使用meb工具在线热备,将单实例切换为主从

热门文章

  1. Shapiro-Wilk (SW) 检验
  2. .NET加密打包教程一(.NetReactor加密)
  3. 科普:什么是上网?网络是怎样连接的?
  4. 重启服务器对数据库有影响吗,服务器重启2008数据库
  5. 游戏平台SDK设计和开发之旅——XSDK功能点梳理
  6. 最强端到端文本识别模型 Mask TextSpotter v3 来了!
  7. 微软语音合成网页版源码,影视解说配音网页版
  8. web网站验证码重要性和验证码注意事项
  9. shell脚本中设置字体颜色
  10. 想看懂三次握手,四次挥手?看这里!!!