阿里天池-糖尿病命名实体识别

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

一、阿里天池赛题

官网链接:https://tianchi.aliyun.com/competition/entrance/231687/information
没用到CRF,运行环境Kaggle。
有需要数据集或者帮助的可以留下联系方式或私聊。

NER任务介绍

命名实体识别(NER)是自然语言处理领域的一个基本任务,其目标是从文本中识别出具有特定意义的实体,如人名、地名、组织名等。 这些实体在文本中扮演着关键角色,对于文本理解和信息抽取具有重要意义。随着深度学习技术的发展,NER任务取得了显著的进展,各种算法和模型不断涌现,为NLP领域的研究和应用提供了强大的支持。
本部分写的是与糖尿病相关的NER任务。

二、实验步骤

1.准备数据集

代码如下(示例):

# 标签列表和映射字典
label_list = ['O', 'B-Disease', 'I-Disease', 'B-Reason', 'I-Reason', 'B-Symptom', 'I-Symptom', 'B-Test', 'I-Test', 
              'B-Test_Value', 'I-Test_Value', 'B-Drug', 'I-Drug', 'B-Frequency', 'I-Frequency', 'B-Amount', 'I-Amount', 
              'B-Treatment', 'I-Treatment', 'B-Operation', 'I-Operation', 'B-Method', 'I-Method', 'B-SideEff', 'I-SideEff', 'B-Anatomy', 'I-Anatomy', 'B-Level', 'I-Level', 'B-Duration', 'I-Duration']
label_to_id = {label: idx for idx, label in enumerate(label_list)}

def load_data(file_path):
    sentences = []
    labels = []
    current_sentence = []
    current_labels = []

    with open(file_path, 'r', encoding='utf-8') as file:
        for line in file:
            if line.strip() == "":  # 跳过空行
                continue
            word, label = line.strip().split()
            if word == "SPACE":
                if current_sentence:  # 确保不添加空句子
                    sentences.append(current_sentence)
                    labels.append(current_labels)
                    current_sentence = []
                    current_labels = []
            else:
                current_sentence.append(word)
                current_labels.append(label)
        
        # 添加最后一段数据
        if current_sentence:
            sentences.append(current_sentence)
            labels.append(current_labels)
    
    return sentences, labels

def construct_dataframe(sentences, labels, label_to_id):
    data = {'Sentence': [' '.join(sentence) for sentence in sentences],
            'Labels': [','.join(label) for label in labels]}
    df = pd.DataFrame(data)

    # 将标签转换为数字型数据
    df['Labels'] = df['Labels'].apply(lambda x: [label_to_id[label] for label in x.split(',')])
    return df

file_path1 = '/kaggle/input/crfmedicaldataset/ruijin_train.data'
sentences1, labels1 = load_data(file_path1)
file_path2 = '/kaggle/input/crfmedicaldataset/ruijin_dev.data'
sentences2, labels2 = load_data(file_path2)
train_df = construct_dataframe(sentences1, labels1, label_to_id)
test_df = construct_dataframe(sentences2, labels2, label_to_id)

2.转换成dataloader

代码如下(示例):

class NERDataset(Dataset):
    def __init__(self, df, tokenizer, max_len):
        self.sentences = df['Sentence'].values
        self.labels = df['Labels'].values
        self.tokenizer = tokenizer
        self.max_len = max_len

    def __len__(self):
        return len(self.sentences)

    def __getitem__(self, index):
        sentence = self.sentences[index]
        labels = self.labels[index]

        # Tokenize the sentence
        encoding = self.tokenizer(
            sentence.split(),
            is_split_into_words=True,
            truncation=True,
            padding='max_length',
            max_length=self.max_len,
            return_tensors='pt'
        )

        labels = [0] + labels + [0] * (self.max_len -1 - len(labels))  # Pad with 0
        labels = labels[:self.max_len]  # Truncate to max_len
        labels = torch.tensor(labels, dtype=torch.long)

        item = {key: val.squeeze(0) for key, val in encoding.items()}
        item['labels'] = labels

        return item

# 配置
PRETRAINED_MODEL_NAME = "bert-base-chinese"
MAX_LEN = 64
BATCH_SIZE = 64

# 初始化tokenizer
tokenizer = BertTokenizer.from_pretrained(PRETRAINED_MODEL_NAME)

# 构建Dataset
train_dataset = NERDataset(train_df, tokenizer, MAX_LEN)
test_dataset = NERDataset(test_df, tokenizer, MAX_LEN)

# 构建DataLoader
train_dataloader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)
test_dataloader = DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=True)


3.构建模型(最简单的bert)

代码如下(示例):

class BERT_NER(torch.nn.Module):
    def __init__(self,bertModel):
        super(BERT_NER, self).__init__()
        self.bert = bertModel
        self.dropout = nn.Dropout(0.1)
        self.linear = nn.Linear(768, 31)

    def forward(self, input_ids, attention_mask):
        outputs = self.bert(input_ids, attention_mask)
        sequence_output = self.dropout(outputs[0])
        emissions = self.linear(sequence_output)
        return emissions

model = BERT_NER(bertModel)
model = model.to(device)

4.训练模型

代码如下(示例):

#对计算结果和label变形,并且移除pad
def reshape_and_remove_pad(outs, labels, attention_mask):
    #变形,便于计算loss
    outs = outs.reshape(-1, 31)
    labels = labels.reshape(-1)

    #忽略对pad的计算结果
    #[b, lens] -> [b*lens - pad]
    select = attention_mask.reshape(-1) == 1
    outs = outs[select]
    labels = labels[select]

    return outs, labels

your_labels_list = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]
optimizer = AdamW(model.parameters(), lr=3e-5)
epochs = 3
total_steps = len(train_dataloader) * epochs
loss_function = torch.nn.CrossEntropyLoss()
all_big_idx = np.array([])
all_targets = np.array([])
for epoch in range(epochs):
    model.train()
    total_loss = 0
    for _,data in enumerate(train_dataloader, 0):
        batch_input_ids = data['input_ids'].to(device, dtype = torch.long)
        batch_input_mask = data['attention_mask'].to(device, dtype = torch.long)
        batch_labels = data['labels'].to(device, dtype = torch.long) 
        
        out= model(batch_input_ids, attention_mask=batch_input_mask)
        out, targets = reshape_and_remove_pad(out, batch_labels,batch_input_mask)
        big_val, big_idx = torch.max(out.data, dim=1)
        loss = loss_function(out, targets)
        total_loss += loss.item()
        
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        big_idx = big_idx.cpu()
        big_idx = big_idx.detach().numpy()

        all_big_idx = np.concatenate((all_big_idx,big_idx))
        targets = targets.cpu()
        targets = targets.detach().numpy()
        all_targets = np.concatenate((all_targets,targets))
        
        if (_+1) %1000 == 0:
            precision = precision_score(all_big_idx, all_targets, labels=your_labels_list, average='weighted')
            recall = recall_score(all_big_idx, all_targets, labels=your_labels_list, average='weighted')
            f = f1_score(all_big_idx, all_targets, labels=your_labels_list, average='weighted')
            print(f) #打印结果
            avg_train_loss = total_loss / len(train_dataloader)
            print(f"Average train loss: {avg_train_loss}")
        if (_+1) %1000 == 0:  # 查看部分预测与实际值
            print(big_idx)
            print(targets)

5.验证模型

代码如下(示例):

model.eval()
total_loss = 0
all_big_idx = np.array([])
all_targets = np.array([])
for _,data in enumerate(test_dataloader, 0):
    batch_input_ids = data['input_ids'].to(device, dtype = torch.long)
    batch_input_mask = data['attention_mask'].to(device, dtype = torch.long)
    batch_labels = data['labels'].to(device, dtype = torch.long) 

    out= model(batch_input_ids, attention_mask=batch_input_mask)
    out, targets = reshape_and_remove_pad(out, batch_labels,batch_input_mask)
    big_val, big_idx = torch.max(out.data, dim=1)
    loss = loss_function(out, targets)
    total_loss += loss.item()

    big_idx = big_idx.cpu()
    big_idx = big_idx.detach().numpy()

    all_big_idx = np.concatenate((all_big_idx,big_idx))
    targets = targets.cpu()
    targets = targets.detach().numpy()
    all_targets = np.concatenate((all_targets,targets))

    if (_+1) %1000 == 0:
        precision = precision_score(all_big_idx, all_targets, labels=your_labels_list, average='weighted')
        recall = recall_score(all_big_idx, all_targets, labels=your_labels_list, average='weighted')
        f = f1_score(all_big_idx, all_targets, labels=your_labels_list, average='weighted')
        print(f)
        avg_train_loss = total_loss / len(train_dataloader)
        print(f"Average train loss: {avg_train_loss}")
    if (_+1) %1000 == 0:
        print(big_idx)
        print(targets)

总结

相当于用Bert做分类任务,针对的是每个token分类,下一步准备加入CRF,并把模型bert换成更新的。
部分结果展示

  • 19
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 阿里天池淘宝2017-11用户行为数据分析是基于Hive进行的。Hive是一个构建在Hadoop之上的数据仓库基础架构,提供了类似于SQL的查询语言HiveQL,使用户能够在大规模数据集上进行数据查询和分析。 在进行淘宝用户行为数据分析时,首先需要将原始数据导入Hive数据仓库中。数据源可以是来自淘宝的用户行为日志文件,其中包含了用户在淘宝平台上的各种行为,例如浏览商品、点击广告、添加购物车、购买等等。 然后,使用HiveQL语言编写查询语句,通过Hive进行数据分析。数据分析的目标可能包括但不限于:用户行为的频率分布、用户购买转化率、热门商品排行、用户购买决策的时间分布等等。通过对用户行为数据进行分析,阿里天池淘宝可以洞察用户行为的规律,发现用户需求和购物习惯,从而为优化产品和推广策略提供参考。 Hive的优势之一是可以处理大规模的数据,因此对于淘宝这样拥有海量用户和数据的平台而言,使用Hive进行用户行为数据分析非常合适。此外,Hive还提供了数据仓库的概念,可以通过不同的方式将数据进行结构化和存储,以方便后续的查询和分析。 综上所述,阿里天池淘宝2017-11用户行为数据分析基于Hive,通过将用户行为数据导入Hive数据仓库,利用HiveQL进行查询和分析,从而洞察用户行为规律,为产品和推广策略优化提供依据。Hive作为一个大数据处理工具,对于处理淘宝这样海量用户和数据的平台来说是非常适用的。 ### 回答2: 阿里巴巴天池是一个面向数据科学家和机器学习爱好者的在线数据科学竞赛平台,提供丰富多样的数据集和竞赛任务。其中,淘宝用户行为数据分析是天池平台的一个竞赛任务。在这个竞赛中,参赛者需要使用Hive来完成对淘宝2017年11月的用户行为数据进行分析。 Hive是基于Hadoop的数据仓库系统,它可以处理大规模数据,并提供了类似于SQL的查询语言,使得用户可以通过编写SQL式的语句来查询和分析数据。在淘宝用户行为数据分析任务中,Hive可以帮助分析师和数据科学家从大量数据中提取有用的信息。 通过Hive,我们可以利用淘宝用户行为数据进行各种分析,如用户购买行为、浏览行为、搜索行为等。我们可以使用Hive的查询语句来筛选、聚合和统计数据,以得出用户行为的关键指标。 一种常见的使用Hive进行用户行为数据分析的方法是利用Hive提供的内置函数和操作符来进行数据的转换和计算。通过使用Hive的内置函数,我们可以对用户行为数据进行预处理,如将日期格式化、提取关键字等。然后,我们可以使用Hive的聚合函数和操作符来计算用户行为的各种指标,如总购买金额、平均浏览次数等。 此外,Hive还支持用户自定义函数和UDAF(用户自定义聚合函数),这使得分析师和数据科学家可以根据自己的需求来扩展Hive的功能。通过编写自定义函数,我们可以在Hive中实现更加复杂的计算和分析。 总的来说,通过Hive,我们可以使用SQL式的查询语言阿里天池淘宝2017年11月的用户行为数据进行分析。通过Hive的内置函数和操作符,以及用户自定义函数和UDAF,我们可以从大规模的数据中提取有用的信息,并计算出用户行为的各项指标。 ### 回答3: 阿里天池淘宝2017-11用户行为数据分析基于Hive,可以使用Hive这个大数据存储和计算框架对淘宝2017年11月的用户行为数据进行分析。 Hive是一个基于Hadoop的数据仓库基础架构,可以将大规模数据集存储在Hadoop集群中,并同时提供类似于关系型数据库的查询和分析功能。通过Hive,可以利用SQL的方式对大规模数据进行查询和分析,使得数据分析师更加方便地处理和分析海量数据。 对于淘宝2017-11用户行为数据,可以将其导入Hive中进行分析。首先,可以创建一个Hive表,定义各个字段的名称和数据类型,然后将用户行为数据导入到这个表中。接着,可以使用Hive提供的SQL语句进行各种查询和分析。 例如,可以通过查询语句统计每个用户的购买次数、浏览次数、加入购物车次数等行为情况,从而分析用户的购买意向和行为模式。也可以对用户的购买行为进行细分,比如按照地区、商品类别等进行分组,以了解不同用户群体的购物习惯和喜好。此外,还可以对用户行为的时间分布进行分析,了解用户在不同时间段的活跃度和购买偏好。 通过Hive的数据分析功能,可以深入挖掘淘宝2017-11用户行为数据中潜在的商业价值,为企业的市场营销和业务决策提供重要参考依据。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值