自然語言處理:文本分類

介紹

大家好,我這個熱衷于分享知識的博主又來啦!之前我們一起深入探討了自然語言處理領域中非常重要的兩個方法:樸素貝葉斯邏輯斯諦回歸。在探索的過程中,我們剖析了樸素貝葉斯如何基于概率原理和特征條件獨立假設,快速對文本進行分類。也了解了邏輯斯諦回歸是怎樣通過巧妙地將線性模型與邏輯函數相結合,精準地預測文本的類別歸屬。

而今天,我要帶大家進一步深入自然語言處理的世界,來聊聊文本分類這個關鍵的主題。有了之前對樸素貝葉斯邏輯斯諦回歸的講解,相信大家對文本分類中涉及的一些基礎概念和核心思路已經有了一定的認知。我相信今天關于文本分類的分享,理解起來會更加順暢,也能讓大家更系統地掌握自然語言處理中這一重要的技術應用!

文本分類

概念闡述

自然語言處理中的文本分類,是指運用自然語言處理和機器學習等相關技術,依據文本的內容、結構、語義、情感傾向等多方面特征,將給定的文本自動劃分到預先定義好的一個或多個類別中的過程

這些預先設定的類別可以是諸如新聞領域中的政治、經濟、文化、體育等主題分類;電商場景里的產品好評、差評、中評的情感分類;或者是垃圾郵件識別中的正常郵件與垃圾郵件分類等。

文本分類通過對文本信息的理解和分析,實現對文本的有效組織與管理,從而為信息檢索、情感分析、內容推薦等自然語言處理任務提供支持。

基于規則的文本分類

在文本分類任務里,基于規則的方法常運用正則表達式。具體來說,針對每個文本類別,我們都要編寫一條甚至多條正則表達式。就拿商品評論分類舉例:

  • 好評的正則表達式可以寫成 “.(非常好 | 不錯 | 很 (贊 | 滿意)).” ,它表示只要文本中出現“非常好”“不錯”“很贊”“很滿意”等詞匯,就可能屬于好評。
  • 而差評的正則表達式 “.(太 (差 | 爛)| 糟糕 | 避雷).” ,意味著文本里若有“太差”“太爛”“糟糕”“避雷”這類詞,大概率是差評。

我們用代碼來演示一下:

完整代碼
# 導入正則表達式模塊,用于處理正則匹配
import re# 定義一個自然語言處理文本分類的類
class NLPTextClassification:# 類的初始化方法,目前為空,不做任何操作def __init__(self):pass# 定義文本分類方法,接收一個評論文本作為輸入def text_classification(self, review_text):# 定義分類規則列表,包含正則表達式、類別和優先級classification_rules = [# 定義好評的正則表達式規則,匹配包含特定詞匯的文本(re.compile(r'.*(非常好|不錯|很(贊|滿意)).*'), '好評', 1),# 定義差評的正則表達式規則,匹配包含特定詞匯的文本(re.compile(r'.*(太(差|爛)|糟糕|避雷).*'), '差評', 2)]# 存儲匹配到的規則信息matched_classification_rules = []# 遍歷規則列表for regex_pattern, category, priority in classification_rules:# 檢查評論是否匹配當前規則if regex_pattern.match(review_text):# 若匹配則添加到匹配規則列表matched_classification_rules.append((category, priority))# 若沒有匹配到任何規則if len(matched_classification_rules) == 0:# 返回未分類結果return '未分類'# 若只匹配到一條規則elif len(matched_classification_rules) == 1:# 返回該規則對應的類別return matched_classification_rules[0][0]else:# 對匹配規則按優先級排序matched_classification_rules.sort(key=lambda x: x[1])# 返回優先級最高的規則對應的類別return matched_classification_rules[0][0]# 當腳本作為主程序運行時執行以下代碼
if __name__ == "__main__":# 創建NLPTextClassification類的實例nlp_text_normalization = NLPTextClassification()# 定義商品評論列表,包含多條不同的評論文本product_reviews = ["這個商品非常好,我很滿意","這個商品太差了,太爛了","這個商品不錯,但有點小瑕疵,避雷吧","商品還行,沒什么特別的"]# 遍歷評論列表進行分類for review in product_reviews:# 調用實例的文本分類方法進行分類classification_result = nlp_text_normalization.text_classification(review)# 打印評論內容及其分類結果print(f"評論: {review},分類結果: {classification_result}")
運行結果
評論: 這個商品非常好,我很滿意,分類結果: 好評
評論: 這個商品太差了,太爛了,分類結果: 差評
評論: 這個商品不錯,但有點小瑕疵,避雷吧,分類結果: 好評
評論: 商品還行,沒什么特別的,分類結果: 未分類進程已結束,退出代碼為 0

當面對一篇文檔時,如果它只匹配上了一條正則表達式,那直接就能確定其對應的類別。可要是文檔同時匹配了多條對應不同類別的正則表達式,就得提前設定好這些正則表達式的優先級,輸出優先級最高的那條正則表達式所對應的類別。

這種用正則表達式進行文本分類的方式,有明顯的優點:

  • 首先,規則簡單易懂,即便是不太了解技術的人,也能明白分類的依據。
  • 其次,要是分類結果出錯,由于規則清晰,能迅速找到是哪條規則出了問題,方便及時修改,比如刪掉不合適的規則、增添新規則等。
  • 而且,和基于機器學習的文本分類比起來,它無需大量標注數據,也不用復雜的訓練過程,能節省不少時間和精力。

不過,它的缺點也不容忽視:

  • 一方面,編寫正則表達式需要既懂分類業務,又熟悉正則表達式的專家,人力門檻較高。
  • 另一方面,由于語言表達的豐富性和多樣性,即使是專家,也很難寫出能涵蓋所有情況的正則表達式,導致覆蓋率有限。
  • 另外,在有標注數據的情況下,這種方法難以借助這些數據自動優化規則,缺乏自我提升的能力。

基于機器學習的文本分類

在自然語言處理領域,基于機器學習的文本分類是指利用機器學習中的監督學習算法,借助已標注好類別的訓練數據(如由人工仔細標注的文檔集合),讓模型學習文本特征與類別之間的映射關系,從而對新文本自動歸類的過程。

該方式可分為生成式分類器和判別式分類器。生成式分類器著重對每個類別下的文本分布進行建模,然后依據模型計算文本屬于各類別的概率;判別式分類器則聚焦于挖掘能有效區分不同類別的文本特征,直接預測文本所屬類別。

在這兩類分類器中,樸素貝葉斯算法便是典型的生成式分類器的代表。它基于條件獨立假設等原理,對每個類別內的文本分布進行建模。通過學習訓練數據中每個類別出現的先驗概率,以及每個詞在各個類別中出現的條件概率,來計算文本屬于不同類別的概率。

邏輯斯諦回歸則屬于判別式分類器,它直接挖掘文本中能夠區分不同類別的特征,通過構建邏輯函數將線性回歸的輸出轉化為概率值,以此預測文本的類別。

樸素貝葉斯

概念闡述

樸素貝葉斯是生成式分類器中的基礎模型,它基于概率論和貝葉斯定理,通過計算文本在不同類別下的概率來判斷文本類別。它假設文本中的各個特征(詞)在給定類別下是相互獨立的,即條件獨立假設;同時采用詞袋假設,忽略詞的順序,僅考慮詞的出現情況,將文本看作是詞的集合。

公式展示

將文檔表示為詞的序列d=(x_1, x_2,\cdots, x_n) ,類別集合為C。根據貝葉斯公式,計算文檔d屬于類別c的后驗概率:

P(c|d)=\frac{P(d|c)P(c)}{P(d)}

由于P(d)對于所有類別都是相同的常數,在比較不同類別概率大小時可忽略,因此樸素貝葉斯分類的目標是求解:

\hat{c}=\arg\max_{c\in C}P(d|c)P(c)=\arg\max_{c\in C}P(x_1, x_2,\cdots, x_n|c)P(c)

基于條件獨立假設,P(x_1, x_2,\cdots, x_n|c)=\prod_{i = 1}^{n}P(x_i|c),所以公式可進一步寫為:

\hat{c}=\arg\max_{c\in C}P(c)\prod_{i = 1}^{n}P(x_i|c)

其中,\hat{c}是預測的文檔類別;P(c)是類別c的先驗概率;P(x_i|c)是在類別c下詞x_i出現的條件概率 。

原理解釋

樸素貝葉斯的核心在于根據訓練數據學習每個類別出現的先驗概率,以及每個詞在各個類別中出現的條件概率。當對新文本分類時,根據這些已學習到的概率,結合貝葉斯公式計算該文本屬于各個類別的后驗概率,最終將文本劃分到后驗概率最大的類別中。

具體而言,先從訓練集中統計每個類別文檔的數量,以計算先驗概率;再統計每個詞在不同類別文檔中出現的次數,進而得到條件概率。對于新文本,基于條件獨立假設,將文本中各個詞的條件概率相乘,再乘以先驗概率,得到該文本屬于每個類別的概率值,以此完成分類判斷。

代碼演示

接下來的幾段代碼,將為大家展示樸素貝葉斯模型的訓練與預測過程。這里所用到的數據集,是代碼自動生成的Books數據集,其中涵蓋了大約1萬本圖書的標題,這些標題被劃分成6種主題。

首先,在正式進行模型訓練和預測之前,需要先進行數據預處理,針對文本分類的預處理主要包含以下幾個關鍵步驟:

  • 文本統一化:對于英文文本,通常把所有字母轉換為小寫形式;而中文內容,則統一轉換為簡體字。這樣的操作一般不會對文本所表達的核心內容產生影響。
  • 標點去除:英文里,標點符號與單詞緊密相連(比如“Let's go.”),要是去掉標點,“Let' s”“go”會被當作和“Let”“s”“there”不同的詞來識別,這顯然不符合實際情況。在中文里,去掉標點通常也不會干擾文本想要傳達的信息。
  • 分詞處理:中文和英文不同,漢字之間沒有空格來區分,所以中文分詞的難度有時會比英文分詞更大,具體的分詞方法這里就不詳細展開了。
  • 停用詞清理:“and”“the”“了”這類詞,它們在文本中出現的頻率很高,但本身并沒有實際的表意價值,所以需要把它們從文本中去除。
  • 構建詞表:在構建詞表時,一般會把語料庫中出現頻率極低的詞排除在外。
  • 詞向量化:將每個詞轉化為詞表中的索引(也就是ID),這樣更便于機器學習模型進行數據處理和分析。

然后,在完成分詞操作后,篩選出出現次數大于3次的詞元,據此構建詞表,并將分詞后的文檔轉換為對應的詞元ID序列。

最后,我們要著手把數據以及對應的標簽整理成一種更有利于進行模型訓練的矩陣格式。這種格式能夠讓數據的結構更加規整,使得后續的訓練過程更加高效、順暢,有助于模型更好地學習數據中的特征和模式,從而提升訓練的效果和質量。

在運行下列代碼前,我們需要安裝spacy庫,安裝命令:

pip install spacy

注:spacy是一款強大且高效的Python自然語言處理庫,廣泛應用于多種文本處理任務。它能夠實現精準的詞法分析,像將文本分割為詞或符號的分詞操作,為每個詞標注詞性的詞性標注,以及把詞還原成基本形式的詞形還原。

成功安裝spacy庫后,我們還需要下載預訓練的中文小型語言模型zh_core_web_sm,下載命令為:

python -m spacy download zh_core_web_sm

注:zh_core_web_smspacy庫提供的一個預訓練的中文語言模型。在自然語言處理(NLP)任務中,我們常常需要對文本進行各種分析和處理,而zh_core_web_sm模型可以幫助我們完成這些任務。例如在處理中文新聞文章時,使用該模型可以進行詞性標注,了解每個詞在句子中的詞性;還能進行命名實體識別,找出文章里的人名、地名、組織機構名等關鍵信息,這有助于我們對文章內容進行快速理解和分類。?

完整代碼

nlp_dataset_processor.py

# 導入用于處理JSON數據的模塊
import json
# 從collections模塊中導入defaultdict類,用于創建默認值為0的字典
from collections import defaultdict
# 導入自然語言處理庫spacy
import spacy
# 從spacy的中文語言模塊中導入中文停用詞集合
from spacy.lang.zh.stop_words import STOP_WORDS
# 從tqdm模塊中導入tqdm函數,用于顯示進度條
from tqdm import tqdm
# 導入用于數據可視化的庫matplotlib
import matplotlib# 設置matplotlib的后端為tkAgg,以便在圖形界面中顯示圖表
matplotlib.use('tkAgg')
# 加載中文語言模型,用于后續的自然語言處理任務
nlp_tool = spacy.load('zh_core_web_sm')# 定義一個名為DatasetProcessor的類,用于處理數據集相關的操作
class DatasetProcessor:# 類的初始化方法,用于設置類的屬性并初始化數據def __init__(self):# 初始化標簽ID到標簽名稱的映射為空self.id_to_label = None# 初始化標簽名稱到標簽ID的映射為空self.label_to_id = None# 初始化測試數據集為空self.test_dataset = None# 初始化訓練數據集為空self.train_dataset = None# 初始化詞到ID的映射為空self.word_to_id = None# 設置訓練數據文件和測試數據文件的路徑self.train_file_path, self.test_file_path = 'training_dataset.jsonl', 'test_dataset.jsonl'# 調用initialize_data方法初始化數據self.initialize_data()# 定義一個方法,用于讀取指定路徑的JSON文件并解析為Python對象列表def read_json_file(self, file_path):# 以只讀模式打開指定路徑的文件,并指定編碼為utf-8with open(file_path, 'r', encoding='utf-8') as file_reader:# 讀取文件的所有行并存儲為列表json_lines = list(file_reader)# 初始化一個空列表,用于存儲解析后的JSON數據data_list = []# 遍歷每一行JSON數據for json_line in json_lines:# 將JSON字符串解析為Python對象,并添加到數據列表中data_list.append(json.loads(json_line))# 返回解析后的數據列表return data_list# 定義一個方法,用于初始化訓練數據集、測試數據集以及標簽的映射關系def initialize_data(self):# 調用read_json_file方法讀取訓練數據文件和測試數據文件self.train_dataset, self.test_dataset = self.read_json_file(self.train_file_path), self.read_json_file(self.test_file_path)# 打印訓練數據集和測試數據集的大小print('訓練數據集大小 =', len(self.train_dataset),', 測試數據集大小 =', len(self.test_dataset))# 初始化標簽名稱到標簽ID和標簽ID到標簽名稱的映射字典self.label_to_id, self.id_to_label = {}, {}# 遍歷訓練數據集和測試數據集for data_subset in [self.train_dataset, self.test_dataset]:# 遍歷數據集中的每個數據項for data_item in data_subset:# 獲取數據項中的類別標簽文本label_text = data_item['class']# 如果標簽文本不在標簽名稱到標簽ID的映射字典中if label_text not in self.label_to_id:# 為該標簽分配一個新的IDlabel_index = len(self.label_to_id)# 將標簽文本和對應的ID添加到標簽名稱到標簽ID的映射字典中self.label_to_id[label_text] = label_index# 將ID和對應的標簽文本添加到標簽ID到標簽名稱的映射字典中self.id_to_label[label_index] = label_text# 獲取該標簽在映射字典中的IDlabel_id = self.label_to_id[label_text]# 在數據項中添加標簽ID字段data_item['label'] = label_id# 定義一個方法,用于對數據集中的文本進行分詞處理,并去除停用詞def tokenize_text(self, attribute='book'):# 遍歷訓練數據集和測試數據集for data_subset in [self.train_dataset, self.test_dataset]:# 使用tqdm顯示處理進度條,遍歷數據集中的每個數據項for data_item in tqdm(data_subset):# 獲取數據項中指定屬性的文本,并轉換為小寫text_content = data_item[attribute].lower()# 使用nlp_tool對文本進行分詞,并過濾掉停用詞,獲取分詞列表tokens_list = [token.text for token in nlp_tool(text_content) if token.text not in STOP_WORDS]# 在數據項中添加分詞結果字段data_item['tokens'] = tokens_list# 定義一個方法,用于構建詞匯表,并統計詞匯的相關信息def build_vocabulary(self, min_frequency=3, min_length=2, max_size=None):# 初始化一個默認值為0的字典,用于統計每個詞的出現頻率word_frequency = defaultdict(int)# 遍歷訓練數據集中的每個數據項for data_item in self.train_dataset:# 獲取數據項中的分詞列表tokens = data_item['tokens']# 遍歷分詞列表中的每個詞for token in tokens:# 統計詞的出現頻率word_frequency[token] += 1# 打印詞匯表的相關統計信息,包括唯一詞數、總詞數、最大頻率和最小頻率print(f'unique tokens = {len(word_frequency)}, ' + \f'total counts = {sum(word_frequency.values())}, ' + \f'max freq = {max(word_frequency.values())}, ' + \f'min freq = {min(word_frequency.values())}')# 初始化詞到ID的映射字典self.word_to_id = {}# 初始化ID到詞的映射字典self.id_to_word = {}# 初始化總詞數計數器total_token_count = 0# 按詞頻從高到低遍歷詞頻字典for token, freq in sorted(word_frequency.items(), key=lambda x: -x[1]):# 如果設置了最大詞匯表大小,且當前詞匯表大小已達到或超過該值,則停止添加詞if max_size and len(self.word_to_id) >= max_size:break# 如果詞的頻率大于最小頻率要求if freq > min_frequency:# 如果未設置最小詞長要求,或者詞長滿足最小詞長要求if (min_length is None) or (min_length and len(token) >= min_length):# 將詞添加到詞到ID的映射字典中,并記錄其IDself.word_to_id[token] = len(self.word_to_id)# 將ID添加到ID到詞的映射字典中,并記錄對應的詞self.id_to_word[len(self.id_to_word)] = token# 累加總詞數total_token_count += freqelse:break# 打印詞匯表構建的相關參數和統計信息,包括最小頻率、最小詞長、最大大小、剩余詞數和詞匯表覆蓋率print(f'min_freq = {min_frequency}, min_len = {min_length}, ' + \f'max_size = {max_size}, 'f'remaining tokens = {len(self.word_to_id)}, 'f'in-vocab rate = {total_token_count / sum(word_frequency.values())}')# 定義一個方法,用于將數據集中的分詞結果轉換為對應的詞ID列表def convert_tokens_to_indices(self):# 遍歷訓練數據集和測試數據集for data_subset in [self.train_dataset, self.test_dataset]:# 遍歷數據集中的每個數據項for data_item in data_subset:# 初始化一個空列表,用于存儲詞IDdata_item['token_indices'] = []# 遍歷數據項中的每個分詞for token in data_item['tokens']:# 如果分詞在詞到ID的映射字典中if token in self.word_to_id:# 將分詞對應的ID添加到詞ID列表中data_item['token_indices'].append(self.word_to_id[token])

nlp_naive_bayes_classifier.py

# 導入用于數值計算的numpy庫
import numpy as np# 定義一個樸素貝葉斯分類器類
class NaiveBayesClassifier:# 類的初始化方法,接收類別數量和詞匯表大小作為參數def __init__(self, num_classes, vocabulary_size):# 存儲類別數量self.num_classes = num_classes# 存儲詞匯表大小self.vocabulary_size = vocabulary_size# 初始化先驗概率數組,長度為類別數量,元素類型為64位浮點數self.prior_probabilities = np.zeros(num_classes, dtype=np.float64)# 初始化似然概率矩陣,形狀為(類別數量, 詞匯表大小),元素類型為64位浮點數self.likelihood_probabilities = np.zeros((num_classes, vocabulary_size), dtype=np.float64)# 定義訓練模型的方法,接收輸入特征和對應的標簽作為參數def train_model(self, input_features, labels):# 遍歷輸入特征和對應的標簽for feature, label in zip(input_features, labels):# 統計每個類別的樣本數量,更新先驗概率self.prior_probabilities[label] += 1# 遍歷輸入特征中的每個詞的索引for token_index in feature:# 統計每個類別下每個詞的出現次數,更新似然概率self.likelihood_probabilities[label, token_index] += 1# 計算先驗概率,將每個類別的樣本數量除以總樣本數量self.prior_probabilities /= self.prior_probabilities.sum()# 對似然概率矩陣進行拉普拉斯平滑,避免概率為0的情況self.likelihood_probabilities += 1# 計算似然概率,將每個類別下每個詞的出現次數除以該詞在所有類別中的總出現次數self.likelihood_probabilities /= self.likelihood_probabilities.sum(axis=0)# 對先驗概率取對數,避免下溢問題self.prior_probabilities = np.log(self.prior_probabilities)# 對似然概率取對數,避免下溢問題self.likelihood_probabilities = np.log(self.likelihood_probabilities)# 定義進行預測的方法,接收輸入特征作為參數def make_predictions(self, input_features):# 初始化一個空列表,用于存儲預測結果predictions = []# 遍歷每個輸入特征for feature in input_features:# 初始化一個概率數組,用于存儲每個類別的預測概率probabilities = np.zeros(self.num_classes, dtype=np.float64)# 遍歷每個類別for i in range(self.num_classes):# 累加該類別的先驗概率probabilities[i] += self.prior_probabilities[i]# 遍歷輸入特征中的每個詞的索引for token in feature:# 累加該類別下該詞的似然概率probabilities[i] += self.likelihood_probabilities[i, token]# 將概率最大的類別索引作為預測結果,添加到預測結果列表中predictions.append(np.argmax(probabilities))# 返回預測結果列表return predictions

nlp_text_classification.py

# 導入用于數值計算的numpy庫
import numpy as np
# 從自定義模塊中導入數據集處理類
from nlp_dataset_processor import DatasetProcessor
# 從自定義模塊中導入樸素貝葉斯分類器類
from nlp_naive_bayes_classifier import NaiveBayesClassifier# 定義一個自然語言處理文本分類的類
class NLPTextClassification:# 類的初始化方法,目前為空,不做任何操作def __init__(self):pass# 定義文本分類方法def text_classification(self):# 創建數據集處理對象,用于加載和預處理數據集dataset = DatasetProcessor()# 對數據集中的文本進行分詞處理dataset.tokenize_text()# 打印訓練數據集中第一個樣本的分詞結果print(dataset.train_dataset[0]['tokens'])# 打印標簽到ID的映射關系print(dataset.label_to_id)# 構建詞匯表,設置最小詞頻為3dataset.build_vocabulary(min_frequency=3)# 將分詞結果轉換為對應的詞ID列表dataset.convert_tokens_to_indices()# 打印訓練數據集中第一個樣本的詞ID列表print(dataset.train_dataset[0]['token_indices'])# 初始化訓練輸入特征和訓練標簽列表training_input_features, training_labels = [], []# 初始化測試輸入特征和測試標簽列表testing_input_features, testing_labels = [], []# 遍歷訓練數據集for data in dataset.train_dataset:# 初始化特征向量,長度為詞匯表大小,元素類型為32位整數feature_vector = np.zeros(len(dataset.word_to_id), dtype=np.int32)# 遍歷樣本的詞ID列表for token_index in data['token_indices']:# 統計每個詞的出現次數feature_vector[token_index] += 1# 將特征向量添加到訓練輸入特征列表中training_input_features.append(feature_vector)# 將樣本的標簽添加到訓練標簽列表中training_labels.append(data['label'])# 遍歷測試數據集for data in dataset.test_dataset:# 初始化特征向量,長度為詞匯表大小,元素類型為32位整數feature_vector = np.zeros(len(dataset.word_to_id), dtype=np.int32)# 遍歷樣本的詞ID列表for token_index in data['token_indices']:# 統計每個詞的出現次數feature_vector[token_index] += 1# 將特征向量添加到測試輸入特征列表中testing_input_features.append(feature_vector)# 將樣本的標簽添加到測試標簽列表中testing_labels.append(data['label'])# 將訓練輸入特征和訓練標簽轉換為numpy數組training_input_features, training_labels = np.array(training_input_features), np.array(training_labels)# 將測試輸入特征和測試標簽轉換為numpy數組testing_input_features, testing_labels = np.array(testing_input_features), np.array(testing_labels)# 創建樸素貝葉斯分類器對象,傳入類別數量和詞匯表大小naive_bayes_model = NaiveBayesClassifier(len(dataset.label_to_id), len(dataset.word_to_id))# 重新初始化訓練輸入特征和訓練標簽列表training_input_features, training_labels = [], []# 遍歷訓練數據集for data in dataset.train_dataset:# 將樣本的詞ID列表添加到訓練輸入特征列表中training_input_features.append(data['token_indices'])# 將樣本的標簽添加到訓練標簽列表中training_labels.append(data['label'])# 使用訓練數據對樸素貝葉斯模型進行訓練naive_bayes_model.train_model(training_input_features, training_labels)# 打印前3個類別的先驗概率for i in range(3):print(f'P({dataset.id_to_label[i]}) = {np.exp(naive_bayes_model.prior_probabilities[i])}')# 打印前3個詞在第一個類別下的似然概率for i in range(3):print(f'P({dataset.id_to_word[i]}|{dataset.id_to_label[0]}) = ' + \f'{np.exp(naive_bayes_model.likelihood_probabilities[0, i])}')# 重新初始化測試輸入特征和測試標簽列表testing_input_features, testing_labels = [], []# 遍歷測試數據集for data in dataset.test_dataset:# 將樣本的詞ID列表添加到測試輸入特征列表中testing_input_features.append(data['token_indices'])# 將樣本的標簽添加到測試標簽列表中testing_labels.append(data['label'])# 使用訓練好的樸素貝葉斯模型對測試數據進行預測naive_bayes_predictions = naive_bayes_model.make_predictions(testing_input_features)# 打印前5個測試樣本的預測結果和真實標簽for i, (prediction, label) in enumerate(zip(naive_bayes_predictions, testing_labels)):if i >= 5:breakprint(f'test example:{i}, prediction = {prediction}, label = {label}')# 程序入口,當腳本作為主程序運行時執行
if __name__ == "__main__":# 創建自然語言處理文本分類對象nlp_text_classification = NLPTextClassification()# 調用文本分類方法進行文本分類操作nlp_text_classification.text_classification()
運行結果
訓練數據集大小 = 8627 , 測試數據集大小 = 2157
100%|██████████| 8627/8627 [00:20<00:00, 413.90it/s]
100%|██████████| 2157/2157 [00:05<00:00, 413.93it/s]
['地質學', '前沿', '研究', '進展']
{'科學類': 0, '計算機類': 1, '藝術傳媒類': 2, '經管類': 3, '文學類': 4, '歷史類': 5}
unique tokens = 97, total counts = 36235, max freq = 868, min freq = 262
min_freq = 3, min_len = 2, max_size = None, remaining tokens = 93, in-vocab rate = 0.9606181868359321
[80, 36, 37, 38]
P(科學類) = 0.1662223252579112
P(計算機類) = 0.16680190100846182
P(藝術傳媒類) = 0.17016344036165526
P(小說|科學類) = 0.0011441647597254007
P(指南|科學類) = 0.0012987012987012991
P(揭秘|科學類) = 0.001362397820163487
測試樣本:0, 預測結果 = 2, 真實類別 = 2
測試樣本:1, 預測結果 = 2, 真實類別 = 2
測試樣本:2, 預測結果 = 1, 真實類別 = 1
測試樣本:3, 預測結果 = 5, 真實類別 = 5
測試樣本:4, 預測結果 = 2, 真實類別 = 2進程已結束,退出代碼為 0

這段代碼的目的是對書籍相關的文本數據進行預處理,構建樸素貝葉斯分類模型,并使用該模型對數據進行分類預測。通過數據處理和模型訓練,實現對文本數據的自動分類。?

邏輯斯諦回歸

概念闡述

邏輯斯諦回歸(Logistic Regression)是一種廣義的線性回歸分析模型,常用于處理二分類問題(也可擴展到多分類問題),雖然名字里有“回歸”,但它的本質是用于分類預測。它通過一個邏輯斯諦函數(也稱為Sigmoid函數)將線性回歸模型的輸出值映射到一個概率值,該概率值表示樣本屬于某一類別的可能性大小。

例如,在判斷一封郵件是否為垃圾郵件的場景中,邏輯斯諦回歸可以根據郵件的各種特征(如發件人、主題、內容關鍵詞等)計算出該郵件是垃圾郵件的概率,然后根據設定的閾值(通常為0.5)來決定郵件的類別。

公式展示

線性回歸部分:輯斯諦回歸首先基于線性回歸模型,對于有$n$個特征的樣本$x = (x_1, x_2, ..., x_n)$,其線性組合為$z = w_0 + w_1x_1 + w_2x_2 + ... + w_nx_n$,可以寫成向量形式$z = w^Tx$,其中$w = (w_0, w_1, ..., w_n)$是模型的參數向量,$x = (1, x_1, x_2, ..., x_n)$(在$x$向量中添加了一個常數項$1$$w_0$對應)。

邏輯斯諦函數(Sigmoid函數):將線性回歸的結果$z$作為輸入,通過Sigmoid函數$\sigma(z) = \frac{1}{1 + e^{-z}}$,將$z$映射到區間$(0, 1)$上,得到樣本屬于正類(通常標記為1)的概率$p = \sigma(z) = \frac{1}{1 + e^{-w^Tx}}$。那么樣本屬于負類(通常標記為0)的概率為$1 - p$

原理解釋:

  • 概率估計:邏輯斯諦回歸的核心原理是通過最大化樣本的似然函數來估計模型的參數$w$。對于一個二分類問題,假設樣本$x_i$屬于正類的概率為$p_i = \frac{1}{1 + e^{-w^Tx_i}}$,屬于負類的概率為$1 - p_i$。給定一組獨立同分布的樣本$(x_1, y_1), (x_2, y_2), ..., (x_m, y_m)$,其中$y_i \in \{0, 1\}$是樣本$x_i$的真實標簽,其似然函數為$L(w) = \prod_{i = 1}^{m} p_i^{y_i} (1 - p_i)^{1 - y_i}$
  • 對數似然函數:為了便于計算和求導,通常對似然函數取對數,得到對數似然函數$l(w) = \sum_{i = 1}^{m} [y_i \ln(p_i) + (1 - y_i) \ln(1 - p_i)]$
  • 參數估計:目標是找到一組參數$w$,使得對數似然函數$l(w)$最大化。常用的方法是梯度上升法(與最小化損失函數的梯度下降法相對應),通過不斷更新參數$w$,沿著梯度的方向逐步增加對數似然函數的值,直到達到收斂。在實際應用中,也可以通過一些優化算法如隨機梯度下降、批量梯度下降等來求解參數$w$,從而得到最優的邏輯斯諦回歸模型,用于對新的樣本進行分類預測。?
代碼演示

我們使用代碼來演示,基于博主在自然語言處理:文本表示-CSDN博客介紹的TF-IDF方法構建文檔的特征向量表示,并借助PyTorch深度學習框架實現邏輯斯諦回歸模型的訓練與預測。

邏輯斯諦回歸本質上可被視為一種僅有一層的神經網絡模型架構,借助PyTorch強大的框架來實現該模型時,能夠輕松且高效地運用其自動求導功能,極大地簡化了模型訓練過程中的梯度計算。

下面給出的代碼會利用已經經過訓練、能夠有效處理相關任務的模型,針對測試集中的數據進行預測。之后,會把預測得到的分類結果報告出來,方便我們了解模型在測試數據上的表現。

完整代碼

nlp_tfidf_transformer.py

# 導入用于數值計算的numpy庫
import numpy as np# 定義一個TF-IDF轉換器類,用于將文本特征轉換為TF-IDF特征
class TFIDFTransformer:# 類的初始化方法,接收詞匯表大小、歸一化方式、是否平滑處理IDF和是否使用子線性TF作為參數def __init__(self, vocabulary_size, norm='l2', smooth_idf=True, sublinear_tf=True):# 初始化逆文檔頻率(IDF)為Noneself.idf = None# 存儲詞匯表大小self.vocabulary_size = vocabulary_size# 存儲歸一化方式,默認為'l2'self.norm = norm# 存儲是否對IDF進行平滑處理的標志,默認為Trueself.smooth_idf = smooth_idf# 存儲是否使用子線性TF的標志,默認為Trueself.sublinear_tf = sublinear_tf# 定義擬合轉換器的方法,用于計算逆文檔頻率(IDF)def fit_transformer(self, input_features):# 初始化文檔頻率數組,長度為詞匯表大小,元素類型為64位浮點數document_frequency = np.zeros(self.vocabulary_size, dtype=np.float64)# 遍歷每個輸入特征for data in input_features:# 遍歷輸入特征中唯一的詞索引for token_index in set(data):# 統計每個詞的文檔頻率document_frequency[token_index] += 1# 對文檔頻率進行平滑處理,若smooth_idf為True則加1,否則加0document_frequency += int(self.smooth_idf)# 計算樣本數量,加上平滑處理的樣本數num_samples = len(input_features) + int(self.smooth_idf)# 計算逆文檔頻率(IDF)self.idf = np.log(num_samples / document_frequency) + 1# 定義轉換特征的方法,將輸入特征轉換為TF - IDF特征def transform_features(self, input_features):# 確保已經計算了逆文檔頻率(IDF)assert hasattr(self, 'idf')# 初始化詞頻矩陣,形狀為(輸入特征數量,詞匯表大小),元素類型為64位浮點數term_frequency = np.zeros((len(input_features), self.vocabulary_size), dtype=np.float64)# 遍歷每個輸入特征及其索引for i, data in enumerate(input_features):# 遍歷輸入特征中的每個詞索引for token in data:# 統計詞頻term_frequency[i, token] += 1# 如果使用子線性TFif self.sublinear_tf:# 對詞頻進行對數變換term_frequency = np.log(term_frequency + 1)# 計算TF-IDF特征矩陣transformed_features = term_frequency * self.idf# 如果設置了歸一化方式if self.norm:# 計算每行的范數row_norm = (transformed_features ** 2).sum(axis=1)# 將范數為0的行設置為1,避免除零錯誤row_norm[row_norm == 0] = 1# 對TF-IDF特征矩陣進行歸一化transformed_features /= np.sqrt(row_norm)[:, None]# 返回轉換后的TF-IDF特征矩陣return transformed_features# 定義擬合并轉換特征的方法,先計算IDF再轉換輸入特征def fit_and_transform(self, input_features):# 調用fit_transformer方法計算逆文檔頻率(IDF)self.fit_transformer(input_features)# 調用transform_features方法將輸入特征轉換為TF-IDF特征return self.transform_features(input_features)

nlp_logistic_regression_model.py

# 從torch模塊導入nn子模塊,用于構建神經網絡
from torch import nn# 定義一個邏輯回歸模型類,繼承自nn.Module
class LogisticRegressionModel(nn.Module):# 類的初始化方法,接收輸入維度和輸出維度作為參數def __init__(self, input_dimension, output_dimension):# 調用父類的初始化方法super(LogisticRegressionModel, self).__init__()# 定義一個線性層,輸入維度為input_dimension,輸出維度為output_dimensionself.linear_layer = nn.Linear(input_dimension, output_dimension)# 定義模型的前向傳播方法,接收輸入特征和可選的標簽作為參數def forward(self, input_features, labels=None):# 通過線性層計算輸出outputs = self.linear_layer(input_features)# 如果傳入了標簽if labels is not None:# 定義交叉熵損失函數loss_function = nn.CrossEntropyLoss()# 計算損失loss = loss_function(outputs, labels)# 返回損失和輸出return loss, outputs# 如果沒有傳入標簽,直接返回輸出return outputs

nlp_custom_dataset.py

# 從torch.utils.data模塊導入Dataset類,用于自定義數據集
from torch.utils.data import Dataset# 定義一個自定義數據集類,繼承自torch的Dataset類
class CustomDataset(Dataset):# 類的初始化方法,接收輸入特征和標簽作為參數def __init__(self, input_features, labels):# 存儲輸入特征self.input_features = input_features# 存儲標簽self.labels = labels# 定義返回數據集長度的方法,用于獲取數據集樣本數量def __len__(self):# 返回輸入特征的數量,即數據集的樣本數return len(self.input_features)# 定義根據索引獲取數據集中單個樣本的方法def __getitem__(self, index):# 根據索引返回對應的輸入特征和標簽return self.input_features[index], self.labels[index]

nlp_data_collation.py

# 導入用于數值計算的numpy庫
import numpy as np
# 導入深度學習框架PyTorch
import torch# 定義一個數據整理類,用于對批量數據進行整理
class DataCollation:# 定義一個類方法,用于將批量數據整理成適合模型輸入的格式@classmethoddef collate_batch_data(cls, batch):# 初始化空列表,用于分別存儲特征和標簽features, labels = [], []# 遍歷批量數據中的每個樣本for feature, label in batch:# 將樣本的特征添加到特征列表中features.append(feature)# 將樣本的標簽添加到標簽列表中labels.append(label)# 將特征列表轉換為numpy數組,再轉換為torch的浮點型張量features = torch.tensor(np.array(features), dtype=torch.float)# 將標簽列表轉換為numpy數組,再轉換為torch的長整型張量labels = torch.tensor(np.array(labels), dtype=torch.long)# 返回一個字典,包含整理好的輸入特征和標簽return {'input_features': features, 'labels': labels}

nlp_text_classification.py

# 導入用于數值計算的numpy庫
import numpy as np
# 導入深度學習框架PyTorch
import torch
# 從torch.utils.data模塊導入DataLoader類,用于批量加載數據
from torch.utils.data import DataLoader
# 從torch.optim模塊導入Adam優化器,用于優化模型參數
from torch.optim import Adam
# 從tqdm模塊導入trange函數,用于顯示進度條
from tqdm import trange
# 導入用于數據可視化的matplotlib庫
import matplotlib# 從自定義模塊中導入自定義數據集類
from nlp_custom_dataset import CustomDataset
# 從自定義模塊中導入數據整理類
from nlp_data_collation import DataCollation
# 從自定義模塊中導入數據集處理類
from nlp_dataset_processor import DatasetProcessor
# 從自定義模塊中導入邏輯回歸模型類
from nlp_logistic_regression_model import LogisticRegressionModel
# 從自定義模塊中導入樸素貝葉斯分類器類
from nlp_naive_bayes_classifier import NaiveBayesClassifier
# 從自定義模塊中導入TF - IDF轉換器類
from nlp_tfidf_transformer import TFIDFTransformer# 設置matplotlib的后端為tkAgg,以便在圖形界面中顯示圖表
matplotlib.use('tkAgg')
# 定義一個字典config,用于設置matplotlib的字體和符號顯示配置
config = {"font.family": 'serif',  # 設置字體族為襯線字體"mathtext.fontset": 'stix',  # 設置數學文本的字體集為stix"font.serif": 'SimSun',  # 設置襯線字體為宋體'axes.unicode_minus': False  # 解決負號顯示問題
}
# 使用config字典更新matplotlib的全局參數配置
matplotlib.rcParams.update(config)
# 從matplotlib庫中導入pyplot模塊,用于繪制圖表
import matplotlib.pyplot as plt# 定義一個自然語言處理文本分類的類
class NLPTextClassification:# 類的初始化方法,目前為空,不做任何操作def __init__(self):pass# 定義文本分類方法def text_classification(self):# 創建數據集處理對象,用于加載和預處理數據集dataset = DatasetProcessor()# 對數據集中的文本進行分詞處理dataset.tokenize_text()# 打印訓練數據集中第一個樣本的分詞結果print(dataset.train_dataset[0]['tokens'])# 打印標簽到ID的映射關系print(dataset.label_to_id)# 構建詞匯表,設置最小詞頻為3dataset.build_vocabulary(min_frequency=3)# 將分詞結果轉換為對應的詞ID列表dataset.convert_tokens_to_indices()# 打印訓練數據集中第一個樣本的詞ID列表print(dataset.train_dataset[0]['token_indices'])# 初始化訓練輸入特征和訓練標簽列表training_input_features, training_labels = [], []# 初始化測試輸入特征和測試標簽列表testing_input_features, testing_labels = [], []# 遍歷訓練數據集for data in dataset.train_dataset:# 初始化特征向量,長度為詞匯表大小,元素類型為32位整數feature_vector = np.zeros(len(dataset.word_to_id), dtype=np.int32)# 遍歷樣本的詞ID列表for token_index in data['token_indices']:# 統計每個詞的出現次數feature_vector[token_index] += 1# 將特征向量添加到訓練輸入特征列表中training_input_features.append(feature_vector)# 將樣本的標簽添加到訓練標簽列表中training_labels.append(data['label'])# 遍歷測試數據集for data in dataset.test_dataset:# 初始化特征向量,長度為詞匯表大小,元素類型為32位整數feature_vector = np.zeros(len(dataset.word_to_id), dtype=np.int32)# 遍歷樣本的詞ID列表for token_index in data['token_indices']:# 統計每個詞的出現次數feature_vector[token_index] += 1# 將特征向量添加到測試輸入特征列表中testing_input_features.append(feature_vector)# 將樣本的標簽添加到測試標簽列表中testing_labels.append(data['label'])# 將訓練輸入特征和訓練標簽轉換為numpy數組training_input_features, training_labels = np.array(training_input_features), np.array(training_labels)# 將測試輸入特征和測試標簽轉換為numpy數組testing_input_features, testing_labels = np.array(testing_input_features), np.array(testing_labels)# 創建樸素貝葉斯分類器對象,傳入類別數量和詞匯表大小naive_bayes_model = NaiveBayesClassifier(len(dataset.label_to_id), len(dataset.word_to_id))# 重新初始化訓練輸入特征和訓練標簽列表training_input_features, training_labels = [], []# 遍歷訓練數據集for data in dataset.train_dataset:# 將樣本的詞ID列表添加到訓練輸入特征列表中training_input_features.append(data['token_indices'])# 將樣本的標簽添加到訓練標簽列表中training_labels.append(data['label'])# 使用訓練數據對樸素貝葉斯模型進行訓練naive_bayes_model.train_model(training_input_features, training_labels)# 打印前3個類別的先驗概率for i in range(3):print(f'P({dataset.id_to_label[i]}) = {np.exp(naive_bayes_model.prior_probabilities[i])}')# 打印前3個詞在第一個類別下的似然概率for i in range(3):print(f'P({dataset.id_to_word[i]}|{dataset.id_to_label[0]}) = ' + \f'{np.exp(naive_bayes_model.likelihood_probabilities[0, i])}')# 重新初始化測試輸入特征和測試標簽列表testing_input_features, testing_labels = [], []# 遍歷測試數據集for data in dataset.test_dataset:# 將樣本的詞ID列表添加到測試輸入特征列表中testing_input_features.append(data['token_indices'])# 將樣本的標簽添加到測試標簽列表中testing_labels.append(data['label'])# 使用訓練好的樸素貝葉斯模型對測試數據進行預測naive_bayes_predictions = naive_bayes_model.make_predictions(testing_input_features)# 打印前5個測試樣本的預測結果和真實標簽for i, (prediction, label) in enumerate(zip(naive_bayes_predictions, testing_labels)):if i >= 5:breakprint(f'測試樣本:{i}, 預測結果 = {prediction}, 真實類別 = {label}')# 創建TF - IDF轉換器對象,傳入詞匯表大小tfidf_transformer = TFIDFTransformer(len(dataset.word_to_id))# 使用訓練數據擬合TF - IDF轉換器tfidf_transformer.fit_transformer(training_input_features)# 將訓練數據轉換為TF - IDF特征training_features = tfidf_transformer.transform_features(training_input_features)# 將測試數據轉換為TF - IDF特征testing_features = tfidf_transformer.transform_features(testing_input_features)# 創建邏輯回歸模型對象,傳入輸入維度和輸出維度logistic_regression_model = LogisticRegressionModel(len(dataset.word_to_id), len(dataset.label_to_id))# 設置訓練的輪數num_epochs = 50# 設置批量大小batch_size = 128# 設置學習率learning_rate = 1e-3# 設置權重衰減系數weight_decay = 0# 創建自定義訓練數據集對象training_dataset = CustomDataset(training_features, training_labels)# 創建自定義測試數據集對象testing_dataset = CustomDataset(testing_features, testing_labels)# 創建數據整理對象data_collator = DataCollation()# 創建訓練數據加載器,設置批量大小、是否打亂數據和數據整理函數training_dataloader = DataLoader(training_dataset, batch_size=batch_size, shuffle=True,collate_fn=data_collator.collate_batch_data)# 創建測試數據加載器,設置批量大小、不打亂數據和數據整理函數testing_dataloader = DataLoader(testing_dataset, batch_size=batch_size, shuffle=False,collate_fn=data_collator.collate_batch_data)# 創建Adam優化器,傳入邏輯回歸模型的參數、學習率和權重衰減系數optimizer = Adam(logistic_regression_model.parameters(), lr=learning_rate, weight_decay=weight_decay)# 清空邏輯回歸模型的梯度logistic_regression_model.zero_grad()# 將邏輯回歸模型設置為訓練模式logistic_regression_model.train()# 使用trange顯示訓練輪數的進度條with trange(num_epochs, desc='epoch', ncols=60) as progress_bar:# 初始化每一輪的損失列表epoch_losses = []# 遍歷每一輪訓練for epoch in progress_bar:# 將邏輯回歸模型設置為訓練模式logistic_regression_model.train()# 遍歷訓練數據加載器中的每個批次for step, batch in enumerate(training_dataloader):# 計算當前批次的損失loss = logistic_regression_model(**batch)[0]# 更新進度條的描述信息,顯示當前輪數和損失值progress_bar.set_description(f'epoch-{epoch}, loss={loss.item():.4f}')# 反向傳播計算梯度loss.backward()# 更新模型參數optimizer.step()# 清空邏輯回歸模型的梯度logistic_regression_model.zero_grad()# 將當前批次的損失添加到損失列表中epoch_losses.append(loss.item())# 將每一輪的損失列表轉換為numpy數組epoch_losses = np.array(epoch_losses)# 繪制損失曲線plt.plot(range(len(epoch_losses)), epoch_losses)# 設置x軸標簽為訓練輪數plt.xlabel('訓練輪次')# 設置y軸標簽為損失值plt.ylabel('損失(值)')# 顯示損失曲線plt.show()# 將邏輯回歸模型設置為評估模式logistic_regression_model.eval()# 不計算梯度,提高推理速度with torch.no_grad():# 初始化評估損失列表loss_values = []# 遍歷測試數據加載器中的每個批次for batch in testing_dataloader:# 計算當前批次的損失loss = logistic_regression_model(**batch)[0]# 將當前批次的損失添加到評估損失列表中loss_values.append(loss.item())# 打印平均評估損失print(f'評估損失 = {np.mean(loss_values):.4f}')# 初始化邏輯回歸模型的預測結果列表logistic_regression_predictions = []# 將邏輯回歸模型設置為評估模式logistic_regression_model.eval()# 遍歷測試數據加載器中的每個批次for batch in testing_dataloader:# 不計算梯度,提高推理速度with torch.no_grad():# 計算模型的輸出和損失,取預測結果_, predictions = logistic_regression_model(**batch)# 獲取預測結果中概率最大的類別索引predictions = np.argmax(predictions, axis=1)# 將當前批次的預測結果添加到預測結果列表中logistic_regression_predictions.extend(predictions)# 打印前5個測試樣本的邏輯回歸模型預測結果和真實標簽for i, (prediction, label) in enumerate(zip(logistic_regression_predictions, testing_labels)):if i >= 5:breakprint(f'測試樣本:{i}, 預測結果 = {prediction}, 真實類別 = {label}')# 程序入口,當腳本作為主程序運行時執行
if __name__ == "__main__":# 創建自然語言處理文本分類對象nlp_text_classification = NLPTextClassification()# 調用文本分類方法進行文本分類操作nlp_text_classification.text_classification()
運行結果
訓練數據集大小 = 8627 , 測試數據集大小 = 2157
100%|██████████| 8627/8627 [00:20<00:00, 413.90it/s]
100%|██████████| 2157/2157 [00:05<00:00, 413.93it/s]
['地質學', '前沿', '研究', '進展']
{'科學類': 0, '計算機類': 1, '藝術傳媒類': 2, '經管類': 3, '文學類': 4, '歷史類': 5}
unique tokens = 97, total counts = 36235, max freq = 868, min freq = 262
min_freq = 3, min_len = 2, max_size = None, remaining tokens = 93, in-vocab rate = 0.9606181868359321
[80, 36, 37, 38]
P(科學類) = 0.1662223252579112
P(計算機類) = 0.16680190100846182
P(藝術傳媒類) = 0.17016344036165526
P(小說|科學類) = 0.0011441647597254007
P(指南|科學類) = 0.0012987012987012991
P(揭秘|科學類) = 0.001362397820163487
測試樣本:0, 預測結果 = 2, 真實類別 = 2
測試樣本:1, 預測結果 = 2, 真實類別 = 2
測試樣本:2, 預測結果 = 1, 真實類別 = 1
測試樣本:3, 預測結果 = 5, 真實類別 = 5
測試樣本:4, 預測結果 = 2, 真實類別 = 2
epoch-49, loss=0.0274: 100%|█| 50/50 [00:02<00:00, 20.06it/s
評估損失 = 0.0303
測試樣本:0, 預測結果 = 2, 真實類別 = 2
測試樣本:1, 預測結果 = 2, 真實類別 = 2
測試樣本:2, 預測結果 = 1, 真實類別 = 1
測試樣本:3, 預測結果 = 5, 真實類別 = 5
測試樣本:4, 預測結果 = 2, 真實類別 = 2進程已結束,退出代碼為 0

注意:博主采用的訓練集和測試集是用代碼自動生成出來的內容保存到文件中去,目的是為了方便講解功能和展示效果,代碼也是方便給大家參考。請大家根據需求加載自己的訓練集和測試集。

分類結果評價

概念闡述

在自然語言處理(NLP)中,分類結果評價是指使用一系列指標和方法,對文本分類模型的性能和預測效果進行評估和分析,從而衡量模型在將文本正確歸類到不同類別方面的能力。其主要目的包括評估模型的優劣、比較不同模型的性能、發現模型存在的問題以及為模型的改進提供依據。

評價指標

準確率

Accuracy,指分類模型正確預測的樣本數占總樣本數的比例,計算公式為:

$Accuracy = \frac{TP + TN}{TP + TN + FP + FN}$

其中 $TP$(真正例)是指實際為正例且被正確預測為正例的樣本數,$TN$(真反例)是實際為反例且被正確預測為反例的樣本數,$FP$(假正例)是實際為反例但被錯誤預測為正例的樣本數,$FN$(假反例)是實際為正例但被錯誤預測為反例的樣本數。例如,在一個情感分類任務中,總共有100條文本,模型正確分類了80條,那么準確率就是80%

精確率

Precision,也叫查準率,是指在被模型預測為正例的樣本中,真正為正例的比例,計算公式為:

$Precision = \frac{TP}{TP + FP}$

例如,模型預測了30條文本為積極情感,其中實際有25條是積極情感,那么精確率為$\frac{25}{30} \approx 83.3\%$

召回率

Recall,又稱查全率,是指在實際為正例的樣本中,被模型正確預測為正例的比例,計算公式為:

$Recall = \frac{TP}{TP + FN}$

例如,實際有40條積極情感的文本,模型正確預測出了30條,召回率就是$\frac{30}{40} = 75\%$

F1值

F1-score,是精確率召回率調和平均數綜合考慮精確率召回率,計算公式為:

$F1 = \frac{2 \times Precision \times Recall}{Precision + Recall}$

F1值越高,說明模型在精確率和召回率方面的綜合表現越好。

宏平均

Macro-average,對于多分類問題,先分別計算每個類別的精確率召回率F1值,然后對這些算術平均值,得到宏平均精確率、宏平均召回率和宏平均F1值。它給予每個類別相同的權重,能夠反映模型在各個類別上的平均性能。

微平均

Micro-average,在多分類問題中,先計算所有類別的真正例假正例假反例總數,然后基于這些總數計算精確率召回率F1值。它更關注整體的分類性能,尤其是在樣本不均衡的情況下,能夠突出模型對主要類別的分類能力。

其他

除了這些指標外,還有一些其他的評價方法和指標,如混淆矩陣(Confusion Matrix),可以直觀地展示模型在各個類別上的分類情況;ROC曲線(Receiver Operating Characteristic Curve)AUC(Area Under the Curve),用于評估模型在不同閾值下的性能等。通過綜合運用這些評價指標和方法,可以全面、客觀地評價自然語言處理中的分類結果。 ?

代碼演示

接下來的代碼將運用已經完成訓練流程、具備預測能力的模型,針對測試集展開預測工作,并且會對預測所得到的分類結果進行報告。

完整代碼

nlp_evaluation_metrics.py

# 導入用于數值計算的numpy庫
import numpy as np# 定義一個評估指標類,用于計算評估模型性能的指標
class EvaluationMetrics:# 類的初始化方法,目前為空實現def __init__(self):pass# 定義計算微平均F1值的方法,接收數據集、預測結果和真實標簽作為參數def calculate_micro_f1(self, dataset, predictions, true_labels):# 計算預測結果與真實標簽相等的數量,即真正例的數量true_positives = np.sum(predictions == true_labels)# 初始化假負例和假正例的數量為0false_negatives = false_positives = 0# 遍歷數據集中的每個類別for i in range(len(dataset.label_to_id)):# 累加假負例的數量,即預測為該類但真實不是該類的數量false_negatives += np.sum((predictions == i) & (true_labels != i))# 累加假正例的數量,即預測不是該類但真實是該類的數量false_positives += np.sum((predictions != i) & (true_labels == i))# 計算精確率,即真正例在真正例和假正例總和中的比例precision = true_positives / (true_positives + false_positives)# 計算召回率,即真正例在真正例和假負例總和中的比例recall = true_positives / (true_positives + false_negatives)# 計算微平均F1值,是精確率和召回率的調和平均值f1_score = 2 * precision * recall / (precision + recall)# 返回計算得到的微平均F1值return f1_score# 定義計算宏平均F1值的方法,接收數據集、預測結果和真實標簽作為參數def calculate_macro_f1(self, dataset, predictions, true_labels):# 初始化一個空列表,用于存儲每個類別的F1值f_scores = []# 遍歷數據集中的每個類別for i in range(len(dataset.label_to_id)):# 計算當前類別的真正例數量true_positives = np.sum((predictions == i) & (true_labels == i))# 計算當前類別的假負例數量false_negatives = np.sum((predictions == i) & (true_labels != i))# 計算當前類別的假正例數量false_positives = np.sum((predictions != i) & (true_labels == i))# 計算當前類別的精確率precision = true_positives / (true_positives + false_positives)# 計算當前類別的召回率recall = true_positives / (true_positives + false_negatives)# 計算當前類別的F1值f1_score = 2 * precision * recall / (precision + recall)# 將當前類別的F1值添加到列表中f_scores.append(f1_score)# 計算所有類別F1值的平均值,即宏平均F1值return np.mean(f_scores)

nlp_text_classification.py

# 導入用于數值計算的numpy庫
import numpy as np
# 導入深度學習框架PyTorch
import torch
# 從torch.utils.data模塊導入DataLoader類,用于批量加載數據
from torch.utils.data import DataLoader
# 從torch.optim模塊導入Adam優化器,用于優化模型參數
from torch.optim import Adam
# 從tqdm模塊導入trange函數,用于顯示進度條
from tqdm import trange
# 導入用于數據可視化的matplotlib庫
import matplotlib# 從自定義模塊中導入自定義數據集類
from nlp_custom_dataset import CustomDataset
# 從自定義模塊中導入數據整理類
from nlp_data_collation import DataCollation
# 從自定義模塊中導入數據集處理類
from nlp_dataset_processor import DatasetProcessor
# 從自定義模塊中導入評估指標類
from nlp_evaluation_metrics import EvaluationMetrics
# 從自定義模塊中導入邏輯回歸模型類
from nlp_logistic_regression_model import LogisticRegressionModel
# 從自定義模塊中導入樸素貝葉斯分類器類
from nlp_naive_bayes_classifier import NaiveBayesClassifier
# 從自定義模塊中導入TF - IDF轉換器類
from nlp_tfidf_transformer import TFIDFTransformer# 設置matplotlib的后端為tkAgg,以便在圖形界面中顯示圖表
matplotlib.use('tkAgg')
# 定義一個字典config,用于設置matplotlib的字體和符號顯示配置
config = {"font.family": 'serif',  # 設置字體族為襯線字體"mathtext.fontset": 'stix',  # 設置數學文本的字體集為stix"font.serif": 'SimSun',  # 設置襯線字體為宋體'axes.unicode_minus': False  # 解決負號顯示問題
}
# 使用config字典更新matplotlib的全局參數配置
matplotlib.rcParams.update(config)
# 從matplotlib庫中導入pyplot模塊,用于繪制圖表
import matplotlib.pyplot as plt# 定義一個自然語言處理文本分類的類
class NLPTextClassification:# 類的初始化方法,目前為空,不做任何操作def __init__(self):pass# 定義文本分類方法def text_classification(self):# 創建數據集處理對象,用于加載和預處理數據集dataset = DatasetProcessor()# 對數據集中的文本進行分詞處理dataset.tokenize_text()# 打印訓練數據集中第一個樣本的分詞結果print(dataset.train_dataset[0]['tokens'])# 打印標簽到ID的映射關系print(dataset.label_to_id)# 構建詞匯表,設置最小詞頻為3dataset.build_vocabulary(min_frequency=3)# 將分詞結果轉換為對應的詞ID列表dataset.convert_tokens_to_indices()# 打印訓練數據集中第一個樣本的詞ID列表print(dataset.train_dataset[0]['token_indices'])# 初始化訓練輸入特征和訓練標簽列表training_input_features, training_labels = [], []# 初始化測試輸入特征和測試標簽列表testing_input_features, testing_labels = [], []# 遍歷訓練數據集for data in dataset.train_dataset:# 初始化特征向量,長度為詞匯表大小,元素類型為32位整數feature_vector = np.zeros(len(dataset.word_to_id), dtype=np.int32)# 遍歷樣本的詞ID列表for token_index in data['token_indices']:# 統計每個詞的出現次數feature_vector[token_index] += 1# 將特征向量添加到訓練輸入特征列表中training_input_features.append(feature_vector)# 將樣本的標簽添加到訓練標簽列表中training_labels.append(data['label'])# 遍歷測試數據集for data in dataset.test_dataset:# 初始化特征向量,長度為詞匯表大小,元素類型為32位整數feature_vector = np.zeros(len(dataset.word_to_id), dtype=np.int32)# 遍歷樣本的詞ID列表for token_index in data['token_indices']:# 統計每個詞的出現次數feature_vector[token_index] += 1# 將特征向量添加到測試輸入特征列表中testing_input_features.append(feature_vector)# 將樣本的標簽添加到測試標簽列表中testing_labels.append(data['label'])# 將訓練輸入特征和訓練標簽轉換為numpy數組training_input_features, training_labels = np.array(training_input_features), np.array(training_labels)# 將測試輸入特征和測試標簽轉換為numpy數組testing_input_features, testing_labels = np.array(testing_input_features), np.array(testing_labels)# 創建樸素貝葉斯分類器對象,傳入類別數量和詞匯表大小naive_bayes_model = NaiveBayesClassifier(len(dataset.label_to_id), len(dataset.word_to_id))# 重新初始化訓練輸入特征和訓練標簽列表training_input_features, training_labels = [], []# 遍歷訓練數據集for data in dataset.train_dataset:# 將樣本的詞ID列表添加到訓練輸入特征列表中training_input_features.append(data['token_indices'])# 將樣本的標簽添加到訓練標簽列表中training_labels.append(data['label'])# 使用訓練數據對樸素貝葉斯模型進行訓練naive_bayes_model.train_model(training_input_features, training_labels)# 打印前3個類別的先驗概率for i in range(3):print(f'P({dataset.id_to_label[i]}) = {np.exp(naive_bayes_model.prior_probabilities[i])}')# 打印前3個詞在第一個類別下的似然概率for i in range(3):print(f'P({dataset.id_to_word[i]}|{dataset.id_to_label[0]}) = ' + \f'{np.exp(naive_bayes_model.likelihood_probabilities[0, i])}')# 重新初始化測試輸入特征和測試標簽列表testing_input_features, testing_labels = [], []# 遍歷測試數據集for data in dataset.test_dataset:# 將樣本的詞ID列表添加到測試輸入特征列表中testing_input_features.append(data['token_indices'])# 將樣本的標簽添加到測試標簽列表中testing_labels.append(data['label'])# 使用訓練好的樸素貝葉斯模型對測試數據進行預測naive_bayes_predictions = naive_bayes_model.make_predictions(testing_input_features)# 打印前5個測試樣本的預測結果和真實標簽for i, (prediction, label) in enumerate(zip(naive_bayes_predictions, testing_labels)):if i >= 5:breakprint(f'測試樣本:{i}, 預測結果 = {prediction}, 真實類別 = {label}')# 創建TF - IDF轉換器對象,傳入詞匯表大小tfidf_transformer = TFIDFTransformer(len(dataset.word_to_id))# 使用訓練數據擬合TF - IDF轉換器tfidf_transformer.fit_transformer(training_input_features)# 將訓練數據轉換為TF - IDF特征training_features = tfidf_transformer.transform_features(training_input_features)# 將測試數據轉換為TF - IDF特征testing_features = tfidf_transformer.transform_features(testing_input_features)# 創建邏輯回歸模型對象,傳入輸入維度和輸出維度logistic_regression_model = LogisticRegressionModel(len(dataset.word_to_id), len(dataset.label_to_id))# 設置訓練的輪數num_epochs = 50# 設置批量大小batch_size = 128# 設置學習率learning_rate = 1e-3# 設置權重衰減系數weight_decay = 0# 創建自定義訓練數據集對象training_dataset = CustomDataset(training_features, training_labels)# 創建自定義測試數據集對象testing_dataset = CustomDataset(testing_features, testing_labels)# 創建數據整理對象data_collator = DataCollation()# 創建訓練數據加載器,設置批量大小、是否打亂數據和數據整理函數training_dataloader = DataLoader(training_dataset, batch_size=batch_size, shuffle=True,collate_fn=data_collator.collate_batch_data)# 創建測試數據加載器,設置批量大小、不打亂數據和數據整理函數testing_dataloader = DataLoader(testing_dataset, batch_size=batch_size, shuffle=False,collate_fn=data_collator.collate_batch_data)# 創建Adam優化器,傳入邏輯回歸模型的參數、學習率和權重衰減系數optimizer = Adam(logistic_regression_model.parameters(), lr=learning_rate, weight_decay=weight_decay)# 清空邏輯回歸模型的梯度logistic_regression_model.zero_grad()# 將邏輯回歸模型設置為訓練模式logistic_regression_model.train()# 使用trange顯示訓練輪數的進度條with trange(num_epochs, desc='epoch', ncols=60) as progress_bar:# 初始化每一輪的損失列表epoch_losses = []# 遍歷每一輪訓練for epoch in progress_bar:# 將邏輯回歸模型設置為訓練模式logistic_regression_model.train()# 遍歷訓練數據加載器中的每個批次for step, batch in enumerate(training_dataloader):# 計算當前批次的損失loss = logistic_regression_model(**batch)[0]# 更新進度條的描述信息,顯示當前輪數和損失值progress_bar.set_description(f'epoch-{epoch}, loss={loss.item():.4f}')# 反向傳播計算梯度loss.backward()# 更新模型參數optimizer.step()# 清空邏輯回歸模型的梯度logistic_regression_model.zero_grad()# 將當前批次的損失添加到損失列表中epoch_losses.append(loss.item())# 將每一輪的損失列表轉換為numpy數組epoch_losses = np.array(epoch_losses)# 繪制損失曲線plt.plot(range(len(epoch_losses)), epoch_losses)# 設置x軸標簽為訓練輪數plt.xlabel('訓練輪次')# 設置y軸標簽為損失值plt.ylabel('損失(值)')# 顯示損失曲線plt.show()# 將邏輯回歸模型設置為評估模式logistic_regression_model.eval()# 不計算梯度,提高推理速度with torch.no_grad():# 初始化評估損失列表loss_values = []# 遍歷測試數據加載器中的每個批次for batch in testing_dataloader:# 計算當前批次的損失loss = logistic_regression_model(**batch)[0]# 將當前批次的損失添加到評估損失列表中loss_values.append(loss.item())# 打印平均評估損失print(f'評估損失 = {np.mean(loss_values):.4f}')# 初始化邏輯回歸模型的預測結果列表logistic_regression_predictions = []# 將邏輯回歸模型設置為評估模式logistic_regression_model.eval()# 遍歷測試數據加載器中的每個批次for batch in testing_dataloader:# 不計算梯度,提高推理速度with torch.no_grad():# 計算模型的輸出和損失,取預測結果_, predictions = logistic_regression_model(**batch)# 獲取預測結果中概率最大的類別索引predictions = np.argmax(predictions, axis=1)# 將當前批次的預測結果添加到預測結果列表中logistic_regression_predictions.extend(predictions)# 打印前5個測試樣本的邏輯回歸模型預測結果和真實標簽for i, (prediction, label) in enumerate(zip(logistic_regression_predictions, testing_labels)):if i >= 5:breakprint(f'測試樣本:{i}, 預測結果 = {prediction}, 真實類別 = {label}')# 將測試標簽轉換為numpy數組testing_labels = np.array(testing_labels)# 將樸素貝葉斯模型的預測結果轉換為numpy數組naive_bayes_predictions = np.array(naive_bayes_predictions)# 將邏輯回歸模型的預測結果轉換為numpy數組logistic_regression_predictions = np.array(logistic_regression_predictions)# 創建評估指標對象evaluation = EvaluationMetrics()# 打印樸素貝葉斯模型的微平均F1值和宏平均F1值print(f'NB: micro-f1 = {evaluation.calculate_micro_f1(dataset, naive_bayes_predictions, testing_labels)}, ' + f'macro-f1 = {evaluation.calculate_macro_f1(dataset, naive_bayes_predictions, testing_labels)}')# 打印邏輯回歸模型的微平均F1值和宏平均F1值print(f'LR: micro-f1 = {evaluation.calculate_micro_f1(dataset, logistic_regression_predictions, testing_labels)}, ' + f'macro-f1 = {evaluation.calculate_macro_f1(dataset, logistic_regression_predictions, testing_labels)}')# 程序入口,當腳本作為主程序運行時執行
if __name__ == "__main__":# 創建自然語言處理文本分類對象nlp_text_classification = NLPTextClassification()# 調用文本分類方法進行文本分類操作nlp_text_classification.text_classification()
運行結果
NB: micro-f1 = 1.0, macro-f1 = 1.0
LR: micro-f1 = 1.0, macro-f1 = 1.0進程已結束,退出代碼為 0

注意:博主采用的訓練集和測試集是用代碼自動生成出來的內容保存到文件中去,目的是為了方便講解功能和展示效果,代碼也是方便給大家參考。請大家根據需求加載自己的訓練集和測試集。

結束

好了,以上就是本次關于自然語言處理文本分類的全部內容了。從數據集的預處理、特征工程的構建,到樸素貝葉斯和邏輯回歸等不同模型的應用,再到分類結果的評估,我們全面地探討了文本分類任務的各個關鍵環節。

在這個過程中,我們看到了不同模型的優勢與局限。樸素貝葉斯算法憑借其簡單高效,在一些場景下能取得不錯的效果;而邏輯回歸模型借助強大的深度學習框架PyTorch,通過自動求導等功能,實現了更為精細的參數優化。

當然,自然語言處理文本分類領域仍有許多值得深入研究和探索的方向。比如如何進一步提升模型在小樣本、不均衡數據集上的性能,以及怎樣更好地融合多種模型的優點來構建更強大的分類器。希望今天的分享能為大家在自然語言處理的學習和實踐中提供一些思路和幫助。

那么本次分享就到這里了。最后,博主還是那句話:請大家多去大膽的嘗試和使用,成功總是在不斷的失敗中試驗出來的,敢于嘗試就已經成功了一半。如果大家對博主分享的內容感興趣或有幫助,請點贊和關注。大家的點贊和關注是博主持續分享的動力🤭,博主也希望讓更多的人學習到新的知識。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/897382.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/897382.shtml
英文地址,請注明出處:http://en.pswp.cn/news/897382.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PDFMathTranslate安裝使用

PDF全文翻譯&#xff01;&#xff01;&#xff01;&#xff01; PDFMathTranslate安裝使用 它是個啥 PDFMathTranslate 可能是一個用于 PDF 文件的數學公式翻譯 工具。它可能包含以下功能&#xff1a; 提取 PDF 內的數學公式 將數學公式轉換成 LaTeX 代碼 翻譯數學公式的內…

【由技及道】量子構建交響曲:Jenkinsfile流水線的十一維編程藝術【人工智障AI2077的開發日志008】

摘要&#xff1a;當代碼提交觸發時空漣漪&#xff0c;當構建流水線穿越量子維度——歡迎來到自動化構建的終極形態。本文將揭示如何用Jenkinsfile編寫量子構建樂章&#xff0c;讓每次代碼提交都成為跨維度交響樂的音符。 動機&#xff1a;構建系統的量子哲學 “主人啊&#xff…

K8S高可用集群-小白學習之二進制部署(ansible+shell)

一.K8S高可用集群配置概述 序言:本文從一個小白的視角進行K8S的研究和部署,采用二進制的方式是為了更清楚了分解部署流程及了解這個集群是怎么運作的,加上ansible+shell是方便在這個過程中,遇到了問題,我們可以不斷的快速重復部署來測試和研究問題的所在點,本文的架構圖…

【自學筆記】R語言基礎知識點總覽-持續更新

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 R語言基礎知識點總覽1. R語言簡介2. R語言安裝與環境配置3. R語言基礎語法3.1 數據類型3.2 向量與矩陣3.3 數據框與列表 4. 控制結構4.1 條件語句4.2 循環結構 5. 函…

【編譯器】VSCODE搭建ESP32-C3

【編譯器】VSCODE搭建ESP32-C3 文章目錄 [TOC](文章目錄) 前言一、下載配置二、編譯三、燒錄四、參考資料總結 前言 使用工具&#xff1a; 1. 提示&#xff1a;以下是本篇文章正文內容&#xff0c;下面案例可供參考 一、下載配置 安裝IDF&#xff0c;打開例程 二、編譯 三…

通義千問本地配置并實現微調

通義千問本地配置并實現微調 最小Qwen模型大小942mb from modelscope import snapshot_download model_dir = snapshot_download(“qwen/Qwen2.5-0.5B”, cache_dir=“./models2.5”) Qwen2.5-0.5B:942MB from modelscope import snapshot_download model_dir = snapshot_d…

Magento2根據圖片文件包導入產品圖片

圖片包給的圖片文件是子產品的圖片&#xff0c;如下圖&#xff1a;A104255是主產品的sku <?php/*** 根據圖片包導入產品圖片&#xff0c;包含子產品和主產品* 子產品是作為主圖&#xff0c;主產品是作為附加圖片*/use Magento\Framework\App\Bootstrap;include(../app/boot…

力扣146 - LRU緩存

視頻講解 哈希 雙向鏈表 為什么要用雙向鏈表&#xff1f; 快速刪除節點&#xff08;O(1&#xff09;&#xff09; 如果是單鏈表的話&#xff0c;刪除一個節點時&#xff0c;需要從頭遍歷&#xff0c;找到前驅節點&#xff0c;才能修改 prev->next&#xff0c;導致 O(n)…

考研408

是否需要考研&#xff1f; 考研前期準備 目標院校 每年9月10月才會公布 考試時長3小時 數據結構 1.時間復雜度選擇題計算 2.順序表鏈表特點;指針、結構體語法&#xff0c;鏈表結點定義&#xff0c;鏈表頭結點與頭指針,常見的五種鏈 表&#xff0c;鏈表的插入刪除操作;順…

nodejs使用WebSocket實現聊天效果

在nodejs中使用WebSocket實現聊天效果&#xff08;簡易實現&#xff09; 安裝 npm i ws 實現 創建 server.js /*** 創建一個 WebSocket 服務器&#xff0c;監聽指定端口&#xff0c;并處理客戶端連接和消息。** param {Object} WebSocket - 引入的 WebSocket 模塊&#xff0c…

Web網頁制作(靜態網頁):千年之戀

一、是用的PyCharm來寫的代碼 二、代碼中所用到的知識點&#xff08;無 js&#xff09; 這段HTML代碼展示了一個簡單的注冊頁面&#xff0c;包含了多個HTML元素和CSS樣式的應用。 這段HTML代碼展示了一個典型的注冊頁面&#xff0c;包含了常見的HTML元素和表單控件。通過CSS樣…

操作系統知識點23

1.實時操作系統的主要設計目標&#xff1a;在嚴格時間氛圍內對外部請求做出反應。 2.當用戶程序正在處理器上運行時&#xff0c;若此刻取到了一條特權指令&#xff0c;則處理器將停止執行該指令&#xff0c;并產生一個“非法操作”的事件 3.某網絡監控系統中。多個被授權的用…

CSS—網格布局Grid

網格布局grid 提供了帶有行和列的基于網格的布局系統&#xff0c;無需使用浮動和定位。 當 HTML 元素的 display 屬性設置為 grid 或 inline-grid 時&#xff0c;它就會成為網格容器。 更多布局模式可以參考之前的博客&#xff1a; ??????CSS—flex布局、過渡transit…

如何將本地已有的倉庫上傳到gitee (使用UGit)

1、登錄Gitee。 2、點擊個人頭像旁邊的加號&#xff0c;選擇新建倉庫&#xff1a; 3、填寫倉庫相關信息 4、復制Gitee倉庫的地址 5、綁定我們的本地倉庫與遠程倉庫 6、將本地倉庫發布&#xff08;推送&#xff09;到遠程倉庫&#xff1a; 注意到此處報錯&#xff0c;有關于…

【JAVA面試題】Spring、Spring MVC、Spring Boot、Spring Cloud的區別與聯系

在Java生態中&#xff0c;Spring框架及其衍生技術&#xff08;如Spring MVC、Spring Boot、Spring Cloud&#xff09;是開發企業級應用的核心工具。它們在功能、定位和使用場景上各有側重&#xff0c;但又緊密聯系。本文將詳細解析它們的區別與聯系&#xff0c;幫助你在面試中更…

【Linux系統編程】初識系統編程

目錄 一、什么是系統編程1. 系統編程的定義2. 系統編程的特點3. 系統編程的應用領域4. 系統編程的核心概念5. 系統編程的工具和技術 二、操作系統四大基本功能1. 進程管理&#xff08;Process Management&#xff09;2. 內存管理&#xff08;Memory Management&#xff09;3. 文…

Web基礎:HTML快速入門

HTML基礎語法 HTML&#xff08;超文本標記語言&#xff09; 是用于創建網頁內容的 標記語言&#xff0c;通過定義頁面的 結構和內容 來告訴瀏覽器如何呈現網頁。 超文本&#xff08;Hypertext&#xff09; 是一種通過 鏈接&#xff08;Hyperlinks&#xff09; 將不同文本、圖像…

Linux基本操作指令3

1、wget: 這是一個用于從網絡上下載文件的命令行工具。它支持 HTTP、HTTPS 和 FTP 協議。 wget http://download.qt.io/archive/qt/5.12/5.12.9/qt-opensource-linux-x64-5.12.9.run 2、下載完成后&#xff0c;你可以通過以下命令使文件可執行并運行安裝程序&#xff1a; ch…

Deeplabv3+改進3:在主干網絡中添加NAMAttention|助力漲點!

??【DeepLabv3+改進專欄!探索語義分割新高度】 ?? 你是否在為圖像分割的精度與效率發愁? ?? 本專欄重磅推出: ? 獨家改進策略:融合注意力機制、輕量化設計與多尺度優化 ? 即插即用模塊:ASPP+升級、解碼器 PS:訂閱專欄提供完整代碼 目錄 論文簡介 步驟一 步驟二…

二分查找(遞歸和迭代)– Python

1. 使用遞歸進行二分查找的 Python 程序 創建一個遞歸函數&#xff0c;并將搜索空間的 mid 與 key 進行比較。根據結果&#xff0c;要么返回找到鍵的索引&#xff0c;要么調用下一個搜索空間的遞歸函數。 # 用于遞歸二進制搜索的 Python 3 程序。 # 在注釋中可以找到對舊版 Pyt…