Sentence-BERT实现文本匹配【分类目标函数】

BERT句向量(一):Sentence-BERT 前言 句向量:能够表征整个句子语义的向量,目前效果比较好的方法还是通过bert模型结构来实现,也是本文的主题。 有了句向量,我们可以用来进行聚类,处理大规模的文本相似度比较,或者基于语义搜索的信息检索。 例如搜索系统中的输入query和匹配文档document、Q&A任务的问题和答案等等,都可以转化为计算两个句子的语义相似/相关度,相关度最高的n个作为模型的返回结果。 题外话 这种类似的模型一般称为passage retrieval models,即段落检索,有两个代表: sparse model 阅读详情

引言

从这篇文章开始进入文本系列的BERT预训练模型时代,本文实战Sentence-BERT提出的如何训练嵌入模型的方法。实现类似Huggingface的风格,不同方法的实现之间可能会有一些重复,但每个方法是独立的,降低了复杂性。

架构

img

我们首先来看的是这种孪生网络结构。如上图所示,句子A和句子B经过同一个预训练好的BERT模型,然后经过池化操作得到定长向量u和v,最后对这两个向量进行一些处理和拼接喂给一个分类层得到最终的输出——对应类别的logits。

可以用于有相似标签(1)和不相似标签(0)的数据集,判断给定的语句对是相似还是不相似的,作为一个分类任务。但在推理阶段,拿到这两个语句的句嵌入后,不需要真的经过Softmax分类器,而是直接计算句嵌入之间的余弦相似度即可。

实现

实现采用类似Huggingface的形式,每个文件夹下面有一种模型。分为modeling、arguments、trainer等不同的文件。不同的架构放置在不同的文件夹内。

modeling.py:

from dataclasses import dataclass

import torch
from torch import Tensor, nn

from transformers.file_utils import ModelOutput

from transformers import (
    AutoModel,
    AutoTokenizer,
)

import numpy as np
from tqdm.autonotebook import trange
from typing import Optional

# 定义输出类,继承ModelOutput
@dataclass
class BiOutput(ModelOutput):
    loss: Optional[Tensor] = None
    scores: Optional[Tensor] = None

# 基于分类目标函数训练的Sentence Bert模型
class SentenceBert(nn.Module):
    def __init__(
        self,
        model_name: str,
        trust_remote_code: bool = True,
        max_length: int = None,
        num_classes: int = 2,
        pooling_mode: str = "mean",
        normalize_embeddings: bool = False,
    ) -> None:
        super().__init__()
        self.model_name = model_name
        self.normalize_embeddings = normalize_embeddings

        self.device = "cuda" if torch.cuda.is_available() else "cpu"

        self.tokenizer = AutoTokenizer.from_pretrained(
            model_name, trust_remote_code=trust_remote_code
        )
        self.model = AutoModel.from_pretrained(
            model_name, trust_remote_code=trust_remote_code
        ).to(self.device)

        self.max_length = max_length
        self.pooling_mode = pooling_mode

        self.loss_fct = nn.CrossEntropyLoss(reduction="mean")
        # (u, v, |u - v|)
        self.classifier = nn.Linear(self.model.config.hidden_size * 3, num_classes)

    def sentence_embedding(self, last_hidden_state, attention_mask):
        # 支持平均池化和cls token
        if self.pooling_mode == "mean":
            attention_mask = attention_mask.unsqueeze(-1).float()
            return torch.sum(last_hidden_state * attention_mask, dim=1) / torch.clamp(
                attention_mask.sum(1), min=1e-9
            )
        else:
            # cls
            return last_hidden_state[:, 0]
 # 将原始文本编码成句向量,支持批处理防止OOM
    def encode(
        self,
        sentences: str | list[str],
        batch_size: int = 64,
        convert_to_tensor: bool = True,
        show_progress_bar: bool = False,
    ):
        if isinstance(sentences, str):
            sentences = [sentences]

        all_embeddings = []

        for start_index in trange(
            0, len(sentences), batch_size, desc="Batches", disable=not show_progress_bar
        ):
            batch = sentences[start_index : start_index + batch_size]

            features = self.tokenizer(
                batch,
                padding=True,
                truncation=True,
                return_tensors="pt",
                return_attention_mask=True,
                max_length=self.max_length,
            ).to(self.device)

            out_features = self.model(**features, return_dict=True)
            embeddings = self.sentence_embedding(
                out_features.last_hidden_state, features["attention_mask"]
            )
            if not self.training:
                # 非训练模式下可以脱离计算图,节省显存
                embeddings = embeddings.detach()

            if self.normalize_embeddings:
                embeddings = torch.nn.functional.normalize(embeddings, p=2, dim=1)

            if not convert_to_tensor:
                embeddings = embeddings.cpu()

            all_embeddings.extend(embeddings)
  # 支持将句向量转换为Tensor或Numpy
        if convert_to_tensor:
            all_embeddings = torch.stack(all_embeddings)
        else:
            all_embeddings = np.asarray([emb.numpy() for emb in all_embeddings])

        return all_embeddings

    def concat_embedding(self, source_embeddings, target_embeddings):
        # (u, v, |u - v|)的拼接
        embeddings = torch.cat(
            [
                source_embeddings,
                target_embeddings,
                torch.abs(source_embeddings - target_embeddings),
            ],
            dim=-1,
        )
        return self.classifier(embeddings)

    def compute_loss(self, source_embed, target_embed, labels):
        logits = self.concat_embedding(source_embed, target_embed)
        labels = torch.LongTensor(labels).to(self.device)
        # 计算损失
        return self.loss_fct(logits, labels)

    def forward(self, source, target, labels) -> BiOutput:
        """
        forward仅是用于训练,推理时直接使用encode即可
        Args:
            source :
            target :
        """
        source_embed = self.encode(source)
        target_embed = self.encode(target)

        scores = torch.cosine_similarity(source_embed, target_embed)

        loss = self.compute_loss(source_embed, target_embed, labels)
        return BiOutput(loss, scores)

    def save_pretrained(self, output_dir: str):
        # 修改保存模型参数的方法
        state_dict = self.model.state_dict()
        state_dict = type(state_dict)(
            {k: v.clone().cpu().contiguous() for k, v in state_dict.items()}
        )
        self.model.save_pretrained(output_dir, state_dict=state_dict)

整个模型的实现放到modeling.py文件中。

arguments.py:

from dataclasses import dataclass, field
from typing import Optional

import os


@dataclass
class ModelArguments:
    model_name_or_path: str = field(
        metadata={
            "help": "Path to pretrained model"
        }
    )
    config_name: Optional[str] = field(
        default=None,
        metadata={
            "help": "Pretrained config name or path if not the same as model_name"
        },
    )
    tokenizer_name: Optional[str] = field(
        default=None,
        metadata={
            "help": "Pretrained tokenizer name or path if not the same as model_name"
        },
    )


@dataclass
class DataArguments:
    train_data_path: str = field(
        default=None, metadata={"help": "Path to train corpus"}
    )
    eval_data_path: str = field(default=None, metadata={"help": "Path to eval corpus"})
    max_length: int = field(
        default=512,
        metadata={
            "help": "The maximum total input sequence length after tokenization for input text."
        },
    )

    def __post_init__(self):
        if not os.path.exists(self.train_data_path):
            raise FileNotFoundError(
                f"cannot find file: {self.train_data_path}, please set a true path"
            )
        
        if not os.path.exists(self.eval_data_path):
            raise FileNotFoundError(
                f"cannot find file: {self.eval_data_path}, please set a true path"
            )

定义了模型和数据相关参数。

dataset.py:

from torch.utils.data import Dataset
from datasets import Dataset as dt
import pandas as pd

from utils import build_dataframe_from_csv


class PairDataset(Dataset):
    def __init__(self, data_path: str) -> None:

        df = build_dataframe_from_csv(data_path)
        self.dataset = dt.from_pandas(df, split="train")

        self.total_len = len(self.dataset)

    def __len__(self):
        return self.total_len

    def __getitem__(self, index) -> dict[str, str]:
        query1 = self.dataset[index]["query1"]
        query2 = self.dataset[index]["query2"]
        label = self.dataset[index]["label"]
        return {"query1": query1, "query2": query2, "label": label}


class PairCollator:
    def __call__(self, features) -> dict[str, list[str]]:
        queries1 = []
        queries2 = []
        labels = []

        for feature in features:
            queries1.append(feature["query1"])
            queries2.append(feature["query2"])
            labels.append(feature["label"])

        return {"source": queries1, "target": queries2, "labels": labels}

数据集类考虑了LCQMC数据集的格式,即成对的语句和一个数值标签。类似:

Hello. Hi. 1
Nice to see you. Nice 0

trainer.py:

import torch
from transformers.trainer import Trainer

from typing import Optional
import os
import logging

from modeling import SentenceBert

TRAINING_ARGS_NAME = "training_args.bin"
logger = logging.getLogger(__name__)


class BiTrainer(Trainer):

    def compute_loss(self, model: SentenceBert, inputs, return_outputs=False):
        outputs = model(**inputs)
        loss = outputs.loss

        return (loss, outputs) if return_outputs else loss

    def _save(self, output_dir: Optional[str] = None, state_dict=None):
        # If we are executing this function, we are the process zero, so we don't check for that.
        output_dir = output_dir if output_dir is not None else self.args.output_dir
        os.makedirs(output_dir, exist_ok=True)
        logger.info(f"Saving model checkpoint to {output_dir}")

        self.model.save_pretrained(output_dir)

        if self.tokenizer is not None:
            self.tokenizer.save_pretrained(output_dir)

        # Good practice: save your training arguments together with the trained model
        torch.save(self.args, os.path.join(output_dir, TRAINING_ARGS_NAME))

继承🤗 Transformers的Trainer类,重写了compute_loss和_save方法。

这样我们就可以利用🤗 Transformers来训练我们的模型了。

utils.py:

import torch
import pandas as pd
from scipy.stats import pearsonr, spearmanr
from typing import Tuple


def build_dataframe_from_csv(dataset_csv: str) -> pd.DataFrame:
    df = pd.read_csv(
        dataset_csv,
        sep="\t",
        header=None,
        names=["query1", "query2", "label"],
    )

    return df


def compute_spearmanr(x, y):
    return spearmanr(x, y).correlation


def compute_pearsonr(x, y):
    return pearsonr(x, y)[0]


def find_best_acc_and_threshold(scores, labels, high_score_more_similar: bool):
    """Copied from https://github.com/UKPLab/sentence-transformers/tree/master"""
    assert len(scores) == len(labels)
    rows = list(zip(scores, labels))

    rows = sorted(rows, key=lambda x: x[0], reverse=high_score_more_similar)
    print(rows)

    max_acc = 0
    best_threshold = -1
    # positive examples number so far
    positive_so_far = 0
    # remain negative examples
    remaining_negatives = sum(labels == 0)

    for i in range(len(rows) - 1):
        score, label = rows[i]
        if label == 1:
            positive_so_far += 1
        else:
            remaining_negatives -= 1

        acc = (positive_so_far + remaining_negatives) / len(labels)
        if acc > max_acc:
            max_acc = acc
            best_threshold = (rows[i][0] + rows[i + 1][0]) / 2

    return max_acc, best_threshold


def metrics(y: torch.Tensor, y_pred: torch.Tensor) -> Tuple[float, float, float, float]:
    TP = ((y_pred == 1) & (y == 1)).sum().float()  # True Positive
    TN = ((y_pred == 0) & (y == 0)).sum().float()  # True Negative
    FN = ((y_pred == 0) & (y == 1)).sum().float()  # False Negatvie
    FP = ((y_pred == 1) & (y == 0)).sum().float()  # False Positive
    p = TP / (TP + FP).clamp(min=1e-8)  # Precision
    r = TP / (TP + FN).clamp(min=1e-8)  # Recall
    F1 = 2 * r * p / (r + p).clamp(min=1e-8)  # F1 score
    acc = (TP + TN) / (TP + TN + FP + FN).clamp(min=1e-8)  # Accurary
    return acc, p, r, F1


def compute_metrics(predicts, labels):
    return metrics(labels, predicts)

定义了一些帮助函数,从sentence-transformers库中拷贝了寻找最佳准确率阈值的实现find_best_acc_and_threshold。

除了准确率,还计算了句嵌入的余弦相似度与真实标签之间的斯皮尔曼等级相关系数指标。

最后定义训练和测试脚本。

train.py:

from transformers import set_seed, HfArgumentParser, TrainingArguments

import logging
from pathlib import Path

from datetime import datetime

from modeling import SentenceBert
from trainer import BiTrainer
from arguments import DataArguments, ModelArguments
from dataset import PairCollator, PairDataset

logger = logging.getLogger(__name__)
logging.basicConfig(
    format="%(asctime)s - %(levelname)s - %(name)s - %(message)s",
    datefmt="%m/%d/%Y %H:%M:%S",
    level=logging.INFO,
)


def main():
    parser = HfArgumentParser((TrainingArguments, DataArguments, ModelArguments))
    training_args, data_args, model_args = parser.parse_args_into_dataclasses()
 # 根据当前时间生成输出目录
    output_dir = f"{training_args.output_dir}/{model_args.model_name_or_path.replace('/', '-')}-{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}"
    training_args.output_dir = output_dir

    logger.info(f"Training parameters {training_args}")
    logger.info(f"Data parameters {data_args}")
    logger.info(f"Model parameters {model_args}")
 # 设置随机种子
    set_seed(training_args.seed)
 # 加载预训练模型
    model = SentenceBert(
        model_args.model_name_or_path,
        trust_remote_code=True,
        max_length=data_args.max_length,
    )
 
    tokenizer = model.tokenizer
 # 构建训练和测试集
    train_dataset = PairDataset(data_args.train_data_path)
    eval_dataset = PairDataset(data_args.eval_data_path)
 # 传入参数
    trainer = BiTrainer(
        model=model,
        args=training_args,
        train_dataset=train_dataset,
        eval_dataset=eval_dataset,
        data_collator=PairCollator(),
        tokenizer=tokenizer,
    )
    Path(training_args.output_dir).mkdir(parents=True, exist_ok=True)
 # 开始训练
    trainer.train()
    trainer.save_model()


if __name__ == "__main__":
    main()

训练

基于train.py定义了train.sh传入相关参数:

timestamp=$(date +%Y%m%d%H%M)
logfile="train_${timestamp}.log"

# change CUDA_VISIBLE_DEVICES
CUDA_VISIBLE_DEVICES=3 nohup python train.py \
    --model_name_or_path=hfl/chinese-macbert-large \
    --output_dir=output \
    --train_data_path=data/train.txt \
    --eval_data_path=data/dev.txt \
    --num_train_epochs=3 \
    --save_total_limit=5 \
    --learning_rate=2e-5 \
    --weight_decay=0.01 \
    --warmup_ratio=0.01 \
    --bf16=True \
    --eval_strategy=epoch \
    --save_strategy=epoch \
    --per_device_train_batch_size=64 \
    --report_to="none" \
    --remove_unused_columns=False \
    --max_length=128 \
    > "$logfile" 2>&1 &

以上参数根据个人环境修改,这里使用的是哈工大的chinese-macbert-large预训练模型。

注意:

  • --remove_unused_columns是必须的。
  • 通过bf16=True可以加速训练同时不影响效果。
  • 其他参数可以自己调整。
...
100%|██████████| 11193/11193 [46:22<00:00,  4.32it/09/02/2024 20:14:12 - INFO - trainer - Saving model checkpoint to output/hfl-chinese-macbert-large-2024-09-02_19-27-42/checkpoint-11193
100%|██████████| 11193/11193 [46:40<00:00,  4.00it/s]
09/02/2024 20:14:29 - INFO - trainer - Saving model checkpoint to output/hfl-chinese-macbert-large-2024-09-02_19-27-42
{'eval_loss': 0.32857951521873474, 'eval_runtime': 56.1904, 'eval_samples_per_second': 156.646, 'eval_steps_per_second': 19.594, 'epoch': 3.0}
{'train_runtime': 2800.0605, 'train_samples_per_second': 255.815, 'train_steps_per_second': 3.997, 'train_loss': 0.1678411467916938, 'epoch': 3.0}

这里仅训练了3轮,我们拿最后保存的模型output/hfl-chinese-macbert-large-2024-09-02_19-27-42进行测试。

测试

test.py: 测试脚本见后文的完整代码。

test.sh:

# change CUDA_VISIBLE_DEVICES
CUDA_VISIBLE_DEVICES=0 python test.py \
    --model_name_or_path=output/hfl-chinese-macbert-large-2024-09-02_19-27-42/checkpoint-11193 \
    --test_data_path=data/test.txt

输出:

TestArguments(model_name_or_path='output/hfl-chinese-macbert-large-2024-09-02_19-27-42/checkpoint-11193', test_data_path='data/test.txt', max_length=64, batch_size=128)
Batches: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 98/98 [00:11<00:00,  8.71it/s]
Batches: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 98/98 [00:10<00:00,  8.99it/s]
max_acc: 0.8918, best_threshold: 0.898765
spearman corr: 0.7982 |  pearson_corr corr: 0.7514 | compute time: 22.19s
accuracy=0.892 precision=0.896 recal=0.886 f1 score=0.8912

正如上文所说,我们还计算了spearman。

测试集上的准确率达到89.2%,超过了之前我们看到的所有模型。

如何学习AI大模型?

大模型时代,火爆出圈的LLM大模型让程序员们开始重新评估自己的本领。 “AI会取代那些行业?”“谁的饭碗又将不保了?”等问题热议不断。

不如成为「掌握AI工具的技术人」,毕竟AI时代,谁先尝试,谁就能占得先机!

想正式转到一些新兴的 AI 行业,不仅需要系统的学习AI大模型。同时也要跟已有的技能结合,辅助编程提效,或上手实操应用,增加自己的职场竞争力。

但是LLM相关的内容很多,现在网上的老课程老教材关于LLM又太少。所以现在小白入门就只能靠自学,学习成本和门槛很高

那么我作为一名热心肠的互联网老兵,我意识到有很多经验和知识值得分享给大家,希望可以帮助到更多学习大模型的人!至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

这份完整版的大模型 AI 学习资料已经上传优快云,朋友们如果需要可以微信扫描下方优快云官方认证二维码免费领取【保证100%免费】

👉 福利来袭优快云大礼包:《2025最全AI大模型学习资源包》免费分享,安全可点 👈

全套AGI大模型学习大纲+路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

img

640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

👉学会后的收获:👈
• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。

👉 福利来袭优快云大礼包:《2025最全AI大模型学习资源包》免费分享,安全可点 👈

img

这份完整版的大模型 AI 学习资料已经上传优快云,朋友们如果需要可以微信扫描下方优快云官方认证二维码免费领取【保证100%免费】

作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。

Ollama 可以在 Windows 上运行了 阅读详情

相关推荐

DeepSeek本地部署详细指南

通过上述步骤,你可以在本地成功部署DeepSeek模型,并通过Ollama或Open Web UI与模型进行交互。本地部署不仅能够保护数据隐私,还能根据需求灵活调整模型参数,满足不同场景下的使用需求。如果你在部署过程中遇到任何问题,可以在评论区留言,我们将一起解决。希望这篇教程能帮助你顺利部署DeepSeek模型,开启高效开发的新旅程!

m0_56896669的博客 14万+

一文彻底整明白,基于Ollama工具的LLM大语言模型Web可视化对话机器人部署指南

在上一篇博文中,我们在本地部署了**Llama 3 8B**参数大模型,并用 Python 写了一个控制台对话客户端,基本能愉快的与 Llama 大模型对话聊天了。但控制台总归太技术化,体验不是很友好,我们希望能有个类似 ChatGPT 那样的 Web 聊天对话界面,本博文就安排起来……

老牛啊 1万+

语义匹配(一)【NLP论文复现】Sentence-BERT 句子语义匹配模型的tensorflow实现以及训练Trick

Sentence-BERT 句子语义匹配模型的tensorflow实现以及训练trick论文模型回顾建模与训练模型代码部分数据处理训练模型训练Tricktrick1 warm up代码实现:trick2 focal loss代码实现:总结与思考 论文模型回顾 论文链接:https://arxiv.org/abs/1908.10084 文章在已有的语义匹配模型的基础上提出了基于Bert的句义匹配孪生网络 模型介绍:将两个句子通过Bert(注意:在对句子相似度建模时,两个句子经过的Bert层应该是共享权重.

weixin_45839693的博客 6702

使用ollama在本地部署llama3-8b大模型

使用ollama在本地部署llama3-8b大模型

weixin_39945822的博客 1万+

Sentence - BERT(SBERT)

的经典训练架构,用于文本匹配任务,核心是用孪生(Siamese)BERT 网络生成句子嵌入(Sentence Embeddings),实现文本语义匹配。

mayaohao的博客 1098

【EMNLP 2019】Sentence-BERT

在许多NLP任务(特别是在文本语义匹、文本向量检索等)需要训练优质的句子表示向量,模型通过计算两个句子编码后的Embedding在表示空间的相似度来衡量这两个句子语义上的相关程度,从而决定其匹配分数。尽管基于BERT在诸多NLP任务上取得了不错的性能,但其自身导出的句向量(【CLS】输出的向量、对所有输出字词token向量求平均)质量较低。由于BERT输出token向量预训练中,后面接的的分类的任务。所以其实输出token向量并不适合作为生成句子表示。

2359

Sentence Bert模型在文本匹配中的高效应用与优化策略

本文深入探讨了Sentence Bert模型在文本匹配任务中的高效应用与优化策略。针对传统Bert模型在海量匹配场景下的效率瓶颈,Sentence Bert通过预计算句向量实现快速语义检索,大幅提升性能。文章详细解析了其孪生网络架构、三种核心训练目标(分类、回归、三重损失),并提供了从数据准备、模型训练、评估到部署上线的完整实战指南。同时,分享了数据增强、模型微调、知识蒸馏及工程化优化等进阶技巧,帮助开发者在搜索、推荐、问答等场景中构建高性能语义匹配系统。

m0n1o2p的博客 411

LLM的MCP协议:初识MCP,搭建第一个MCP Server

MCP(Model Context Protocol),是一个开发的协议,标准化了应用程序如何为大模型提供上下文。MCP提供了一个标准的为LLM提供数据、工具的方式,使用MCP会更容易的构建Agent或者是基于LLM的复杂工作流。

Criss@陈磊 2万+

文本匹配之Sentence Bert模型

文章目录前言Bert句向量表示效果为什么不好?Sentence Bert 原理 前言 目前,对于大部分的NLP任务来说,通过对预训练模型进行微调的方式已经取得了很好的效果,但对于某些特定的场景,我们常常需要的是文本的表示,比如文本聚类,文本匹配(搜索场景)等等; 在进行文本匹配任务时,在计算语义相似度时,Bert模型需要将两个句子同时进入模型,进行信息交互,假如有10000个句子,找出最相似的句子对,需要计算(10000*9999/2)次,非常耗时。而Sentencebert可以预先将标准库中的问题预先离线

dzysunshine的博客 6391

Vivado安装教程:多版本共存的配置技巧

详解Vivado安装教程中的多版本共存配置技巧,帮助用户在同一系统中管理不同版本的Vivado开发环境,提升开发效率与兼容性,适用于需要切换版本的FPGA开发者。

weixin_35257663的博客 1775

Nvidia Tesla A100 驱动安装方法

Nvidia Tesla A100 驱动安装方法 遇到的问题:以前安装tesla系列、geforce系列等gpu 驱动的时候,只需执行nvidiaxxxx.run驱动包或者安装nvidiaxxxx.rpm包即可,但遇到新的GPU Nvidia Tesla A100的时候,安装完驱动似乎不起作用,找了半天资料,原来需要以下步骤才可以使用;

qq_24343177的博客 2万+

Sentence-BERT实现文本匹配【回归目标函数】

我们通过Sentence-Bert提出的分类目标函数来训练句子嵌入模型,本文同样基于Sentence-Bert的架构,但改用回归目标函数。

日积月累,天道酬勤 1588

一体化伺服电机与施耐德PLC TM241CEC24T在Canopen协议下的应用

一.硬件组成 软件组成:施耐德SoMachineV4.3二.○1.打开SoMachineV4.3,点击“新建项目”○2.点击“空白项目”○3.项目命名○4.点击“创建项目” 三. 点击“Logic Builder” 四. ○1.右击项目”PMM_CANOPEN_ST”添加设备○2.点击”LogicController”选择PLC型号TM241CEC24T/U○3.点击“添加设备” 五. ○1.右击CAN_1,添加设备○2.选择“CANopen Perfomance”○3.点击“添加设备”

m0_46512607的博客 2520

文本匹配利器:从孪生网络到Sentence-BERT综述

本文首发于公众号【NLP情报局】,如需转载请声明作者和来源 文本匹配是自然语言处理领域一个基础且重要的方向,一般研究两段文本之间的关系。文本相似度、自然语言推理、问答系统、信息检索都可以看作针对不同数据和场景的文本匹配应用。 本文总结了文本匹配任务中的经典网络Siamse Network,它和近期预训练语言模型的组合,一些调优技巧以及在线下数据集上的效果检验。 1、Siamese 孪生网络 在正式介绍之前,我们先来看一个有趣的故事。 孪生网络的由来 “Siamese”中的“Siam”是古时泰国的称呼,中文译

weixin_43569819的博客 1832

使用mne包来对脑电数据进行预处理(一)

MNE(MNE-Python)是一个用于处理脑电(EEG)、磁图(MEG)和其他神经科学数据的Python库。它提供了丰富的功能,包括数据加载、预处理、分析和可视化,旨在帮助研究人员和神经科学家更轻松地进行脑电数据的处理和分析。在本文中,我们使用mne来对不同的格式的脑电数据集进行数据读取。

m0_71596228的博客 4304

Polyworks宏脚本开发入门:5分钟搞定环境搭建与基础命令录制

本文详细介绍了Polyworks宏脚本开发的入门指南,包括环境搭建、基础命令录制和核心对象操作。通过5分钟快速启动开发模式,掌握自动化操作流程和脚本调试技巧,帮助工程师高效完成工业测量与三维检测任务。

weixin_29306875的博客 535

Embedding技术:Sentence-BERT句嵌入模型介绍和实践

Sentence-BERT是一种句嵌入表征模型,常用于文本语义相似度的匹配,本篇对Sentence-BERT做理论介绍,并结合领域文本数据进行实践,训练句嵌入实现语义检索。

2401_85375151的博客 3748

用Frida-RPC搞定大麦App最新版签名:一个脚本解决x-sign和x-mini-wua

本文深入解析大麦App最新版签名机制(x-sign和x-mini-wua),详细介绍如何利用Frida-RPC技术开发稳定脚本获取签名参数。通过实战案例展示Java上下文切换、参数序列化等关键技术解决方案,为安全研究和技术验证提供可靠方案。

weixin_42525738的博客 643

【科研】BERT模型理论详解

原文:https://cloud.tencent.com/developer/article/1389555 本文首先介绍BERT模型要做什么,即:模型的输入、输出分别是什么,以及模型的预训练任务是什么;然后,分析模型的内部结构,图解如何将模型的输入一步步地转化为模型输出;最后,我们在多个中/英文、不同规模的数据集上比较了BERT模型与现有方法的文本分类效果。 模型的输入/输出 BERT模型的全称是:BidirectionalEncoder Representations from Transforme

weixin_39798910的博客 4万+

Sony微单相机alpha6000 wifi远程控制(1)

引言 Sony’s Camera Remote API beta SDK allows you to control a number of Sony cameras, including Sony Action cams, Sony Alpha cameras and Lens Style cameras, wirelessly from another device. 索尼于2017年三月Re...

markfuk996的博客 4966

FineReport SQL查询分页

打开模板>模板web属性>分页预览设置,选择为该模板单独设置,将默认的工具栏按钮全部清除掉,然后依次添加两个自定义按钮,一个邮件按钮,两个自定义按钮,一个Word格式,一个PDF按钮。如下所示:注:使用具体格式按钮,如邮件、Word格式、PDF按钮是为了JS直接使用控件名称获取空间方便修改其内容;

lep的博客 2428
上一篇: 不懂代码真的不要再做AI产品经理了
下一篇: 从销售到 AI 算法工程师 | 转行人工智能大模型(含面经&裁员幸存指南)
少喝冰美式
博客等级 码龄3年 6839粉丝 517原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值