Python 全栈体系【四阶】(五十七)

news2024/11/16 3:32:35

第五章 深度学习

十三、自然语言处理(NLP)

2. 传统NLP处理技术

2.4 关键词提取

关键词提取是提取出代表文章重要内容的一组词,对文本聚类、分类、自动摘要起到重要作用。此外,关键词提取还能使人们便捷地浏览和获取信息。现实中大量文本不包含关键词,自动提取关检测技术具有重要意义和价值。关键词提取包括有监督学习、无监督学习方法两类。

有监督关键词提取。该方法主要通过分类方式进行,通过构建一个较为丰富完整的词表,然后通过判断每个文档与词表中每个词的匹配程度,以类似打标签的方式,达到关键词提取的效果。该方法能获取较高的精度,但需要对大量样本进行标注,人工成本过高。另外,现在每天都有大量新的信息出现,固定词表很难将新信息内容表达出来,但人工实时维护词表成本过高。所以,有监督学习关键词提取方法有较明显的缺陷。

无监督关键词提取。相对于有监督关键词提取,无监督方法对数据要求低得多,既不需要人工维护词表,也不需要人工标注语料辅助训练。因此,在实际应用中更受青睐。这里主要介绍无监督关键词提取算法,包括TF-IDF算法,TextRank算法和主题模型算法。

2.4.1 TF-IDF算法

TF-IDF(Term Frequency-Inverse Document Frequency,词频-逆文档频率)是一种基于传统的统计计算方法,常用于评估一个文档集中一个词对某份文档的重要程度。其基本思想是:一个词语在文档中出现的次数越多、出现的文档越少,语义贡献度越大(对文档区分能力越强)。TF-IDF表达式由两部分构成,词频、逆文档频率。词频定义为:

T F i j = n j i ∑ k n k j TF_{ij} = \frac{n_{ji}}{\sum_k n_{kj}} TFij=knkjnji

其中, n i j n_{ij} nij表示词语i在文档j中出现的次数,分母 ∑ k n k j \sum_k n_{kj} knkj表示所有文档总次数。逆文档频率定义为:

I D F i = l o g ( ∣ D ∣ ∣ D i ∣ + 1 ) IDF_i = log(\frac{|D|}{|D_i| + 1}) IDFi=log(Di+1D)

其中, ∣ D ∣ |D| D为文档总数, D i D_i Di为文档中出现词i的文档数量,分母加1是避免分母为0的情况(称为拉普拉斯平滑),TF-IDF算法是将TF和IDF综合使用,表达式为:

T F − I D F = T F i j × I D F i = n j i ∑ k n k j × l o g ( ∣ D ∣ ∣ D i ∣ + 1 ) TF-IDF = TF_{ij} \times IDF_i =\frac{n_{ji}}{\sum_k n_{kj}} \times log(\frac{|D|}{|D_i| + 1}) TFIDF=TFij×IDFi=knkjnji×log(Di+1D)

由公式可知,词频越大,该值越大;出现的文档数越多(说明该词越通用),逆文档频率越接近0,语义贡献度越低。例如有以下文本:

世界献血日,学校团体、献血服务志愿者等可到血液中心参观检验加工过程,我们会对检验结果进行公示,同时血液的价格也将进行公示。

以上文本词语总数为30,计算几个词的词频:

T F 献血 = 2 / 30 ≈ 0.067 T F 血液 = 2 / 30 ≈ 0.067 T F 进行 = 2 / 30 ≈ 0.067 T F 公示 = 2 / 30 ≈ 0.067 TF_{献血} = 2 / 30 \approx 0.067 \\ TF_{血液} = 2 / 30 \approx 0.067 \\ TF_{进行} = 2 / 30 \approx 0.067 \\ TF_{公示} = 2 / 30 \approx 0.067 TF献血=2/300.067TF血液=2/300.067TF进行=2/300.067TF公示=2/300.067

假设出现献血、血液、进行、公示文档数量分别为10、15、100、50,根据TF-IDF计算公式,得:

T F − I D F 献血 = 0.067 ∗ l o g ( 1000 / 10 ) = 0.067 ∗ 2 = 0.134 T F − I D F 血液 = 0.067 ∗ l o g ( 1000 / 15 ) = 0.067 ∗ 1.824 = 0.1222 T F − I D F 进行 = 0.067 ∗ l o g ( 1000 / 100 ) = 0.067 ∗ 1 = 0.067 T F − I D F 公示 = 0.067 ∗ l o g ( 1000 / 50 ) = 0.067 ∗ 1.30 = 0.08717 TF-IDF_{献血} = 0.067 * log(1000/10) = 0.067 * 2 = 0.134\\ TF-IDF_{血液} = 0.067 * log(1000/15) = 0.067 * 1.824 = 0.1222 \\ TF-IDF_{进行} = 0.067 * log(1000/100) = 0.067 * 1 = 0.067 \\ TF-IDF_{公示} = 0.067 * log(1000/50) = 0.067 * 1.30 = 0.08717 TFIDF献血=0.067log(1000/10)=0.0672=0.134TFIDF血液=0.067log(1000/15)=0.0671.824=0.1222TFIDF进行=0.067log(1000/100)=0.0671=0.067TFIDF公示=0.067log(1000/50)=0.0671.30=0.08717

“献血”、“血液”的TF-IDF值最高,所以为最适合这篇文档的关键词。

2.4.2 TextRank算法

与TF-IDF不一样,TextRank算法可以脱离于语料库,仅对单篇文档进行分析就可以提取该文档的关键词,这也是TextRank算法的一个重要特点。TextRank算法最早用于文档的自动摘要,基于句子维度的分析,利用算法对每个句子进行打分,挑选出分数最高的n个句子作为文档的关键句,以达到自动摘要的效果。

TextRank算法的基本思想来源于Google的PageRank算法,该算法是Google创始人拉里·佩奇和希尔盖·布林于1997年构建早期的搜索系统原型时提出的链接分析法,用于评价搜索系统各覆盖网页重要性的一种方法。随着Google的成功,该算法也称为其它搜索引擎和学术界十分关注的计算模型。

在这里插入图片描述

PageRank基本思想有两条:

  • 链接数量。一个网页被越多的其它网页链接,说明这个网页越重要
  • 链接质量。一个网页被一个越高权值的网页链接,也能表明这个网页越重要

基于上述思想,一个网页的PageRank计算公式可以表示为:

S ( V i ) = ∑ j ∈ I n ( V i ) ( 1 O u t ( V j ) × S ( V j ) ) S(V_i) = \sum_{j \in In(V_i)} \Bigg( \frac{1}{Out(V_j)} \times S(V_j) \Bigg) S(Vi)=jIn(Vi)(Out(Vj)1×S(Vj))

其中, I n ( V i ) In(V_i) In(Vi) V i V_i Vi的入链集合, O u t ( V j ) Out(V_j) Out(Vj) V j V_j Vj的出链集合, ∣ O u t ( V j ) ∣ |Out(V_j)| Out(Vj)为出链的数量。因为每个网页要将它自身的分数平均贡献给每个出链,则 ( 1 O u t ( V j ) × S ( V j ) ) \Bigg( \frac{1}{Out(V_j)} \times S(V_j) \Bigg) (Out(Vj)1×S(Vj))即为 V i V_i Vi贡献给 V j V_j Vj的分数。将所有入链贡献给它的分数全部加起来,就是 V i V_i Vi自身的得分。算法开始时,将所有页面的得分均初始化为1。

对于一些孤立页面,可能链入、链出的页面数量为0,为了避免这种情况,对公式进行了改造,加入了一个阻尼系数 d d d,这样,即使孤立页面也有一个得分。改造后的公式如下:

S ( V i ) = ( 1 − d ) + d × ∑ j ∈ I n ( V i ) ( 1 O u t ( V j ) × S ( V j ) ) S(V_i) = (1 - d) + d \times \sum_{j \in In(V_i)} \Bigg( \frac{1}{Out(V_j)} \times S(V_j) \Bigg) S(Vi)=(1d)+d×jIn(Vi)(Out(Vj)1×S(Vj))

以上就是PageRank的理论,也是TextRank的理论基础,不同于的是TextRank不需要与文档中的所有词进行链接,而是采用一个窗口大小,在窗口中的词互相都有链接关系。例如对下面的文本进行窗口划分:

世界献血日,学校团体、献血服务志愿者等可到血液中心参观检验加工过程,我们会对检验结果进行公示,同时血液的价格也将进行公示。

如果将窗口大小设置为5,则可得到如下计算窗口:

[世界,献血,日,学校,团体]
[献血,日,学校,团体,献血]
[日,学校,团体,献血,服务]
[学校,团体,献血,服务,志愿者]
……

每个窗口内所有词之间都有链接关系,如[世界]和[献血,日,学校,团体]之间有链接关系。得到了链接关系,就可以套用TextRank公式,计算每个词的得分,最后选择得分最高的N个词作为文档的关键词。

2.4.3 关键词提取示例

本案例演示了通过自定义TF-IDF、调用TextRank API实现关键字提取

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

import math
import jieba
import jieba.posseg as psg
from gensim import corpora, models
from jieba import analyse
import functools
import numpy as np


# 停用词表加载方法
def get_stopword_list():
    # 停用词表存储路径,每一行为一个词,按行读取进行加载
    # 进行编码转换确保匹配准确率
    stop_word_path = '../data/stopword.txt'
    with open(stop_word_path, "r", encoding="utf-8") as f:
        lines = f.readlines()

    stopword_list = [sw.replace('\n', '') for sw in lines]
    return stopword_list


# 去除停用词
def word_filter(seg_list):
    filter_list = []
    for word in seg_list:
        # 过滤停用词表中的词,以及长度为<2的词
        if not word in stopword_list and len(word) > 1:
            filter_list.append(word)

    return filter_list


# 数据加载,pos为是否词性标注的参数,corpus_path为数据集路径
def load_data(corpus_path):
    # 调用上面方式对数据集进行处理,处理后的每条数据仅保留非干扰词
    doc_list = []
    for line in open(corpus_path, 'r', encoding='utf-8'):  # 循环读取一行(一行即一个文档)
        content = line.strip()  # 去空格
        seg_list = jieba.cut(content)  # 分词
        filter_list = word_filter(seg_list)  # 去除停用词
        doc_list.append(filter_list)  # 将分词后的内容添加到列表

    return doc_list


# idf值统计方法
def train_idf(doc_list):
    idf_dic = {}
    tt_count = len(doc_list)  # 总文档数

    # 每个词出现的文档数
    for doc in doc_list:
        doc_set = set(doc)  # 将词推入集合去重
        for word in doc_set:  # 词语在文档中
            idf_dic[word] = idf_dic.get(word, 0.0) + 1.0  # 文档数加1

    # 按公式转换为idf值,分母加1进行平滑处理
    for word, doc_cnt in idf_dic.items():
        idf_dic[word] = math.log(tt_count / (1.0 + doc_cnt))

    # 对于没有在字典中的词,默认其仅在一个文档出现,得到默认idf值
    default_idf = math.log(tt_count / (1.0))

    return idf_dic, default_idf


# TF-IDF类
class TfIdf(object):
    def __init__(self, idf_dic, default_idf, word_list, keyword_num):
        """
        TfIdf类构造方法
        :param idf_dic: 训练好的idf字典
        :param default_idf: 默认idf值
        :param word_list: 待提取文本
        :param keyword_num: 关键词数量
        """
        self.word_list = word_list
        self.idf_dic, self.default_idf = idf_dic, default_idf # 逆文档频率
        self.tf_dic = self.get_tf_dic()  # 词频
        self.keyword_num = keyword_num

    # 统计tf值
    def get_tf_dic(self):
        tf_dic = {}  # 词频字典
        for word in self.word_list:
            tf_dic[word] = tf_dic.get(word, 0.0) + 1.0

        total = len(self.word_list)  # 词语总数
        for word, word_cnt in tf_dic.items():
            tf_dic[word] = float(word_cnt) / total

        return tf_dic

    # 按公式计算tf-idf
    def get_tfidf(self):
        tfidf_dic = {}
        for word in self.word_list:
            idf = self.idf_dic.get(word, self.default_idf)
            tf = self.tf_dic.get(word, 0)

            tfidf = tf * idf  # 计算TF-IDF
            tfidf_dic[word] = tfidf

        # 根据tf-idf排序,去排名前keyword_num的词作为关键词
        s_list = sorted(tfidf_dic.items(), key=lambda x: x[1], reverse=True)
        # print(s_list)
        top_list = s_list[:self.keyword_num]  # 切出前N个
        for k, v in top_list:
            print(k + ", ", end='')
        print()


def tfidf_extract(word_list, keyword_num=20):
    doc_list = load_data('../data/corpus.txt')  # 读取文件内容
    # print(doc_list)
    idf_dic, default_idf = train_idf(doc_list) # 计算逆文档频率

    tfidf_model = TfIdf(idf_dic, default_idf, word_list, keyword_num)
    tfidf_model.get_tfidf()


def textrank_extract(text, keyword_num=20):
    keywords = analyse.textrank(text, keyword_num)
    # 输出抽取出的关键词
    for keyword in keywords:
        print(keyword + ", ", end='')
    print()


if __name__ == '__main__':
    global stopword_list

    text = """在中国共产党百年华诞的重要时刻,在“两个一百年”奋斗目标历史交汇关键节点,
    党的十九届六中全会的召开具有重大历史意义。全会审议通过的《决议》全面系统总结了党的百年奋斗
    重大成就和历史经验,特别是着重阐释了党的十八大以来党和国家事业取得的历史性成就、发生的历史性变革,
    充分彰显了中国共产党的历史自觉与历史自信。"""

    stopword_list = get_stopword_list()

    seg_list = jieba.cut(text)  # 分词
    filter_list = word_filter(seg_list)

    # TF-IDF提取关键词
    print('TF-IDF模型结果:')
    tfidf_extract(filter_list)

    # TextRank提取关键词
    print('TextRank模型结果:')
    textrank_extract(text)

执行结果:

TF-IDF模型结果:
历史, 中国共产党, 百年, 历史性, 华诞, 一百年, 奋斗目标, 交汇, 节点, 十九, 六中全会, 全会, 奋斗, 重大成就, 着重, 阐释, 十八, 党和国家, 成就, 变革,

TextRank模型结果:
历史, 历史性, 意义, 成就, 决议, 审议, 发生, 系统, 总结, 全面, 节点, 关键, 交汇, 召开, 具有, 全会, 取得, 事业, 自信, 变革,
2.5 综合案例
垃圾邮件分类
  • 数据集介绍:包含5000份正常邮件、5001份垃圾邮件的样本
  • 文本特征处理方式:采用TF-IDF作为文本特征值
  • 模型选择:朴素贝叶斯、支持向量机模型
  • 基本流程:读取数据 → 去除停用词和特殊符号 → 计算TF-IDF特征值 → 模型训练 → 预测 → 打印结果
# -*- coding: utf-8 -*-
# 利用TF-IDF特征、朴素贝叶斯/支持向量机实现垃圾邮件分类
import numpy as np
import re
import string
import sklearn.model_selection as ms
from sklearn.naive_bayes import MultinomialNB
from sklearn.linear_model import SGDClassifier
from sklearn import metrics

import jieba
from sklearn.feature_extraction.text import TfidfVectorizer

label_name_map = ["垃圾邮件", "正常邮件"]


# 分词
def tokenize_text(text):
    tokens = jieba.cut(text)  # 分词
    tokens = [token.strip() for token in tokens]  # 去空格
    return tokens


def remove_special_characters(text):
    tokens = tokenize_text(text)
    # escape函数对字符进行转义处理
    # compile函数用于编译正则表达式,生成一个 Pattern 对象
    pattern = re.compile('[{}]'.format(re.escape(string.punctuation)))
    # filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表
    # sub函数进行正则匹配字符串替换
    filtered_tokens = filter(None, [pattern.sub('', token) for token in tokens])
    filtered_text = ' '.join(filtered_tokens)
    return filtered_text


# 去除停用词
def remove_stopwords(text):
    tokens = tokenize_text(text)  # 分词、去空格
    filtered_tokens = [token for token in tokens if token not in stopword_list]  # 去除停用词
    filtered_text = ''.join(filtered_tokens)
    return filtered_text


# 规范化处理
def normalize_corpus(corpus):
    result = []  # 处理结果

    for text in corpus:  # 遍历每个词汇
        text = remove_special_characters(text)  # 去除标点符号
        text = remove_stopwords(text)  # 去除停用词
        result.append(text)

    return result


def tfidf_extractor(corpus):
    vectorizer = TfidfVectorizer(min_df=1,
                                 norm='l2',
                                 smooth_idf=True,
                                 use_idf=True)
    features = vectorizer.fit_transform(corpus)
    return vectorizer, features


def get_data():
    '''
    获取数据
    :return: 文本数据,对应的labels
    '''
    corpus = []  # 邮件内容
    labels = []  # 标签(0-垃圾邮件 1-正常邮件)

    # 正常邮件
    with open("data/ham_data.txt", encoding="utf8") as f:
        for line in f.readlines():
            corpus.append(line)
            labels.append(1)

    # 垃圾邮件
    with open("data/spam_data.txt", encoding="utf8") as f:
        for line in f.readlines():
            corpus.append(line)
            labels.append(0)

    return corpus, labels


# 过滤空文档
def remove_empty_docs(corpus, labels):
    filtered_corpus = []
    filtered_labels = []

    for doc, label in zip(corpus, labels):
        if doc.strip():
            filtered_corpus.append(doc)
            filtered_labels.append(label)

    return filtered_corpus, filtered_labels


# 计算并打印分类指标
def print_metrics(true_labels, predicted_labels):
    # Accuracy
    accuracy = metrics.accuracy_score(true_labels, predicted_labels)

    # Precision
    precision = metrics.precision_score(true_labels,
                                        predicted_labels,
                                        average='weighted')

    # Recall
    recall = metrics.recall_score(true_labels,
                                  predicted_labels,
                                  average='weighted')

    # F1
    f1 = metrics.f1_score(true_labels,
                          predicted_labels,
                          average='weighted')

    print("正确率: %.2f, 查准率: %.2f, 召回率: %.2f, F1: %.2f" % (accuracy, precision, recall, f1))


if __name__ == "__main__":
    global stopword_list

    # 读取停用词
    with open("dict/stop_words.utf8", encoding="utf8") as f:
        stopword_list = f.readlines()

    corpus, labels = get_data()  # 加载数据
    corpus, labels = remove_empty_docs(corpus, labels)
    print("总的数据量:", len(labels))

    # 打印前N个样本
    for i in range(10):
        print("label:", labels[i], " 邮件内容:", corpus[i])

    # 对数据进行划分
    train_corpus, test_corpus, train_labels, test_labels = \
        ms.train_test_split(corpus,
                            labels,
                            test_size=0.10,
                            random_state=36)

    # 规范化处理
    norm_train_corpus = normalize_corpus(train_corpus)
    norm_test_corpus = normalize_corpus(test_corpus)

    # tfidf 特征
    ## 先计算tf-idf
    tfidf_vectorizer, tfidf_train_features = tfidf_extractor(norm_train_corpus)
    ## 再用刚刚训练的tf-idf模型计算测试集tf-idf
    tfidf_test_features = tfidf_vectorizer.transform(norm_test_corpus)
    # print(tfidf_test_features)
    # print(tfidf_test_features)

    # 基于tfidf的多项式朴素贝叶斯模型
    print("基于tfidf的贝叶斯模型")
    nb_model = MultinomialNB()  # 多分类朴素贝叶斯模型
    nb_model.fit(tfidf_train_features, train_labels)  # 训练
    mnb_pred = nb_model.predict(tfidf_test_features)  # 预测
    print_metrics(true_labels=test_labels, predicted_labels=mnb_pred)  # 打印测试集下的分类指标

    print("")

    # 基于tfidf的支持向量机模型
    print("基于tfidf的支持向量机模型")
    svm_model = SGDClassifier()
    svm_model.fit(tfidf_train_features, train_labels)  # 训练
    svm_pred = svm_model.predict(tfidf_test_features)  # 预测
    print_metrics(true_labels=test_labels, predicted_labels=svm_pred)  # 打印测试集下的分类指标

    print("")

    # 打印测试结果
    num = 0
    for text, label, pred_lbl in zip(test_corpus, test_labels, svm_pred):
        print('真实类别:', label_name_map[int(label)], ' 预测结果:', label_name_map[int(pred_lbl)])
        print('邮件内容【', text.replace("\n", ""), '】')
        print("")

        num += 1
        if num == 10:
            break

执行结果:

基于tfidf的贝叶斯模型
正确率: 0.97, 查准率: 0.97, 召回率: 0.97, F1: 0.97

基于tfidf的支持向量机模型
正确率: 0.98, 查准率: 0.98, 召回率: 0.98, F1: 0.98

真实类别: 正常邮件  预测结果: 正常邮件
邮件内容【 分专业吧,也分导师吧 标  题: Re: 问一个:有人觉得自己博士能混毕业吗 当然很好混毕业了 : 博士读到快中期了,始终感觉什么都不会,文章也没发几篇好的,论文的架构也没有, : 一切跟刚上的时候没有区别。但是事实上我也很辛苦的找资料,做实验,还进公司实习过, : 现在感觉好失败,内心已经放弃了,打算混毕业,不知道过来人有什么高招,请指点一二。 -- 】

真实类别: 垃圾邮件  预测结果: 垃圾邮件
邮件内容【 您好! 我公司有多余的发票可以向外代开!(国税、地税、运输、广告、海关缴款书)。 如果贵公司(厂)有需要请来电洽谈、咨询! 联系电话: 01351025****  陈先生 谢谢 顺祝商祺! 】

……

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++进阶】深入STL之vector:深入研究迭代器失效及拷贝问题

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;初步了解vector &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀STL之vector &#x1f4d2;1. 迭…

【Java基础】线程的五大状态

新建状态 使用 new 关键字和 Thread 类或其子类建立一个线程对象后&#xff0c;该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。 就绪状态 当线程对象调用了start()方法之后&#xff0c;该线程就进入就绪状态。就绪状态的线程处于就绪队列中&#xff…

【机器学习基础】Python编程04:五个实用练习题的解析与总结

Python是一种广泛使用的高级编程语言,它在机器学习领域中的重要性主要体现在以下几个方面: 简洁易学:Python语法简洁清晰,易于学习,使得初学者能够快速上手机器学习项目。 丰富的库支持:Python拥有大量的机器学习库,如scikit-learn、TensorFlow、Keras和PyTorch等,这些…

(学习笔记)数仓建模

数仓建模 OLAP数仓分层数据模型数据模型建设方法模型建设具体流程模型数据域事实表设计事实表拉链表 数据模型规范表命名(采用阿里one-data设计)字段命名(采用阿里one-data设计)数据模型标注规范 数据模型发展周期 OLAP OLTP&#xff1a;概念全称OnLine Transaction Processin…

【大模型】Ollama+open-webui/Anything LLM部署本地大模型构建RAG个人知识库教程(Mac)

目录 一、Ollama是什么&#xff1f; 二、如何在Mac上安装Ollama 1. 准备工作 2. 下载并安装Ollama 3. 运行Ollama 4. 安装和配置大型语言模型 5. 使用Ollama 三、安装open-webui 1. 准备工作 2. Open WebUI ⭐的主要特点 3. Docker安装OpenWebUI&#xff0c;拉去太慢…

操作系统教材第6版——个人笔记3

2.1 处理器 2.1.1 处理器与寄存器 处理器部件的简单示意 用户程序可见寄存器 可以使程序员减少访问主存储器的次数&#xff0c;提高指令执行的效率所有程序可使用&#xff0c;包括应用程序和系统程序数据寄存器&#xff1a;又称通用寄存器地址寄存器&#xff1a;索引、栈指针…

妙手ERP接入TEMU美国本土店,支持高效产品刊登、订单管理、库存管理

​​​​​​​ 众所周知&#xff0c;拼多多向来是低价卷王&#xff0c;而TEMU完美继承了拼多多的基因&#xff0c;靠着全托管模式一路狂奔&#xff0c;两年多便扩展至全球60个国家与地区&#xff0c;市场规模预计达到450亿美元&#xff0c;吸引着越来越多的卖家入驻。 在平台…

32C3-2模组与乐鑫ESP32­-C3­-WROOM­-02模组原理图、升级口说明

模组原理图&#xff1a; 底板原理图&#xff1a; u1 是AT通信口&#xff0c;wiif-tx wifi-rx 是升级口&#xff0c;chip-pu是reset复位口&#xff0c;GPIO9拉低复位进入下载模式 ESP32-WROOM-32 系列硬件连接管脚分配 功能 ESP32 开发板/模组管脚 其它设备管脚 下载固件…

Unity DOTS技术(八)状态组件

文章目录 一,简介二.实例 一,简介 因为在ECS中没有回调,因而无从得知组件是否被销毁.所以我们需要使用ISystemStateComponentData. 什么时ISystemStateComponentData状态组件? 当物体被销毁时ISystemStateComponentData组件不会被销毁.因而我们可以在组件被销毁时在该组件中…

搭建大型分布式服务(三十八)SpringBoot 整合多个kafka数据源-支持protobuf

系列文章目录 文章目录 系列文章目录前言一、本文要点二、开发环境三、原项目四、修改项目五、测试一下五、小结 前言 本插件稳定运行上百个kafka项目&#xff0c;每天处理上亿级的数据的精简小插件&#xff0c;快速上手。 <dependency><groupId>io.github.vipjo…

Clo3D导出服装动画,使用Unity3D展示

1.前言 Clo3D是一款应用于时装行业的3D服装设计软件,其强大的布料模拟算法可在3D空间中实现设计、制版、试衣和走秀,大幅提升数字作品逼真度和制作效率。为了让服装动画效果展示在Unity3D上模拟效果&#xff0c;需要Clo3D模拟出逼着的衣服动画。总体流程为Clo3D - Mixamo -Blen…

废酸再生工艺的稳定性强优势

废酸再生工艺&#xff0c;作为现代工业中一项重要的环保技术&#xff0c;其核心目的是将工业生产过程中产生的废酸进行回收、处理和再利用&#xff0c;以实现资源的节约和环境的保护。这一工艺不仅有助于减少废酸对环境的污染&#xff0c;还能为企业带来显著的经济效益。 一、废…

idea实用快捷键(持续更新...)

文章目录 1、快速输入try/catch/finally2、选中多个光标3、实现接口4、方法参数提示5、查看某个类的子类6、弹出显示查找内容的搜索框 1、快速输入try/catch/finally CtrlAltT 2、选中多个光标 ShiftAlt单机多选 End可以全部到行尾&#xff0c;Home则可以全部回到行首 3、实现接…

MySQL的增删改查2

文章目录 1. 数据库约束1.1 约束类型1.2 NOT NULL约束1.3 UNIQUE唯一约束1.4 DEFAULT默认值约束1.5 PRIMARY KEY主键约束1.6 FOREIGN KEY外键约束1.7 CHECK约束 2. 新增3. 查询3.1 聚合查询3.1.1 聚合函数3.1.2 GROUP BY子句3.1.3 HAVING 3.2 联合查询3.2.1 内连接3.2.2 外连接…

慧天卓特:2024年“一带一路”之哈萨克斯坦旱情监测案例分析(FYDI)

引言 联合国防治荒漠化公约组织指出&#xff1a;中亚约有1200万人生活在干旱风险高的地区&#xff0c;面积约为4000万公顷。位于亚洲中部的哈萨克斯坦共和国&#xff08;简称哈萨克斯坦&#xff09;和中国有着长期友好的睦邻和经贸关系&#xff0c;中国是哈萨克斯坦的主要农产…

C++:day3

思维导图 练习题 #include <iostream> using namespace std;class Per { private:string name;int age;int *height;double weight;public:Per(){cout << "Per::无参构造函数" << endl;}Per(string name, int age, int height, double weight) :…

2004NOIP普及组真题 2. 花生采摘

线上OJ&#xff1a; 【04NOIP普及组】花生采摘 核心思想&#xff1a; 1、本题为贪心即可。 2、因为本题严格限制了顺序&#xff0c;所以先把每个节点的花生数量按降序排序。然后逐一判断下一个花生是否需要去采摘即可 3、每一次采摘完&#xff0c;记录耗时 t 以及采集的花…

GPT-4o(OpenAI最新推出的大模型)

简介&#xff1a;最近&#xff0c;GPT-4o横空出世。对GPT-4o这一人工智能技术进行评价&#xff0c;包括版本间的对比分析、GPT-4o的技术能力以及个人感受等。 方向一&#xff1a;对比分析 GPT-4o&#xff08;OpenAI最新推出的大模型&#xff09;与GPT-4之间的主要区别体现在响应…

SSM框架整合,内嵌Tomcat。基于注解的方式集成

介绍&#xff1a; SSM相信大家都不陌生&#xff0c;在spring boot出现之前&#xff0c;SSM一直是Java在web开发中的老大哥。现在虽说有了spring boot能自动整合第三方框架了&#xff0c;但是现在市面上任然有很多老项目是基于SSM技术的。因此&#xff0c;能熟练掌握SSM进行开发…

Python接入淘宝API接口采集商品详情页到手价优惠券信息数据:智能化营销的加速器

在电子商务领域&#xff0c;智能化营销正在成为提高效率和竞争力的关键。淘宝API提供了一套完整的解决方案&#xff0c;帮助商家实现智能化营销&#xff0c;从而提升销售业绩和顾客满意度。 库存管理&#xff1a; 淘宝API使商家能够实时监控库存水平&#xff0c;自动补货&#…