畅游NLP海洋:HuggingFace的快速入门

目录

  • 前言
  • 一、HuggingFace介绍
    • 1-1、HuggingFace的介绍
    • 1-2、安装
  • 二、Tokenizer分词库:分词工具
    • 2-0、加载BertTokenizer:需要传入预训练模型的名字
    • 2-1、使用Tokenizer对句子编码:
    • 2-2、使用增强Tokenizer对句子编码:
    • 2-3、批量编码单个句子:
    • 2-4、添加新词:
    • 2-5、AutoTokenizer与BertTokenizer的区别
  • 三、Datasets数据集库: 数据集使用
    • 3-1、数据集使用
    • 3-2、数据集操作
    • 3-3、评价函数
  • 四、模型
    • 4-1、各类NLP任务的常用模型
  • 五、实战案例分析
    • 5-1、Kaggle竞赛 Real or Not? NLP with Disaster Tweets 文本分类
      • 5-1-1、数据介绍
    • 5-2、训练模型
  • 总结


前言

Hugging Face是一个以自然语言处理(NLP)为重点的技术公司,也是一个开源社区和平台,旨在提供丰富的NLP模型、工具和资源。 Hugging Face的目标是成为NLP领域的社区和创新驱动者,他们通过为开发者和研究人员提供开源工具、预训练模型和数据集来实现这一目标。Hugging Face的开源库和工具广泛应用于各种NLP任务,包括文本分类、命名实体识别、情感分析、机器翻译等。

一、HuggingFace介绍

1-1、HuggingFace的介绍

Hugging Face是一个致力于自然语言处理(NLP)领域的开源社区和技术公司。他们提供了一个广泛的NLP工具和资源平台,旨在帮助开发者和研究人员快速构建、训练和部署各种NLP模型。
通过Hugging Face,你可以使用他们开发的开源库和工具,如transformers、tokenizers和datasets等,来处理文本数据、构建预训练的Transformer模型,并进行微调和迁移学习。这些工具支持各种常见的NLP任务,如文本分类、命名实体识别、情感分析等。
在这里插入图片描述

HuggingFace的主要库为

  • Transformer模型库: 调用各类预训练模型
  • Datasets数据集库: 数据集使用
  • Tokenizer分词库:分词工具

官方文档:https://huggingface.co/docs

1-2、安装

# 安装transformers和datasets包
pip install transformers  -i https://mirror.baidu.com/pypi/simple

pip install datasets  -i https://mirror.baidu.com/pypi/simple

二、Tokenizer分词库:分词工具

2-0、加载BertTokenizer:需要传入预训练模型的名字

from transformers import BertTokenizer

#加载预训练字典和分词方法
tokenizer = BertTokenizer.from_pretrained(
    pretrained_model_name_or_path='bert-base-chinese',  # 可选,huggingface 中的预训练模型名称或路径,默认为 bert-base-chinese
    cache_dir=None,  # 将数据保存到的本地位置,使用cache_dir 可以指定文件下载位置
    force_download=False,   
)

2-1、使用Tokenizer对句子编码:

sents = [
    '选择珠江花园的原因就是方便。',
    '笔记本的键盘确实爽。',
    '房间太小。其他的都一般。',
    '今天才知道这书还有第6卷,真有点郁闷.',
    '机器背面似乎被撕了张什么标签,残胶还在。',
]
#编码两个句子
out = tokenizer.encode(
    text=sents[0],
    text_pair=sents[1],  # 一次编码两个句子,若没有text_pair这个参数,就一次编码一个句子

    #当句子长度大于max_length时,截断
    truncation=True,

    #一律补pad到max_length长度
    padding='max_length',   # 少于max_length时就padding
    add_special_tokens=True,
    max_length=30, # 指定最大长度为30。
    return_tensors=None,  # None表示不指定数据类型,默认返回list
)

print(out)
print(tokenizer.decode(out))

输出:开头是特殊符号 [CLS],两个句子中间用 [SEP] 分隔,句子末尾也是 [SEP],最后用 [PAD] 将句子填充到 max_length 长度

[101, 6848, 2885, 4403, 3736, 5709, 1736, 4638, 1333, 1728, 2218, 3221, 3175, 912, 511, 102, 5011, 6381, 3315, 4638, 7241, 4669, 4802, 2141, 4272, 511, 102, 0, 0, 0]
[CLS] 选 择 珠 江 花 园 的 原 因 就 是 方 便 。 [SEP] 笔 记 本 的 键 盘 确 实 爽 。 [SEP] [PAD] [PAD] [PAD]

2-2、使用增强Tokenizer对句子编码:

sents = [
    '选择珠江花园的原因就是方便。',
    '笔记本的键盘确实爽。',
    '房间太小。其他的都一般。',
    '今天才知道这书还有第6卷,真有点郁闷.',
    '机器背面似乎被撕了张什么标签,残胶还在。',
]

#增强的编码函数
out = tokenizer.encode_plus(
    text=sents[0],
    text_pair=sents[1],

    #当句子长度大于max_length时,截断
    truncation=True,

    #一律补零到max_length长度
    padding='max_length',
    max_length=30,
    add_special_tokens=True,

    #可取值tensorflow,pytorch,numpy,默认值None为返回list
    return_tensors=None,

    #返回token_type_ids
    return_token_type_ids=True,

    #返回attention_mask
    return_attention_mask=True,

    #返回special_tokens_mask 特殊符号标识
    return_special_tokens_mask=True,

    #返回offset_mapping 标识每个词的起止位置,这个参数只能BertTokenizerFast使用
    #return_offsets_mapping=True,

    #返回length 标识长度
    return_length=True,
)

print(out)   # 字典
print(tokenizer.decode(out['input_ids']))

输出
{‘input_ids’: [101, 6848, 2885, 4403, 3736, 5709, 1736, 4638, 1333, 1728, 2218, 3221, 3175, 912, 511, 102, 5011, 6381, 3315, 4638, 7241, 4669, 4802, 2141, 4272, 511, 102, 0, 0, 0], ‘token_type_ids’: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0], ‘special_tokens_mask’: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], ‘attention_mask’: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0], ‘length’: 30}
[CLS] 选 择 珠 江 花 园 的 原 因 就 是 方 便 。 [SEP] 笔 记 本 的 键 盘 确 实 爽 。 [SEP] [PAD] [PAD] [PAD]

指标详细解释

  • input_ids 就是编码后的词,即将句子里的一个一个词变为一个一个数字
  • token_type_ids 第一个句子和特殊符号的位置是0,第二个句子的位置是1(含第二个句子末尾的 [SEP])
  • special_tokens_mask 特殊符号的位置是1,其他位置是0
  • attention_mask pad的位置是0,其他位置是1
  • length 返回句子长度

2-3、批量编码单个句子:

sents = [
    '选择珠江花园的原因就是方便。',
    '笔记本的键盘确实爽。',
    '房间太小。其他的都一般。',
    '今天才知道这书还有第6卷,真有点郁闷.',
    '机器背面似乎被撕了张什么标签,残胶还在。',
]

# 批量编码一个一个的句子
out = tokenizer.batch_encode_plus(
    batch_text_or_text_pairs=[sents[0], sents[1]],  # 批量编码,一次编码了两个句子(与增强的编码函数相比,就此处不同)

    # 当句子长度大于max_length时,截断
    truncation=True,

    # 一律补零到max_length长度
    padding='max_length',
    max_length=15,
    add_special_tokens=True,

    # 可取值tf,pt,np,默认为返回list
    return_tensors=None,

    # 返回token_type_ids
    return_token_type_ids=True,

    # 返回attention_mask
    return_attention_mask=True,

    # 返回special_tokens_mask 特殊符号标识
    return_special_tokens_mask=True,

    # 返回offset_mapping 标识每个词的起止位置,这个参数只能BertTokenizerFast使用
    # return_offsets_mapping=True,

    # 返回length 标识长度
    return_length=True,
)

print(out)  # 字典
print(tokenizer.decode(out['input_ids'][0]))

输出
{‘input_ids’: [[101, 6848, 2885, 4403, 3736, 5709, 1736, 4638, 1333, 1728, 2218, 3221, 3175, 912, 102], [101, 5011, 6381, 3315, 4638, 7241, 4669, 4802, 2141, 4272, 511, 102, 0, 0, 0]], ‘token_type_ids’: [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], ‘special_tokens_mask’: [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]], ‘length’: [15, 12], ‘attention_mask’: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0]]}
[CLS] 选 择 珠 江 花 园 的 原 因 就 是 方 便 [SEP]

2-4、添加新词:

#获取字典
zidian = tokenizer.get_vocab()
#添加新词
tokenizer.add_tokens(new_tokens=['月光', '希望'])

#添加新符号
tokenizer.add_special_tokens({'eos_token': '[EOS]'})   # End Of Sentence

# 获取更新后的字典
zidian = tokenizer.get_vocab()

# 解码新词
#编码新添加的词
out = tokenizer.encode(
    text='月光的新希望[EOS]',
    text_pair=None,

    #当句子长度大于max_length时,截断
    truncation=True,

    #一律补pad到max_length长度
    padding='max_length',
    add_special_tokens=True,
    max_length=8,
    
    return_tensors=None,
)

print(out)

print(tokenizer.decode(out))

输出
在这里插入图片描述

2-5、AutoTokenizer与BertTokenizer的区别

AutoTokenizer是通用封装,根据载入预训练模型来自适应。

主要区别是

  • 自动选择模型类型: AutoTokenizer是一个自动选择适合任务的分词器的工具。它可以根据输入的预训练模型名称或模型类型自动选择对应的分词器。这使得在使用不同的模型时更加方便,而不需要手动指定分词器。例如,你可以使用AutoTokenizer.from_pretrained(“bert-base-uncased”),它将自动选择适合BERT模型的BertTokenizer。

  • 具体模型的分词器: BertTokenizer是用于BERT模型的分词器,它是基于WordPiece分词算法的。它将输入的文本分割成小的单词单元(token),并为每个token分配一个唯一的ID。BertTokenizer还提供了其他有用的方法,如获取特殊token的ID(如[CLS]和[SEP]),将文本转换为模型所需的输入格式等。

  • 支持更多模型类型: AutoTokenizer可以自动选择适合多种预训练模型的分词器,不仅限于BERT。它支持包括GPT、RoBERTa、XLNet等在内的各种模型。这使得你能够使用同一种工具在不同的模型之间进行切换和比较。

总的来说,AutoTokenizer是一个用于自动选择适合任务的分词器的工具,而BertTokenizer是专门用于BERT模型的分词器。AutoTokenizer提供了更大的灵活性和通用性,可以适用于多种不同的预训练模型。

三、Datasets数据集库: 数据集使用

3-1、数据集使用

Datasets数据集库: 数据集使用

  • 数据下载到本地
  • 直接从本地读取
  • 数据集对应Hugging Face网站: https://huggingface.co/datasets.
# 1
from datasets import load_dataset

#加载数据
dataset = load_dataset(path='lansinuote/ChnSentiCorp')
#保存数据集到磁盘
dataset.save_to_disk(dataset_dict_path='./data/ChnSentiCorp')

# 2
#从磁盘加载数据
from datasets import load_from_disk

dataset = load_from_disk('./data/ChnSentiCorp')

问题:容易报错无法找到数据*ConnectionError: Couldn’t reach ‘seamew/ChnSentiCorp’ on the Hub (ConnectionError)*l

解决方法:打开网站https://huggingface.co/datasets/seamew/ChnSentiCorp获取数据。
在这里插入图片描述

3-2、数据集操作

3-3、评价函数

查看所有的评价指标

from datasets import list_metrics

#列出评价指标
metrics_list = list_metrics()

print(metrics_list)

输出
[‘accuracy’, ‘bertscore’, ‘bleu’, ‘bleurt’, ‘brier_score’, ‘cer’, ‘character’, ‘charcut_mt’, ‘chrf’, ‘code_eval’, ‘comet’, ‘competition_math’, ‘coval’, ‘cuad’, ‘exact_match’, ‘f1’, ‘frugalscore’, ‘glue’, ‘google_bleu’, ‘indic_glue’, ‘mae’, ‘mahalanobis’, ‘mape’, ‘mase’, ‘matthews_correlation’, ‘mauve’, ‘mean_iou’, ‘meteor’, ‘mse’, ‘nist_mt’, ‘pearsonr’, ‘perplexity’, ‘poseval’, ‘precision’, ‘r_squared’, ‘recall’, ‘rl_reliability’, ‘roc_auc’, ‘rouge’, ‘sacrebleu’, ‘sari’, ‘seqeval’, ‘smape’, ‘spearmanr’, ‘squad’, ‘squad_v2’, ‘super_glue’, ‘ter’, ‘trec_eval’, ‘wer’, ‘wiki_split’, ‘xnli’, ‘xtreme_s’, ‘AlhitawiMohammed22/CER_Hu-Evaluation-Metrics’, ‘BucketHeadP65/confusion_matrix’, ‘BucketHeadP65/roc_curve’, ‘Drunper/metrica_tesi’, ‘Felipehonorato/eer’, ‘He-Xingwei/sari_metric’, ‘JP-SystemsX/nDCG’, ‘Josh98/nl2bash_m’, ‘Kyle1668/squad’, ‘Muennighoff/code_eval’, ‘NCSOFT/harim_plus’, ‘Natooz/ece’, ‘NikitaMartynov/spell-check-metric’, ‘Pipatpong/perplexity’, ‘Splend1dchan/cosine_similarity’, ‘Viona/fuzzy_reordering’, ‘Viona/kendall_tau’, ‘Vipitis/shadermatch’, ‘Yeshwant123/mcc’, ‘abdusah/aradiawer’, ‘abidlabs/mean_iou’, ‘abidlabs/mean_iou2’, ‘andstor/code_perplexity’, ‘angelina-wang/directional_bias_amplification’, ‘aryopg/roc_auc_skip_uniform_labels’, ‘brian920128/doc_retrieve_metrics’, ‘bstrai/classification_report’, ‘chanelcolgate/average_precision’, ‘ckb/unigram’, ‘codeparrot/apps_metric’, ‘cpllab/syntaxgym’, ‘dvitel/codebleu’, ‘ecody726/bertscore’, ‘fschlatt/ner_eval’, ‘giulio98/codebleu’, ‘guydav/restrictedpython_code_eval’, ‘harshhpareek/bertscore’, ‘hpi-dhc/FairEval’, ‘hynky/sklearn_proxy’, ‘hyperml/balanced_accuracy’, ‘ingyu/klue_mrc’, ‘jpxkqx/peak_signal_to_noise_ratio’, ‘jpxkqx/signal_to_reconstruction_error’, ‘k4black/codebleu’, ‘kaggle/ai4code’, ‘langdonholmes/cohen_weighted_kappa’, ‘lhy/hamming_loss’, ‘lhy/ranking_loss’, ‘lvwerra/accuracy_score’, ‘manueldeprada/beer’, ‘mfumanelli/geometric_mean’, ‘omidf/squad_precision_recall’, ‘posicube/mean_reciprocal_rank’, ‘sakusakumura/bertscore’, ‘sma2023/wil’, ‘spidyidcccc/bertscore’, ‘tialaeMceryu/unigram’, ‘transZ/sbert_cosine’, ‘transZ/test_parascore’, ‘transformersegmentation/segmentation_scores’, ‘unitxt/metric’, ‘unnati/kendall_tau_distance’, ‘weiqis/pajm’, ‘ybelkada/cocoevaluate’, ‘yonting/average_precision_score’, ‘yuyijiong/quad_match_score’]

使用某个评价指标

from datasets import load_metric

#加载一个评价指标
metric = load_metric('glue', 'mrpc') 
#计算一个评价指标
predictions = [0, 1, 0]
references = [0, 1, 1]

final_score = metric.compute(predictions=predictions, references=references)
print(final_score)

四、模型

模型对应Hugging Face网站: https://huggingface.co/models.

4-1、各类NLP任务的常用模型

以下列举一些任务的常用模型:

文本分类:finbert、roberta-base-go_emotions、twitter-roberta-base-sentiment-latest
问答:roberta-base-squad2、xlm-roberta-large-squad2、distilbert-base-cased-distilled-squad
零样本分类:bart-large-mnli、mDeBERTa-v3-base-mnli-xnli
翻译:t5-base、 opus-mt-zh-en、translation_en-zh
总结:bart-large-cnn、led-base-book-summary
文本生成:Baichuan-13B-Chat、falcon-40b、starcoder
文本相似度:all-MiniLML6-v2、text2vec-large-chinese、all-mpnet-base-v2

五、实战案例分析

5-1、Kaggle竞赛 Real or Not? NLP with Disaster Tweets 文本分类

5-1-1、数据介绍

数据来源于:kaggle竞赛- Natural Language Processing with Disaster Tweets

任务:我们需要根据文章的location、keyword以及文本text来判断这篇推文是否和灾难有关,相关部门可以据此来第一时间发现可能存在的灾难并且迅速做出反应,将损失降低到最低。
在这里插入图片描述

数据规模:Training Set Shape: (7613, 5); Test Set Shape: (3263, 4)

训练集
在这里插入图片描述
验证集
在这里插入图片描述

其他事项:根据数据分析得知

  • location这一列缺失值较多,直接摒弃
  • keyword这一列缺失值很少,根据数据分析得知,keyword与标签之间有可见的强相关性。
  • 标签分布均匀,我们可以直接拿来训练模型
  • 这里我们省略数据分析阶段,进入模型训练阶段,如果对完整过程感兴趣请查看我的另一篇文章Kaggle竞赛 Real or Not? NLP with Disaster Tweets 文本分类.

5-2、训练模型

处理final_text,返回编码后的ID串。

def encode_fn(text_list):
    all_input_ids = []
    for text in text_values:
        input_ids = tokenizer.encode(text, add_special_tokens=True, max_length=180, pad_to_max_length=True, return_tensors='pt')
        all_input_ids.append(input_ids)
    all_input_ids = torch.cat(all_input_ids, dim=0)
    return all_input_ids

划分数据为训练集和验证集

epochs = 4
batch_size = 32

# Split data into train and validation
# 将数据转化为输入模型需要的数据类型
all_input_ids = encode_fn(text_values)
labels = torch.tensor(labels)

# TensorDataset是pytorch中的一个类,用于将多个张量打包成一个数据集,将输入数据张量和标签张量进行一一对应组合。
# 划分训练集和验证集
dataset = TensorDataset(all_input_ids, labels)
train_size = int(0.90 * len(dataset))
val_size = len(dataset) - train_size
train_dataset, val_dataset = random_split(dataset, [train_size, val_size])

# Create train and validation dataloaders
train_dataloader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
val_dataloader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False)

加载bert模型

# Load the pretrained BERT model
model = BertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels=2, output_attentions=False, output_hidden_states=False)
model.cuda()

# create optimizer and learning rate schedule
optimizer = AdamW(model.parameters(), lr=2e-5)
# len(train_dataloader),数据被分为N个批次,每个批次的数据长度是32
# total_steps 
total_steps = len(train_dataloader) * epochs
# get_linear_schedule_with_warmup: 创建学习率调度器函数,
# get_linear_schedule_with_warmup函数在训练初期使用一种称为"warm-up"的策略,即在初始几个epoch中逐步增加学习率,以帮助模型更快地收敛到一个相对合适的参数范围。然后,在warm-up之后,学习率线性地减少或保持恒定。
scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps=0, num_training_steps=total_steps)

准确率计算
在这里插入图片描述

from sklearn.metrics import f1_score, accuracy_score

def flat_accuracy(preds, labels):
    
    """A function for calculating accuracy scores"""
    
    pred_flat = np.argmax(preds, axis=1).flatten()
    # 将真实标签数组labels进行展平,得到一维的真实标签数组。
    labels_flat = labels.flatten()
    # 计算展平后的真实标签数组与预测结果数组之间的准确率
    return accuracy_score(labels_flat, pred_flat)

训练和验证

for epoch in range(epochs):
    model.train()
    total_loss, total_val_loss = 0, 0
    total_eval_accuracy = 0
    for step, batch in enumerate(train_dataloader):
        model.zero_grad()
        loss, logits = model(batch[0].to(device), token_type_ids=None, attention_mask=(batch[0]>0).to(device), labels=batch[1].to(device))
        total_loss += loss.item()
        loss.backward()
        torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
        optimizer.step() 
        scheduler.step()
        
    model.eval()
    for i, batch in enumerate(val_dataloader):
        with torch.no_grad():
            loss, logits = model(batch[0].to(device), token_type_ids=None, attention_mask=(batch[0]>0).to(device), labels=batch[1].to(device))
                
            total_val_loss += loss.item()
            
            logits = logits.detach().cpu().numpy()
            label_ids = batch[1].to('cpu').numpy()
            total_eval_accuracy += flat_accuracy(logits, label_ids)
    
    avg_train_loss = total_loss / len(train_dataloader)
    avg_val_loss = total_val_loss / len(val_dataloader)
    avg_val_accuracy = total_eval_accuracy / len(val_dataloader)
    
    print(f'Train loss     : {avg_train_loss}')
    print(f'Validation loss: {avg_val_loss}')
    print(f'Accuracy: {avg_val_accuracy:.2f}')
    print('\n')

Train loss : 0.441781023875452
Validation loss: 0.34831519580135745
Accuracy: 0.86
Train loss : 0.3275374324204257
Validation loss: 0.3286557973672946
Accuracy: 0.88
Train loss : 0.2503694619696874
Validation loss: 0.355623895690466
Accuracy: 0.86
Train loss : 0.19663514375973207
Validation loss: 0.3806843503067891
Accuracy: 0.86

预测

# Create the test data loader
text_values = df_test['final_text'].values
all_input_ids = encode_fn(text_values)
pred_data = TensorDataset(all_input_ids)
pred_dataloader = DataLoader(pred_data, batch_size=batch_size, shuffle=False)
model.eval()
preds = []
for i, (batch,) in enumerate(pred_dataloader):
    with torch.no_grad():
        outputs = model(batch.to(device), token_type_ids=None, attention_mask=(batch>0).to(device))
        logits = outputs[0]
        logits = logits.detach().cpu().numpy()
        preds.append(logits)

final_preds = np.concatenate(preds, axis=0)
final_preds = np.argmax(final_preds, axis=1)

# Create submission file
submission = pd.DataFrame()
submission['id'] = df_test['id']
submission['target'] = final_preds
submission.to_csv('submission.csv', index=False)

参考文章:
HuggingFaceg官方GitHub.
HuggingFace快速上手(以bert-base-chinese为例).
NLP各类任务.
EDA探索式数据分析.
pytorch+huggingface实现基于bert模型的文本分类(附代码).

HuggingFace简明教程.
huggingface transformers预训练模型如何下载至本地,并使用?.
hugging face 模型库的使用及加载 Bert 预训练模型.

总结

只想要快乐。

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

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

相关文章

Apache Kudu 在**医疗科技的生产实践

目录 说明 医疗场景下数据特点 KUDU 的介绍 kudu 架构 kudu 文件组织形式 kudu的生产实践 技术选型 整体的架构 项目遇到的问题 参考资料 说明 本文主要介绍APACHE KUDU 在**医疗科技数据实时分析场景下的实践,内容包括: 医疗场景下数据特点 …

LCD—STM32液晶显示(4.液晶控制代码讲解)

目录 STM32液晶控制代码讲解 液晶接口封装介绍 使用LCD的配置步骤 内存操作要使用volatile进行修饰 图形绘制实现 绘制矩形 重点补充 STM32液晶控制代码讲解 液晶接口封装介绍 指南者液晶接口原理图 左边DB00—DB15表示液晶屏的数据线引脚,分别对应STM32的F…

【无线通信模块】什么是PCB板载天线,PCB板载天线UART/USB接口WiFi模块

基于射频技术的无线模块需要通过天线来发射和接收电磁波信号,市场上常见的天线类型有陶瓷天线、板载天线、棒状天线以及外接天线,外接天线是通过在PCB板上预留IPEX座子,可选天线类型就比较多。本篇SKYLAB小编带大家了解一下板载天线的UART接口…

Ubuntu 考虑采用新的 “统一默认安装 (unified default install)”

导读Ubuntu安装程序中的 “最小化安装” (Minimal installation) 是该发行版多年来最受欢迎的功能之一。 当用户选择 Ubuntu 的 “最小化安装” 选项时,可以在安装更少的预装应用程序情况下,获得完整、功能齐全的 Ubuntu 系统。 但这个功能可能要被砍掉…

MVVM 实现记录文本

1. MVVM 框架说明: Model - 数据层 View - 视图层 ViewModel - 管理模型的视图 2. 资源文件 2.1 启动图标: AppIconhttps://img-blog.csdnimg.cn/8fa1031489f544ef9757b6b3ab0eddbe.png 2.2 Display Name: Do Stuff 2.2 颜色图: 2.3 项目结构图: 3. Model 层实现&a…

设计模式——享元模式

享元模式 定义 享元模式(Flyweight Pattern)是池技术的重要实现方式。 使用共享对象可以有效地支持大量的细粒度对象。 优缺点、应用场景 优点 可以大大减少应用程序创建对象的数量,降低程序内存占用。 缺点 提高了系统的复杂度&…

F#奇妙游(14):F#实现WPF的绑定

WPF中的绑定 绑定在UI开发中是一个非常重要的概念,它可以让我们的UI界面和数据模型之间建立起联系,当数据模型发生变化时,UI界面也会随之变化,反之亦然。这样的好处是显而易见的,我们不需要手动去更新UI界面&#xff…

React native 已有项目升级兼容web

基础 概念 | webpack 中文文档 | webpack 中文文档 | webpack 中文网 深入理解Webpack及Babel的使用 - 掘金 Introduction to React Native for Web // React Native for Web Webpack 是一个现代的 JavaScript 应用程序的静态模块打包工具,它将应用程序所依赖的各…

回归预测 | MATLAB实现GRU(门控循环单元)多输入单输出(不调用工具箱函数)

回归预测 | MATLAB实现GRU(门控循环单元)多输入单输出(不调用工具箱函数) 文章目录 回归预测 | MATLAB实现GRU(门控循环单元)多输入单输出(不调用工具箱函数)预测效果基本介绍程序设计参考资料 预测效果 基本介绍 GRU神经网络是LSTM神经网络的一种变体,LSTM 神经网 …

opencv 基础学习08-图像通道操作

opencv 基础学习08-图像通道操作 什么是图像通道?通道操作:**1 通过索引拆分**2 通过opencv 函数拆分通道合并 什么是图像通道? OpenCV的通道拆分功能可用于将多通道图像拆分成单独的通道,这在图像处理和计算机视觉任务中具有许多…

电子锁语音芯片方案,低功耗声音提示ic,WT588F02B-8S

随着科技的不断发展,电子锁已成为现代社会中,安全性和便利性并存的必备设备。如何为电子锁行业增添智能化、人性化的功能已成为行业内的热门话题。 在这个迅速发展的市场中,深圳唯创知音推出了一款语音交互方案——WT588F02B-8S 低功耗声音提…

【云原生】Docker的初步认识,安装与基本操作

一、Docker的相关知识 Docker是一个开源的应用容器引擎,基于go语言开发并遵循了apache2.0协议开源。 Docker是在Linux容器里运行应用的开源工具,是一种轻量级的“虚拟机”。 Docker 的容器技术可以在一台主机上轻松为任何应用创建一个轻量级的、可移植的…

时序预测 | MATLAB实现Hamilton滤波AR时间序列预测

时序预测 | MATLAB实现Hamilton滤波AR时间序列预测 目录 时序预测 | MATLAB实现Hamilton滤波AR时间序列预测预测效果基本介绍程序设计参考资料预测效果 基本介绍 预测在很大程度上取决于适合周期的模型和所采用的预测方法,就像它们依赖于过滤器提取的周期一样。标准 Hodrick-P…

Bard:Google AI开始支持中文对话和看图说话了

说起时下火爆的生成式AI,并不是只有ChatGPT。Bard也是一个很优秀的产品,并且刚刚发布的很多有趣的新功能。文末告诉你如何访问Bard。 Google AI在最近的更新中发布了Bard,一个新的语言模型。Bard支持多种语言,包括中文&#xff0…

华为模拟器eNSP过程中所遇问题(40错误)与解决办法

1. 版本 2.打开ensp开启AR2204,报错40 3.弹出文档,挨着试一遍先 安装eNSP的PC上是否存在名为“VirtualBox Host-Only Network”的虚拟网卡 需要启用。虚拟网卡的设置是否符合以下要求:IP地址为192.168.56.1,子网掩码为255.255.2…

LCD-STM32液晶显示中英文-(6.unicode字符集)

目录 Unicode字符集和编码 UTF-32 UTF-16 UTF-8(重点:必须掌握) BOM ANSI Unicode字符集和编码 由于各个国家或地区都根据使用自己的文字系统制定标准,同一个编码在不同的标准里表示不一样的字符,各个标准互不兼容…

诚迈科技子公司智达诚远精耕智能驾驶,为商用落地注入创新力量

近期,工业和信息化部副部长辛国斌在新闻发布会上表示,将启动智能网联汽车准入和上路通行试点,组织开展城市级“车路云一体化”示范应用,将支持L3级及更高级别的自动驾驶功能商业化应用。根据工信部最新消息,《智能网联…

<C语言> 自定义类型

1.结构体 结构体是一种用户自定义的数据类型,允许将不同类型的数据项组合在一起,形成一个更大的数据结构。结构体可以包含多个成员变量,每个成员变量可以是不同的数据类型,如整数、字符、浮点数等,甚至可以包含其他结构…

数据可视化——根据提供的数据,将数据经过处理后以折线图的形式展现

文章目录 前言处理数据获取数据筛选数据将JSON数据转换为Python数据筛选出横坐标数据和纵坐标数据 根据处理后的数据绘制折线图整体代码展示 前言 前面我们学习了如何使用 pyecharts 模块绘制简单的折线图,那么今天我将为大家分享,如何根据提供的数据将…

Python+Qt窗体或Django网页支付宝收款码-扫码付款实例

程序示例精选 PythonQt窗体或Django网页支付宝收款码-扫码付款实例 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<PythonQt窗体或Django网页支付宝收款码-扫码付款实例>>编写代…