樸素貝葉斯( NB )是一種簡(jiǎn)單但功能強(qiáng)大的概率分類技術(shù),具有良好的并行性,可以擴(kuò)展到大規(guī)模數(shù)據(jù)集。
如果您一直從事數(shù)據(jù)科學(xué)中的文本處理任務(wù),您就會(huì)知道 機(jī)器學(xué)習(xí) 模型可能需要很長(zhǎng)時(shí)間來(lái)訓(xùn)練。在這些模型上使用 GPU 加速計(jì)算通常可以顯著提高時(shí)間性能, NB 分類器也不例外。
通過(guò)使用 CUDA 加速操作,根據(jù)使用的 NB 模型,我們實(shí)現(xiàn)了從 5 到 20 倍的性能提升。對(duì)稀疏數(shù)據(jù)的智能利用使其中一個(gè)模型的速度提高了 120 倍。
在本文中,我們介紹了 RAPIDS cuML 中 NB 實(shí)現(xiàn)的最新升級(jí),并將其與 Scikit-learn 在 CPU 上的實(shí)現(xiàn)進(jìn)行了比較。我們提供基準(zhǔn)測(cè)試來(lái)演示性能優(yōu)勢(shì),并通過(guò)算法的每個(gè)支持變量的簡(jiǎn)單示例來(lái)幫助您確定哪個(gè)最適合您的用例。
什么是樸素貝葉斯?
NB 使用 Bayes’ theorem (圖 1 )對(duì)如下所示的條件概率分布進(jìn)行建模,以預(yù)測(cè)給定一些輸入特征( x )的標(biāo)簽或類別( y )。在其最簡(jiǎn)單的形式中,貝葉斯定理使用特征和可能標(biāo)簽之間的聯(lián)合概率以及特征在所有可能標(biāo)簽上出現(xiàn)的邊際概率來(lái)計(jì)算條件概率。
圖 1.貝葉斯定理表示由一組特征( x )產(chǎn)生的標(biāo)簽( y )的概率作為條件概率。它是使用每個(gè)標(biāo)簽與特征集發(fā)生的聯(lián)合概率和特征在所有可能標(biāo)簽上發(fā)生的邊際概率來(lái)計(jì)算的
NB 算法在文本分類用例中表現(xiàn)良好。它們通常用于過(guò)濾垃圾郵件等任務(wù);預(yù)測(cè)推特、網(wǎng)頁(yè)、博客帖子、用戶評(píng)分和論壇帖子的類別和情感;或?qū)ξ臋n和網(wǎng)頁(yè)進(jìn)行排名。
NB 算法通過(guò)使每個(gè)特征(例如,輸入向量 x 中的每列)在統(tǒng)計(jì)上獨(dú)立于所有其他特征來(lái)簡(jiǎn)化條件概率分布 naive assumption 。這使得該算法很棒,因?yàn)檫@種天真的假設(shè)提高了算法的并行化能力。此外,計(jì)算特征和類標(biāo)簽之間簡(jiǎn)單共生概率的一般方法使模型能夠進(jìn)行增量訓(xùn)練,支持不適合內(nèi)存的數(shù)據(jù)集。
NB 有幾種變體,它們對(duì)各種類別標(biāo)簽的聯(lián)合分布或共同出現(xiàn)的特征進(jìn)行了某些假設(shè)。
樸素貝葉斯假設(shè)
為了預(yù)測(cè)未知輸入特征集的類別,關(guān)于聯(lián)合分布的不同假設(shè)使算法具有幾種不同的變體,該算法通過(guò)學(xué)習(xí)不同概率分布的參數(shù)來(lái)建模特征分布。
表 1 模擬了一個(gè)簡(jiǎn)單的文檔/術(shù)語(yǔ)矩陣,該矩陣可以來(lái)自文本文檔集合。列中的術(shù)語(yǔ)代表一個(gè)詞匯表。一個(gè)簡(jiǎn)單的詞匯表可能會(huì)將一個(gè)文檔分解為一組在所有文檔中出現(xiàn)的唯一單詞。
表 1 。 包含沿行文檔和沿列出現(xiàn)在每個(gè)文檔中的詞匯的文檔/術(shù)語(yǔ)矩陣
在表 1 中,每個(gè)元素可以是一個(gè)計(jì)數(shù),如此處所示, 0 或 1 表示特征的存在,或其他一些值,如在整個(gè)文檔集上出現(xiàn)的每個(gè)項(xiàng)的比率、擴(kuò)散或離散度。
在實(shí)踐中,滑動(dòng)窗口通常在整個(gè)文檔或術(shù)語(yǔ)上運(yùn)行,將它們進(jìn)一步劃分為小塊的單詞序列,稱為 n-grams 。對(duì)于下圖的第一個(gè)文檔, 2-gram (或 bigram )將是“ I love ”和“ love dogs ”。這類數(shù)據(jù)集中的詞匯通常會(huì)顯著增大并變得稀疏。預(yù)處理步驟通常在詞匯表上執(zhí)行,以過(guò)濾噪聲,例如,通過(guò)刪除大多數(shù)文檔中出現(xiàn)的常見(jiàn)術(shù)語(yǔ)。
將文檔轉(zhuǎn)換為文檔項(xiàng)矩陣的過(guò)程稱為矢量化。有一些工具可以加速這個(gè)過(guò)程,例如 CountVectorizer cuML 中的 CountVectorizer 、 TdfidfVectorizer 或 RAPIDS 估計(jì)器對(duì)象。
多項(xiàng)式和伯努利分布
表 1 表示一組文檔,這些文檔已矢量化為術(shù)語(yǔ)計(jì)數(shù),結(jié)果矩陣中的每個(gè)元素表示特定單詞在其相應(yīng)文檔中出現(xiàn)的次數(shù)。這種簡(jiǎn)單的表示方法可以有效地用于分類任務(wù)。
由于特征代表頻率分布,多項(xiàng)式樸素貝葉斯變體可以有效地將特征及其相關(guān)類別的聯(lián)合分布建模為多項(xiàng)式分布。
可以通過(guò)合并色散度量來(lái)增強(qiáng)每個(gè)項(xiàng)的頻率分布,例如項(xiàng)頻率逆文檔頻率( TF-IDF ),它考慮了每個(gè)項(xiàng)中出現(xiàn)的文檔數(shù)量。這可以通過(guò)對(duì)出現(xiàn)在較少文檔中的術(shù)語(yǔ)賦予更多權(quán)重來(lái)顯著提高性能,從而提高其識(shí)別能力。
雖然多項(xiàng)式分布在直接與項(xiàng)頻率一起使用時(shí)效果很好,但它也被證明在分?jǐn)?shù)值上有很好的性能,如 TF-IDF 值。多項(xiàng)式樸素貝葉斯變體涵蓋了大量用例,因此往往是使用最廣泛的。類似的變體是伯努利樸素貝葉斯,它模擬每個(gè)項(xiàng)的簡(jiǎn)單出現(xiàn),而不是它們的頻率,從而得到 0 和 1 的矩陣(伯努利分布)。
不等階級(jí)分布
在現(xiàn)實(shí)世界中,經(jīng)常會(huì)發(fā)現(xiàn)不平衡的數(shù)據(jù)集。例如,您可能有有限的垃圾郵件和惡意活動(dòng)的數(shù)據(jù)樣本,但有豐富的正常和良性樣本。
補(bǔ)碼樸素貝葉斯變體通過(guò)在訓(xùn)練期間為每個(gè)類使用聯(lián)合分布的補(bǔ)碼,例如,在所有其他類的樣本中出現(xiàn)特征的次數(shù),有助于減少不平等類分布的影響。
分類分布
你也可以為你的每一個(gè)特征創(chuàng)建存儲(chǔ)箱,可能通過(guò)將一些頻率量化到多個(gè)存儲(chǔ)桶中,使得 0-5 的頻率進(jìn)入存儲(chǔ)桶 0 , 6-10 的頻率進(jìn)入存儲(chǔ)桶 1 ,等等。
另一種選擇是將幾個(gè)術(shù)語(yǔ)合并到一個(gè)功能中,可能是為“動(dòng)物”和“假日”創(chuàng)建桶,其中“動(dòng)物”可能有三個(gè)桶,零個(gè)用于貓科動(dòng)物,一個(gè)用于犬科動(dòng)物,兩個(gè)用于嚙齒動(dòng)物。“假日”可能有兩個(gè)桶,零用于個(gè)人假日,如生日或結(jié)婚紀(jì)念日,一個(gè)用于聯(lián)邦假日。
分類樸素貝葉斯 變體假設(shè)特征遵循分類分布。樸素假設(shè)在這種情況下效果很好,因?yàn)樗试S每個(gè)特征都有一組不同的類別,并且它使用(您猜對(duì)了)分類分布對(duì)聯(lián)合分布進(jìn)行建模。
連續(xù)分布
最后,當(dāng)特征是連續(xù)的時(shí),高斯樸素貝葉斯 變體非常有效,可以假設(shè)每個(gè)類別中的特征分布可以用高斯分布建模,即用簡(jiǎn)單的均值和方差。
雖然這種變體在 TF-IDF 歸一化后可能在某些數(shù)據(jù)集上表現(xiàn)出良好的性能,但它在一般機(jī)器學(xué)習(xí)數(shù)據(jù)集上也很有用。
表 2.不同 NB 算法的比較 s
真實(shí)世界的端到端示例
如表 2 所示,為了證明每種算法變體的優(yōu)點(diǎn),我們逐步瀏覽了每種算法變體的示例筆記本。有關(guān)包含所有示例的全面端到端筆記本,請(qǐng)參閱 news_aggregator_a100.ipynb 。
我們使用新聞聚合器數(shù)據(jù)集來(lái)演示 NB 變體的性能。該數(shù)據(jù)集可從 Kaggle 公開(kāi)獲取,由來(lái)自多個(gè)新聞來(lái)源的 422K 條新聞標(biāo)題組成。每個(gè)標(biāo)題都標(biāo)有四個(gè)可能的標(biāo)簽之一:商業(yè)、科技、娛樂(lè)和健康。使用 cuDF RAPIDS 將數(shù)據(jù)直接加載到 GPU 上,并繼續(xù)執(zhí)行針對(duì)每個(gè) NB 變體的預(yù)處理步驟。
高斯樸素貝葉斯
從高斯樸素貝葉斯 , 開(kāi)始,我們運(yùn)行 TD-IDF 矢量器將文本數(shù)據(jù)轉(zhuǎn)換為可用于訓(xùn)練的實(shí)值向量。
通過(guò)指定ngram_range=(1,3),我們表示我們將學(xué)習(xí)單字以及 2-3-gram 。這顯著增加了要學(xué)習(xí)的術(shù)語(yǔ)或功能的數(shù)量,從 15K 個(gè)單詞增加到 180 萬(wàn)個(gè)組合。由于大多數(shù)術(shù)語(yǔ)不會(huì)出現(xiàn)在大多數(shù)標(biāo)題中,因此生成的矩陣稀疏,許多值等于零。 cuML 支持特殊結(jié)構(gòu)來(lái)表示這樣的數(shù)據(jù)。
Gaussian NB
Transform the text through a TF-IDF vectorizer and iterate through the dataset to do multiple partial fits of Gaussian naive Bayes.
vec = TfidfVectorizer(stop_words='english', ngram_range=(1,3), min_df=5)
x_train = vec.fit_transform(X_train_text)
x_test = vec.transform(X_test_text)
def dataset_traversal(X, Y, partial_function):
chunk_size = 12000
classes = cp.unique(Y)
lower = 0
for upper in iter(range(chunk_size, X.shape[0], chunk_size)):
partial_function(X[lower:upper], Y[lower:upper], classes)
lower = upper
partial_function(X[upper:], Y[upper:], classes)
mnb = GaussianNB()
%time dataset_traversal(x_train,\
y_train,\
lambda x,y, c: mnb.partial_fit(x, y, c))
%time dataset_traversal(x_test,\
y_test,\
lambda x, y, c: print(mnb.score(x, y)))
CPU times: user 12.3 s, sys: 2.23 s, total: 14.5 s Wall time: 22 s 0.8769999742507935 0.8840000033378601 0.878083348274231 0.8805833458900452 0.8756666779518127 0.8796666860580444 0.8786666393280029 0.8777499794960022 0.8823529481887817 CPU times: user 4.36 s, sys: 2.74 s, total: 7.1 s Wall time: 22.8 s
vec = TfidfVectorizer(stop_words='english', ngram_range=(1,3), min_df=5)
x_train = vec.fit_transform(X_train_text)
x_test = vec.transform(X_test_text)
x_train_np, x_test_np = x_train.get(), x_test.get()
y_train_np, y_test_np = y_train.to_numpy(), y_test.to_numpy()
def dataset_traversal(X, Y, partial_function):
chunk_size = 5000
classes = np.unique(Y)
lower = 0
for upper in iter(range(chunk_size, X.shape[0], chunk_size)):
partial_function(X[lower:upper], Y[lower:upper], classes)
lower = upper
partial_function(X[upper:], Y[upper:], classes)
mnb = GaussianNB_sk()
%time dataset_traversal(x_train_np,\
y_train_np,\
lambda x, y, c: mnb.partial_fit(x.toarray(), y, c))
%time dataset_traversal(x_test_np,\
y_test_np,\
lambda x, y, c: print(mnb.score(x.toarray(), y)))
CPU times: user 2min 47s, sys: 1min 29s, total: 4min 17s Wall time: 4min 17s 0.885 0.8736 0.8802 0.8828 0.8836 0.8738 0.8806 0.881 0.8832 0.8784 0.8714 0.879 0.8754 0.8782 0.8816 0.8844 0.875 0.8764 0.877 0.8864 0.8796 0.8842975206611571 CPU times: user 3min 8s, sys: 2min 7s, total: 5min 16s Wall time: 5min 16s
NB 分類器的另一個(gè)優(yōu)點(diǎn)是,可以使用partial_fit方法對(duì)Estimator對(duì)象進(jìn)行增量訓(xùn)練。這種技術(shù)適用于可能無(wú)法一次性放入內(nèi)存或必須分布在多個(gè) GPU 中的大規(guī)模數(shù)據(jù)集。
我們的第一個(gè)示例演示了使用高斯樸素貝葉斯的增量訓(xùn)練,方法是在使用 TF-IDF 預(yù)處理為連續(xù)特征后,將數(shù)據(jù)分割成多個(gè)塊。高斯樸素貝葉斯的 cuML 版本在訓(xùn)練方面比 Scikit 學(xué)習(xí)快 21 倍,在推理方面快 72 倍。
伯努利樸素貝葉斯
下一個(gè)示例演示了伯努利樸素貝葉斯,無(wú)需增量訓(xùn)練,使用表示每個(gè)項(xiàng)存在或不存在的二進(jìn)制特征。CountVectorizer對(duì)象可以通過(guò)設(shè)置binary=True來(lái)實(shí)現(xiàn)這一點(diǎn)。在本例中,我們發(fā)現(xiàn)比 Scikit learn 快 14 倍。
Bernoulli + CountVectorizer
In the Bernoulli variant, the feature vector is binarized. That's why using a CountVectorizer transformer is useful: You're more interested in the presence of the word rather than it's frequency.
vec = CountVectorizer(stop_words='english', binary=True, ngram_range=(1,3))
x_train = vec.fit_transform(X_train_text)
x_test = vec.transform(X_test_text)
bnb = BernoulliNB()
%time bnb.fit(x_train, y_train)
%time bnb.score(x_test, y_test)
CPU times: user 44.4 ms, sys: 12.1 ms, total: 56.5 ms Wall time: 56.5 ms CPU times: user 14.9 ms, sys: 19.6 ms, total: 34.5 ms Wall time: 34.2 ms
0.8568723201751709
vec = CountVectorizer(stop_words='english', binary=True, ngram_range=(1,3))
x_train = vec.fit_transform(X_train_text)
x_test = vec.transform(X_test_text)
x_train_np, x_test_np = x_train.get(), x_test.get()
y_train_np, y_test_np = y_train.to_numpy(), y_test.to_numpy()
bnb = BernoulliNB_sk()
%time bnb.fit(x_train_np, y_train_np)
%time bnb.score(x_test_np, y_test_np)
CPU times: user 293 ms, sys: 72.1 ms, total: 365 ms Wall time: 365 ms CPU times: user 141 ms, sys: 90.9 ms, total: 232 ms Wall time: 231 ms
0.8568817764310402
多項(xiàng)式樸素貝葉斯
多項(xiàng)式樸素貝葉斯是最通用和最廣泛使用的變體,如以下示例所示。我們使用 TF-IDF 矢量器而不是CountVectorizer來(lái)實(shí)現(xiàn)比 Scikit learn 快 5 倍的速度。
TF-IDF + Multinomial
Transform the text through a TF-IDF vectorizer, and run a multinomial naive Bayes model.
vec = TfidfVectorizer(stop_words='english', ngram_range=(1,3))
x_train = vec.fit_transform(X_train_text)
x_test = vec.transform(X_test_text)
mnb = MultinomialNB()
%time mnb.fit(x_train, y_train)
%time mnb.score(x_test, y_test)
CPU times: user 55.4 ms, sys: 7.57 ms, total: 63 ms Wall time: 63 ms CPU times: user 20.3 ms, sys: 8.16 ms, total: 28.4 ms Wall time: 28.2 ms
0.9248046875
vec = TfidfVectorizer(stop_words='english', ngram_range=(1,3))
x_train = vec.fit_transform(X_train_text)
x_test = vec.transform(X_test_text)
x_train_np, x_test_np = x_train.get(), x_test.get()
y_train_np, y_test_np = y_train.to_numpy(), y_test.to_numpy()
mnb = MultinomialNB_sk()
%time mnb.fit(x_train_np, y_train_np)
%time mnb.score(x_test_np, y_test_np)
CPU times: user 264 ms, sys: 67.6 ms, total: 332 ms Wall time: 332 ms CPU times: user 31.8 ms, sys: 27.9 ms, total: 59.7 ms Wall time: 59.4 ms
0.9248046967473131
補(bǔ)碼樸素貝葉斯
我們使用CountVectorizer證明了補(bǔ)碼樸素貝葉斯的威力,并表明在我們的不平衡數(shù)據(jù)集上,它比伯努利和多項(xiàng)式 NB 變體產(chǎn)生了更好的分類分?jǐn)?shù)。
CountVectorizer + Complement
Complement naive Bayes models should be coupled with a CountVectorizer to have the best results.
# First let's visualize the class imbalance
dataset['CATEGORY'].value_counts().to_pandas().plot(kind='bar', title='histogram of the class distributions')
dataset['CATEGORY'].value_counts() / len(dataset)
3 0.360943 1 0.274531 2 0.256485 4 0.108042 Name: CATEGORY, dtype: float64
vec = CountVectorizer(stop_words='english', ngram_range=(1,3))
x_train = vec.fit_transform(X_train_text)
x_test = vec.transform(X_test_text)
cnb = ComplementNB()
%time cnb.fit(x_train, y_train)
%time cnb.score(x_test, y_test)
CPU times: user 56.8 ms, sys: 12.3 ms, total: 69.1 ms Wall time: 69.2 ms CPU times: user 22.4 ms, sys: 7.27 ms, total: 29.7 ms Wall time: 29.8 ms
0.9502959251403809
vec = CountVectorizer(stop_words='english', ngram_range=(1,3))
x_train = vec.fit_transform(X_train_text)
x_test = vec.transform(X_test_text)
x_train_np, x_test_np = x_train.get(), x_test.get()
y_train_np, y_test_np = y_train.to_numpy(), y_test.to_numpy()
cnb = ComplementNB_sk()
%time mnb.fit(x_train_np, y_train_np)
%time mnb.score(x_test_np, y_test_np)
CPU times: user 67.5 ms, sys: 31.8 ms, total: 99.3 ms Wall time: 99.5 ms CPU times: user 26.6 ms, sys: 11.4 ms, total: 38 ms Wall time: 37.7 ms
0.9449836611747742
范疇樸素貝葉斯
最后但絕對(duì)不是最不重要的是一個(gè)分類樸素貝葉斯的例子,我們使用 k-means 和之前在另一個(gè) NB 變體上訓(xùn)練的模型對(duì)其進(jìn)行矢量化,以根據(jù)相似項(xiàng)對(duì)結(jié)果類的貢獻(xiàn)將其分組到相同的類別中。
我們發(fā)現(xiàn),與 Scikit 相比,使用 315K 條新聞標(biāo)題訓(xùn)練模型的速度提高了 126 倍,使用 23 倍的速度進(jìn)行推理和計(jì)算模型的準(zhǔn)確性。
Preprocessing
# First fit a TfIdf on the train dataset
tfidfvec = TfidfVectorizer(stop_words='english', min_df=10)
x_train = tfidfvec.fit_transform(X_train_text)
# Fit a Multinomial on the TdIdf data
mnb = MultinomialNB().fit(x_train, y_train)
# Use a KMeans algorithm to cluster on what the Multinomial NB learned of the TfIdf.
# This means that the words that contribute similarly to a category will be clustered together
km = KMeans(n_clusters=1000, random_state=1)
feature_to_cluster = km.fit_predict(mnb.feature_log_prob_.T)
feats2cluster = OneHotEncoder().fit_transform(feature_to_cluster)
# Print statistics on the repartition of the words in the clusters
print(cudf.Series(feats2cluster.sum(0)[0]).describe())
count 1000.000000 mean 14.967000 std 19.519501 min 1.000000 25% 6.000000 50% 11.000000 75% 18.000000 max 254.000000 dtype: float64
Here each cluster holds in average around 15 words
# Lets plot the repartition of the words in each cluster
# And print the words in a few clusters
plt.hist(feature_to_cluster.get(), bins='auto')
print(tfidfvec.vocabulary_[cp.where(feature_to_cluster == 127)[0]])
print("\n")
print(tfidfvec.vocabulary_[cp.where(feature_to_cluster == 632)[0]])
47 117 1597 beam 2114 broadband 2435 carriers 2618 charter 3788 defective 4056 dire 4406 dual 5367 fixes 8365 materials 9072 networking 10900 recognition 11466 rollout 13666 tracker 14088 unveiling Name: token, dtype: object 3293 core 3603 cyber 4751 enterprise 5719 gaming 8738 models 9801 pc 10074 platform 14338 virtual Name: token, dtype: object
# For Categorical Naive Bayes, the count of words is transformed into a count of cluster
vocab = tfidfvec.vocabulary_
countvec = CountVectorizer(stop_words='english')
countvec.vocabulary_ = vocab
x_train = countvec.transform(X_train_text)
x_test = countvec.transform(X_test_text)
print(x_train.shape)
print(feats2cluster.shape)
x_train_cluster = (x_train @ feats2cluster)
x_test_cluster = (x_test @ feats2cluster)
# For each cluster we will have:
# - 0: absence of those wprds.
# - 1: presence of those words
# - 2: multiple presence of those words (2+)
x_train_cluster.data[x_train_cluster.data > 2] = 2
x_test_cluster.data[x_test_cluster.data > 2] = 2
(316814, 14967) (14967, 1000)
Little hack to make sure that if a cluster's max number is 1 in training, it is also 1 in testing
max_one = cp.where(x_train_cluster.max(0).todense() == 1)[1]
for cluster in max_one:
samples = (x_test_cluster[:, cluster] > 1)
if samples.nnz == 0:
continue
samples = cp.where(samples.todense())[0]
x_test_cluster[samples, cluster] = 1
Categorical model training
Now that the preprocessing is done we can train the Categorical model and see how it performs on these clusters
%time cnb = CategoricalNB().fit(x_train_cluster, y_train)
%time cnb.score(x_test_cluster, y_test)
/dev/shm/rapids22.04_env/lib/python3.8/site-packages/cuml/naive_bayes/naive_bayes.py:1498: UserWarning: X dtype is not int32. X will be converted, which will increase memory consumption warnings.warn("X dtype is not int32. X will be " /dev/shm/rapids22.04_env/lib/python3.8/site-packages/cupyx/scipy/sparse/compressed.py:545: UserWarning: Changing the sparsity structure of a csr_matrix is expensive. lil_matrix is more efficient. warnings.warn('Changing the sparsity structure of a ' /dev/shm/rapids22.04_env/lib/python3.8/site-packages/cuml/naive_bayes/naive_bayes.py:1516: UserWarning: X dtype is not int32. X will be converted, which will increase memory consumption warnings.warn("X dtype is not int32. X will be "
CPU times: user 110 ms, sys: 4.87 ms, total: 115 ms Wall time: 112 ms CPU times: user 64.7 ms, sys: 127 ms, total: 191 ms Wall time: 193 ms
0.9256380200386047
x_train_cluster_np = x_train_cluster.get().todense()
x_test_cluster_np = x_test_cluster.get().todense()
y_train_np, y_test_np = y_train.to_numpy(), y_test.to_numpy()
%time cnb = CategoricalNB_sk().fit(x_train_cluster_np, y_train_np)
%time cnb.score(x_test_cluster_np, y_test_np)
/dev/shm/rapids22.04_env/lib/python3.8/site-packages/sklearn/utils/validation.py:593: FutureWarning: np.matrix usage is deprecated in 1.0 and will raise a TypeError in 1.2. Please convert to a numpy array with np.asarray. For more information see: https://numpy.org/doc/stable/reference/generated/numpy.matrix.html warnings.warn(
CPU times: user 13.7 s, sys: 434 ms, total: 14.2 s Wall time: 14.2 s
/dev/shm/rapids22.04_env/lib/python3.8/site-packages/sklearn/utils/validation.py:593: FutureWarning: np.matrix usage is deprecated in 1.0 and will raise a TypeError in 1.2. Please convert to a numpy array with np.asarray. For more information see: https://numpy.org/doc/stable/reference/generated/numpy.matrix.html warnings.warn(
CPU times: user 4.4 s, sys: 110 ms, total: 4.51 s Wall time: 4.51 s
0.9256379906254438
基準(zhǔn)
圖 2 中的圖表比較了 RAPIDS cuML 和 Scikit learn 之間的 NB 訓(xùn)練和推理的性能,以及本文中概述的所有變體。
基準(zhǔn)測(cè)試是在a2-highgpu-8g谷歌云平臺(tái)( GCP )實(shí)例上執(zhí)行的,該實(shí)例配備了 NVIDIA Tesla A100 GPU 和 96 Intel Cascade Lake v CPU ,頻率為 2.2Ghz 。
圖 2.Scikit learn (藍(lán)色)和 cuML (綠色)之間的性能比較
GPU 加速樸素貝葉斯
我們能夠使用 CuPy 在 Python 中實(shí)現(xiàn)所有 NB 變體,這是一種 GPU 加速,幾乎可以替代 NumPy 和 SciPy 。 CuPy 還提供了用 Python 編寫自定義 CUDA 內(nèi)核的功能。當(dāng) Python 應(yīng)用程序運(yùn)行時(shí),它使用 NVRTC 的即時(shí)( JIT )編譯功能在 GPU 上編譯和執(zhí)行它們。
所有 NB 變體的核心是兩個(gè)使用 CuPy 的 JIT 編寫的簡(jiǎn)單原語(yǔ),用于匯總和計(jì)算每個(gè)類的特征。
當(dāng)單個(gè)文檔項(xiàng)矩陣過(guò)大而無(wú)法在單個(gè) GPU 上處理時(shí), Dask 庫(kù)可以利用增量訓(xùn)練功能將處理擴(kuò)展到多個(gè) GPU 和多個(gè)節(jié)點(diǎn)。目前,多項(xiàng)式變量可以在 cuML 中與 Dask 一起分布。
結(jié)論
NB 算法應(yīng)該在每個(gè)數(shù)據(jù)科學(xué)家的工具包中。使用 RAPIDS cuML ,您可以在 GPU 上加速 NB 的實(shí)現(xiàn),而無(wú)需大幅更改代碼。這些強(qiáng)大而基本的算法,再加上 cuML 的加速,提供了您必須在超大或稀疏數(shù)據(jù)集上執(zhí)行分類的一切。
關(guān)于作者
Mickael Ide 是 NVIDIA RAPIDS 團(tuán)隊(duì)的機(jī)器學(xué)習(xí)工程師,專注于開(kāi)發(fā) GPU 加速的機(jī)器學(xué)習(xí)算法。米克爾擁有計(jì)算機(jī)科學(xué)碩士學(xué)位。
Corey Nolet 是 NVIDIA 的 RAPIDS ML 團(tuán)隊(duì)的數(shù)據(jù)科學(xué)家兼高級(jí)工程師,他專注于構(gòu)建和擴(kuò)展機(jī)器學(xué)習(xí)算法,以支持光速下的極端數(shù)據(jù)負(fù)載。在 NVIDIA 工作之前, Corey 花了十多年時(shí)間為國(guó)防工業(yè)的 HPC 環(huán)境構(gòu)建大規(guī)模探索性數(shù)據(jù)科學(xué)和實(shí)時(shí)分析平臺(tái)。科里持有英國(guó)理工學(xué)士學(xué)位計(jì)算機(jī)科學(xué)碩士學(xué)位。他還在攻讀博士學(xué)位。在同一學(xué)科中,主要研究圖形和機(jī)器學(xué)習(xí)交叉點(diǎn)的算法加速。科里熱衷于利用數(shù)據(jù)更好地了解世界。
審核編輯:郭婷
-
cpu
+關(guān)注
關(guān)注
68文章
11011瀏覽量
215223 -
NVIDIA
+關(guān)注
關(guān)注
14文章
5188瀏覽量
105436 -
gpu
+關(guān)注
關(guān)注
28文章
4882瀏覽量
130404
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
機(jī)器學(xué)習(xí)之樸素貝葉斯應(yīng)用教程

一種新型樸素貝葉斯文本分類算法
機(jī)器學(xué)習(xí)之樸素貝葉斯
樸素貝葉斯算法詳細(xì)總結(jié)

如何使用Spark計(jì)算框架進(jìn)行分布式文本分類方法的研究

一種特征假期樸素貝葉斯文本分類算法
樸素貝葉斯分類 樸素貝葉斯算法的優(yōu)點(diǎn)
PyTorch教程22.9之樸素貝葉斯

評(píng)論