基于BERT模型实现文本相似度计算

配置所需的包

!pip install transformers==2.10.0  -i https://pypi.tuna.tsinghua.edu.cn/simple
!pip install HanziConv -i https://pypi.tuna.tsinghua.edu.cn/simple

数据预处理

# -*- coding: utf-8 -*-

from torch.utils.data import Dataset
from hanziconv import HanziConv
import pandas as pd
import torch

class DataPrecessForSentence(Dataset):
    # 处理文本
    def __init__(self, bert_tokenizer, LCQMC_file,
                 pred=None, max_char_len = 103):
        """
        bert_tokenizer :分词器;LCQMC_file     :语料文件
        """
        self.bert_tokenizer = bert_tokenizer
        self.max_seq_len = max_char_len
        self.seqs, self.seq_masks, self.seq_segments, \
        self.labels = self.get_input(LCQMC_file, pred)
    def __len__(self):
        return len(self.labels)
    def __getitem__(self, idx):
        return self.seqs[idx], self.seq_masks[idx], \
               self.seq_segments[idx], self.labels[idx]
    # 获取文本与标签
    def get_input(self, file, pred=None):
        # 预测
        if pred:
            sentences_1 = []
            sentences_2 = []
            for i,j in enumerate(file):
                sentences_1.append(j[0])
                sentences_2.append(j[1])
            sentences_1 = map(HanziConv.toSimplified, sentences_1)
            sentences_2 = map(HanziConv.toSimplified, sentences_2)
            labels = [0] * len(file)
        else:
            ftype = True if file.endswith('.tsv') else False
            limit = 50000
            df = pd.read_csv(file, sep='\t') if ftype else pd.read_json(file,lines=True)
            sentences_1 = map(HanziConv.toSimplified,
                              df['text_a'][:limit].values if ftype else df["sentence1"].iloc[:limit])
            sentences_2 = map(HanziConv.toSimplified,
                              df['text_b'][:limit].values if ftype else df["sentence2"].iloc[:limit])
            labels = df['label'].iloc[:limit].values
        # 切词
        tokens_seq_1 = list(map(self.bert_tokenizer.tokenize, sentences_1))
        tokens_seq_2 = list(map(self.bert_tokenizer.tokenize, sentences_2))
        # 获取定长序列及其mask
        result = list(map(self.trunate_and_pad, tokens_seq_1, tokens_seq_2))
        seqs = [i[0] for i in result]
        seq_masks = [i[1] for i in result]
        seq_segments = [i[2] for i in result]
        return torch.Tensor(seqs).type(torch.long), \
               torch.Tensor(seq_masks).type(torch.long), \
               torch.Tensor(seq_segments).type(torch.long),\
               torch.Tensor(labels).type(torch.long)
    def trunate_and_pad(self, tokens_seq_1, tokens_seq_2):
        # 对超长序列进行截断
        if len(tokens_seq_1) > ((self.max_seq_len - 3)//2):
            tokens_seq_1 = tokens_seq_1[0:(self.max_seq_len - 3)//2]
        if len(tokens_seq_2) > ((self.max_seq_len - 3)//2):
            tokens_seq_2 = tokens_seq_2[0:(self.max_seq_len - 3)//2]
        # 分别在首尾拼接特殊符号
        seq = ['[CLS]'] + tokens_seq_1 + ['[SEP]'] \
              + tokens_seq_2 + ['[SEP]']
        seq_segment = [0] * (len(tokens_seq_1) + 2)\
                      + [1] * (len(tokens_seq_2) + 1)
        # ID化
        seq = self.bert_tokenizer.convert_tokens_to_ids(seq)
        # 根据max_seq_len与seq的长度产生填充序列
        padding = [0] * (self.max_seq_len - len(seq))
        # 创建seq_mask
        seq_mask = [1] * len(seq) + padding
        # 创建seq_segment
        seq_segment = seq_segment + padding
        # 对seq拼接填充序列
        seq += padding
        assert len(seq) == self.max_seq_len
        assert len(seq_mask) == self.max_seq_len
        assert len(seq_segment) == self.max_seq_len
        return seq, seq_mask, seq_segment

构建BERT模型

# -*- coding: utf-8 -*-

import torch
from torch import nn
from transformers import BertForSequenceClassification, BertConfig

class BertModel(nn.Module):
    def __init__(self):
        super(BertModel, self).__init__()
        self.bert = BertForSequenceClassification.from_pretrained("/kaggle/input/textmatch/pretrained_model",
                                                                  num_labels = 2)
        # /bert_pretrain/
        self.device = torch.device("cuda")
        for param in self.bert.parameters():
            param.requires_grad = True  # 每个参数都要 求梯度

    def forward(self, batch_seqs, batch_seq_masks, batch_seq_segments, labels):
        loss, logits = self.bert(input_ids = batch_seqs, attention_mask = batch_seq_masks,
                              token_type_ids=batch_seq_segments, labels = labels,return_dict=False)
        probabilities = nn.functional.softmax(logits, dim=-1)
        logits = torch.Tensor(logits)
        probabilities = nn.functional.softmax(logits, dim=-1)

        return loss, logits, probabilities
    
class BertModelTest(nn.Module):
    def __init__(self, model_path, num_labels=2):  # 设置正确的 num_labels,默认为3
        super(BertModelTest, self).__init__()
        config = BertConfig.from_pretrained(model_path, num_labels=num_labels)
        self.bert = BertForSequenceClassification(config)
        self.device = torch.device("cuda")

    def forward(self, batch_seqs, batch_seq_masks,
                batch_seq_segments, labels):
        loss, logits = self.bert(input_ids=batch_seqs,
                                 attention_mask=batch_seq_masks,
                                 token_type_ids=batch_seq_segments,
                                 labels=labels, return_dict=False)
        probabilities = nn.functional.softmax(logits, dim=-1)
        return loss, logits, probabilities

模型训练

# -*- coding: utf-8 -*-
"""
Created on Thu Mar 12 02:08:46 2020

@author: zhaog
"""
import torch
import torch.nn as nn
import time
from tqdm import tqdm
from sklearn.metrics import roc_auc_score

def correct_predictions(output_probabilities, targets):
    _, out_classes = output_probabilities.max(dim=1)
    correct = (out_classes == targets).sum()
    return correct.item()

def validate(model, dataloader):
    # 开启验证模式
    model.eval()
    device = model.device
    epoch_start = time.time()
    running_loss = 0.0
    running_accuracy = 0.0
    all_prob = []
    all_labels = []
    # 评估时梯度不更新
    with torch.no_grad():
        for (batch_seqs, batch_seq_masks, batch_seq_segments,
             batch_labels) in dataloader:
            # 将数据放入指定设备
            seqs = batch_seqs.to(device)
            masks = batch_seq_masks.to(device)
            segments = batch_seq_segments.to(device)
            labels = batch_labels.to(device)
            loss, logits, probabilities = model(seqs, masks,
                                                segments, labels)
            running_loss += loss.item()
            running_accuracy += correct_predictions(probabilities, labels)
            all_prob.extend(probabilities[:,1].cpu().numpy())
            all_labels.extend(batch_labels)
    epoch_time = time.time() - epoch_start
    epoch_loss = running_loss / len(dataloader)
    epoch_accuracy = running_accuracy / (len(dataloader.dataset))
    return epoch_time, epoch_loss, epoch_accuracy, \
           roc_auc_score(all_labels, all_prob)

def predict(model, test_file, dataloader, device):
    model.eval()
    with torch.no_grad():
        result = []
        for (batch_seqs, batch_seq_masks, batch_seq_segments,
             batch_labels) in dataloader:
            seqs, masks, segments, labels = batch_seqs.to(device), \
                                            batch_seq_masks.to(device),\
                                            batch_seq_segments.to(device), \
                                            batch_labels.to(device)
            _, _, probabilities = model(seqs, masks, segments, labels)
            result.append(probabilities)
    text_result = []
    for i, j in enumerate(test_file):
        text_result.append([j[0], j[1], '相似'
        if torch.argmax(result[i][0]) == 1 else '不相似'])
    return text_result

def train(model, dataloader, optimizer, max_gradient_norm):
    # 开启训练
    model.train()
    device = model.device
    epoch_start = time.time()
    batch_time_avg = 0.0
    running_loss = 0.0
    correct_preds = 0
    tqdm_batch_iterator = tqdm(dataloader)
    for batch_index, (batch_seqs, batch_seq_masks,
                      batch_seq_segments, batch_labels) \
            in enumerate(tqdm_batch_iterator):
        batch_start = time.time()
        # 训练数据放入指定设备,GPU&CPU
        seqs, masks, segments, labels = batch_seqs.to(device),\
                                        batch_seq_masks.to(device), \
                                        batch_seq_segments.to(device),\
                                        batch_labels.to(device)
        optimizer.zero_grad()
        loss, logits, probabilities = model(seqs, masks, segments, labels)
        loss.backward()
        nn.utils.clip_grad_norm_(model.parameters(), max_gradient_norm)
        optimizer.step()
        batch_time_avg += time.time() - batch_start
        running_loss += loss.item()
        correct_preds += correct_predictions(probabilities, labels)
        description = "Avg. batch proc. time: {:.4f}s, loss: {:.4f}"\
                      .format(batch_time_avg/(batch_index+1),
                              running_loss/(batch_index+1))
        tqdm_batch_iterator.set_description(description)
    epoch_time = time.time() - epoch_start
    epoch_loss = running_loss / len(dataloader)
    epoch_accuracy = correct_preds / len(dataloader.dataset)
    return epoch_time, epoch_loss, epoch_accuracy
# -*- coding: utf-8 -*-

import os
import torch
from torch.utils.data import DataLoader
#from data import DataPrecessForSentence
#from utils import train,validate
from transformers import BertTokenizer
#from model import BertModel
from transformers.optimization import AdamW

def main(train_file, dev_file, target_dir,
         epochs=10,
         batch_size=128,
         lr=0.00001,
         patience=3,
         max_grad_norm=10.0,
         checkpoint=None):
    bert_tokenizer = BertTokenizer.from_pretrained('/kaggle/input/textmatch/token/',
                                                   do_lower_case=True)
    device = torch.device("cuda")
    # 保存模型的路径
    if not os.path.exists(target_dir):
        os.makedirs(target_dir)
    print("\t* 加载训练数据...")
    train_data = DataPrecessForSentence(bert_tokenizer, train_file)
    train_loader = DataLoader(train_data, shuffle=True, batch_size=batch_size)
    print("\t* 加载验证数据...")
    dev_data = DataPrecessForSentence(bert_tokenizer, dev_file)
    dev_loader = DataLoader(dev_data, shuffle=True, batch_size=batch_size)
    print("\t* 构建模型...")
    model = BertModel().to(device)
    print("begin to train...")
    # 待优化的参数
    param_optimizer = list(model.named_parameters())
    no_decay = ['bias', 'LayerNorm.bias', 'LayerNorm.weight']
    optimizer_grouped_parameters = [
            {
                    'params':[p for n, p in param_optimizer if
                              not any(nd in n for nd in no_decay)],
                    'weight_decay':0.01
            },
            {
                    'params':[p for n, p in param_optimizer if
                              any(nd in n for nd in no_decay)],
                    'weight_decay':0.0
            }
    ]
    # 优化器
    optimizer = AdamW(optimizer_grouped_parameters, lr=lr)
    scheduler = torch.optim.lr_scheduler.\
        ReduceLROnPlateau(optimizer, mode="max",
                          factor=0.85, patience=0)
    best_score = 0.0
    start_epoch = 1
    epochs_count = [] # 迭代伦次
    train_losses = [] # 训练集loss
    valid_losses = [] # 验证集loss
    if checkpoint:
        checkpoint = torch.load(checkpoint)
        start_epoch = checkpoint["epoch"] + 1
        best_score = checkpoint["best_score"]
        model.load_state_dict(checkpoint["model"])
        optimizer.load_state_dict(checkpoint["optimizer"])
        epochs_count = checkpoint["epochs_count"]
        train_losses = checkpoint["train_losses"]
        valid_losses = checkpoint["valid_losses"]
     # 计算损失、验证集准确度.
    _, valid_loss, valid_accuracy, auc = validate(model, dev_loader)
    patience_counter = 0
    for epoch in range(start_epoch, epochs + 1):
        epochs_count.append(epoch)
        epoch_time, epoch_loss, epoch_accuracy = \
            train(model, train_loader, optimizer, epoch)
        train_losses.append(epoch_loss)
        print("-> Training time: {:.4f}s, loss = {:.4f}, accuracy: {:.4f}%"
              .format(epoch_time, epoch_loss, (epoch_accuracy*100)))
        epoch_time, epoch_loss, epoch_accuracy , \
        epoch_auc= validate(model, dev_loader)
        valid_losses.append(epoch_loss)
        print("-> Valid. time: {:.4f}s, loss: {:.4f}, "
              "accuracy: {:.4f}%, auc: {:.4f}\n"
              .format(epoch_time, epoch_loss,
                      (epoch_accuracy*100), epoch_auc))
        # 更新学习率
        scheduler.step(epoch_accuracy)
        if epoch_accuracy < best_score:
            patience_counter += 1
        else:
            best_score = epoch_accuracy
            patience_counter = 0
            torch.save({"epoch": epoch,
                        "model": model.state_dict(),
                        "best_score": best_score,
                        "epochs_count": epochs_count,
                        "train_losses": train_losses,
                        "valid_losses": valid_losses},
                        os.path.join(target_dir, "best.pth.tar"))
        if patience_counter >= patience:
            print("-> 停止训练")
            break

if __name__ == "__main__":
    main(train_file="/kaggle/input/textmatch/dataset/train.json", dev_file="/kaggle/input/textmatch/dataset/dev.json", target_dir= "models")               

文本预测

import torch
from sys import platform
from torch.utils.data import DataLoader
from transformers import BertTokenizer
# from model import BertModelTest
# from utils import predict
# from data import DataPrecessForSentence

def main(test_file, pretrained_file, batch_size=1):
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    bert_tokenizer = BertTokenizer.from_pretrained('/kaggle/input/textmatch/pretrained_model/',
                                                   do_lower_case=True)
    if platform == "linux" or platform == "linux2":
        checkpoint = torch.load(pretrained_file)
    else:
        checkpoint = torch.load(pretrained_file, map_location=device)
    test_data = DataPrecessForSentence(bert_tokenizer,
                                       test_file, pred=True)
    test_loader = DataLoader(test_data, shuffle=False,
                             batch_size=batch_size)
    model = BertModelTest('/kaggle/input/textmatch/pretrained_model/').to(device)
    model.load_state_dict(checkpoint['model'])
    result = predict(model, test_file, test_loader, device)
    return result

if __name__ == '__main__':
    text = [['微信号怎么二次修改', '怎么再二次修改微信号'],
            ['红米刷什么系统好', '红米可以刷什么系统'],
            ['什么牌子的精油皂好', '什么牌子的精油好'],
            ['鱼竿上有个缘字是什么牌子的','前打鱼竿什么牌子的好']]
    
    result = main(text, '/kaggle/input/textmatch/models/best.pth.tar')
    
    print(10 * "=", "Predict Result", 10 * "=")

    # 在每行中打印每个结果
    for item in result:
        print(item)

操作异常问题与解决方案

1、transformers版本冲突

解决办法,下载项目指定版本:

!pip install transformers==2.10.0  -i https://pypi.tuna.tsinghua.edu.cn/simple

2、文件读取错误,出现无法读取数据集的情况

修改data.py文件里面的读取文件操作,将修改读取.json文件

else:

            ftype = True if file.endswith('.tsv') else False

            limit = 50000

            df = pd.read_csv(file, sep='\t') if ftype else pd.read_json(file,lines=True)

            sentences_1 = map(HanziConv.toSimplified,

                              df['text_a'][:limit].values if ftype else df["sentence1"].iloc[:limit])

            sentences_2 = map(HanziConv.toSimplified,

                              df['text_b'][:limit].values if ftype else df["sentence2"].iloc[:limit])

            labels = df['label'].iloc[:limit].values

3、RuntimeError: Error(s) in loading state_dict for BertModelTest:

      size mismatch for bert.classifier.weight: copying a param with shape torch.Size([2, 768]) from checkpoint, the shape in current model is torch.Size([3, 768]).

      size mismatch for bert.classifier.bias: copying a param with shape torch.Size([2]) from checkpoint, the shape in current model is torch.Size([3]).

解决办法:需要修改model.py文件下来的BertModelTest类中的num_labels修改为2。

4、出现bert-base-cvhinese文件下载不下来的情况

解决办法:将bert-base-cvhinese文件下的config.json、tokenizer.json、tokenizer_config.json、vocab.txt文件分别下载保存重新命名文件夹token中,然后将bert-base-cvhinese修改为token文件夹的路径。 

总结

在我们的实验中,使用主流的预训练模型BERT,我们成功地实现了文本相似度计算任务。该任务的核心目标是通过BERT模型对输入的两段文本进行处理,并判断它们之间是否具有相似性。BERT模型的双向编码器架构使其能够全面理解文本中的语义关系,而不仅仅是单向的传统模型。

通过BERT进行文本相似度计算,我们能够在处理复杂的语境和多义词时取得良好的性能。BERT通过训练过程中的遮蔽语言模型和下一句预测等任务,学习到了丰富的语义表示,这使得它在文本相似度任务中表现出色。在我们的实验结果中,BERT成功捕捉到了输入文本之间的语义信息,有效地判断了它们是否具有相似性。这为解决诸如文本匹配、重述检测等任务奠定了坚实的基础。

总体而言,BERT模型在文本相似度计算任务中的应用展现了其在自然语言处理领域的卓越性能。我们的实验结果为使用BERT解决其他文本相关任务提供了有力的支持,同时也为研究和应用文本相似度计算提供了有益的经验。

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

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

相关文章

统计学-R语言-7.3

文章目录 前言总体方差的检验一个总体方差的检验两个总体方差比的检验 非参数检验总体分布的检验正态性检验的图示法Shapiro-Wilk和K-S正态性检验总体位置参数的检验 练习 前言 本篇文章继续对总体方差的检验进行介绍。 总体方差的检验 一个总体方差的检验 在生产和生活的许多…

Hypermesh中模型抽取中面的方法

一、自动抽取中面 二、手动抽取中面 offsetplanessweeps会记录所抽取的中面由哪两个面形成的 planes&#xff1a;所识别的对面是两个平面&#xff0c;就会在两平面中间区域插入一个中面 sweeps&#xff1a;所识别的对面是两个曲面时&#xff0c;就会在两个曲面中间区域插入一个…

esp32 操作DS1307时钟芯片

电气参数摘要 有VCC供电&#xff0c;IIC活动状态是1.5mA&#xff0c;待机状态200μA&#xff0c;电池电流5nA(MAX50nA&#xff09;无VCC供电的时候&#xff0c;电池电流&#xff0c;300nA&#xff08;时钟运行&#xff09;&#xff0c;10nA&#xff08;时钟停止&#xff09;供…

机器人顶会IROS,ICRA论文模板下载及投稿须知,以及机器人各大会议查询

一、背景 机器人方向&#xff0c;不止期刊TRO&#xff0c;TASE&#xff0c;RAM&#xff0c;RAL上的成果被认可&#xff0c;机器人顶会上的成果也是非常好的。当决定要写一篇IROS论文时&#xff0c;结果IROS论文模板和投稿须知找了半天才找到&#xff0c;且意外发现了一个特别好…

Java 面试题之 IO(一)

字节流 文章目录 字节流InputStream&#xff08;字节输入流&#xff09;OutputStream&#xff08;字节输出流&#xff09; 文章来自Java Guide 用于学习如有侵权&#xff0c;立即删除 InputStream&#xff08;字节输入流&#xff09; InputStream用于从源头&#xff08;通常是…

最全音频总线汇总

本文介绍了常见的音频总线&#xff0c;主要有I2S, AC’97&#xff08;Audio Codec 97&#xff09;, SPI&#xff08;Serial Peripheral Interface&#xff09;,USB Audio, Bluetooth Audio,HDMI, A2B&#xff08;Analog to Digital to Analog&#xff09;, Ethernet Audio I2S…

ros2配合yolov8具体实现

效果图 用yolov8实时检测物体,包括物体的类别,置信度和坐标通过ros2发布出去自定义消息 int64 xmin int64 ymin int64 xmax int64 ymax float32 conf string name发布端代码 from ultralytics import YOLO import cv2 import rclpy from yolo_interfaces.msg import Msgyo…

永宏 plc怎样实现远程调试、远程上下载程序?

准备工作 一台可联网操作的电脑一台单网口的远程透传网关及博达远程透传配置工具网线一条&#xff0c;用于实现网络连接和连接PLC一台永宏 PLC及其编程软件一张4G卡或WIFI天线实现通讯(使用4G联网则插入4G SIM卡&#xff0c;WIFI联网则将WIFI天线插入USB口&#xff09; 第一步…

不会使用这个工具的网工,都不能称为高手

你们好&#xff0c;我的网工朋友。 点开之前&#xff0c;你脑子里闪出来的工具是什么&#xff1f;ping&#xff1f;又或是arp、tracert、route……&#xff1f; 今天要给你分享的是非常经典的Linux网络抓包工具Tcpdump。 它允许用户拦截和显示发送或收到过网络连接到该计算机…

Pytest中doctests的测试方法应用!

在 Python 的测试生态中&#xff0c;Pytest 提供了多种灵活且强大的测试工具。其中&#xff0c;doctests 是一种独特而直观的测试方法&#xff0c;通过直接从文档注释中提取和执行测试用例&#xff0c;确保代码示例的正确性。本文将深入介绍 Pytest 中 doctests 的测试方法&…

幻兽帕鲁服务器视频教程,3分钟快速搭建,新手0基础也可以!

幻兽帕鲁服务器搭建教程&#xff0c;基于阿里云计算巢新手3分钟0基础搞定&#xff0c;详细参考 aliyunbaike.com/go/palworld 视频教程 1分钟部署幻兽帕鲁搭建&#xff0c;新手成功创建&#xff01; 大家也可以参考阿里云百科下方的教程&#xff1a; 如何自建幻兽帕鲁服务器&a…

二极管漏电流对单片机ad采样偏差的影响

1&#xff0c;下图是常规的单片机采集电压电路&#xff0c;被测量电压经过电阻分压&#xff0c;给到mcu采集&#xff0c;反向二极管起到钳位作用&#xff0c;避免高压打坏mcu。 2&#xff0c;该电路存在的问题 二极管存在漏电流&#xff0c;会在100k电阻上产生叠加电压&#x…

pve宿主机更改网络导致没网,pve更改ip

一、问题描述 快过年了&#xff0c;我把那台一直在用的小型服务器&#xff0c;带回去了&#xff0c;导致网络发生了变更&#xff0c;需要对网络进行调整&#xff0c;否则连不上网&#xff0c;我这里改的是宿主机&#xff0c;不是pve虚拟机中的系统。 二、解决方法 pve用的是…

07.领域驱动设计:3种常见微服务架构模型的对比和分析

目录 1、概述 2、整洁架构 3、六边形架构 4、三种微服务架构模型的对比和分析 5、从三种架构模型看中台和微服务设计 5.1 中台建设要聚焦领域模型 5.2 微服务要有合理的架构分层 5.2.1 项目级微服务 5.2.2 企业级中台微服务 5.3 应用和资源的解耦与适配 6、总结 1、概…

2024年CSC公派研究生项目(含联培)选派办法及解读

2024年春节将至&#xff0c;知识人网提前祝大家新年快乐&#xff0c;心想事成&#xff01;同时提醒申请者关注国家留学基金委&#xff08;CSC&#xff09;的申报政策。近日CSC官网发布了2024年国家建设高水平大学公派研究生项目通知&#xff0c;知识人网小编现将其选派办法原文…

13.前端--CSS-盒子模型

1.盒子模型的组成 CSS 盒子模型本质上是一个盒子&#xff0c;封装周围的 HTML 元素&#xff0c;它包括&#xff1a;边框、外边距、内边距、和 实际内容 2.边框&#xff08;border&#xff09; 2.1 边框的使用 1、border设置元素的边框。边框有三部分组成:边框宽度(粗细) 边框…

ucharts 让x轴文字倾斜文字

ucharts 让x轴文字倾斜文字 xAxis: {disableGrid: true,scrollShow: false,//x轴文字倾斜rotateLabel:true},

2023年天猫食用油市场行业分析(电商数据查询软件):市场细分,营养调和油高速成长

食用油是人类膳食的重要组成部分&#xff0c;除了为日常饮食提供美味外&#xff0c;也是人体所需脂肪和能量的重要来源&#xff0c;对人体健康发挥着重要作用。因此&#xff0c;作为日常生活中的刚需品&#xff0c;食用油市场的整体规模也较大。 首先来看食用油市场的年度销售…

华为OD-华为机试精讲500篇系列文章目录介绍(持续补充ing)

目录 背景介绍 什么是华为OD&#xff1f; OD现状 OD趋势 华为OD机考刷题攻略 1、刷题资料&#xff1a;投递岗位通过筛选后提供 2、注意事项&#xff1a; 真题代码目录 背景介绍 经济下行的这几年&#xff0c;每个人都感同身受&#xff0c;如何让自己在芸芸众生中脱颖而…

深度学习之卷积神经网络

卷积神经网络简称为CNN 首先我们来回顾一下&#xff0c;我们之前学到的全连接的神经网络&#xff1a; 上面我们通过线性层串行连接起来的神经网络&#xff0c;我们叫做全链接的网络&#xff0c;在线性层里面&#xff0c;我们的输入值和任意的输出值之间都存在权重&#xff0c;…