探索 Python、机器学习和 NLTK 库 开发一个应用程序,使用 Python、NLTK 和机器学习对 RSS 提要进行分类
挑戰(zhàn):使用機器學習對 RSS 提要進行分類
最近,我接到一項任務,要求為客戶創(chuàng)建一個 RSS 提要分類子系統(tǒng)。目標是讀取幾十個甚至幾百個 RSS 提要,將它們的許多文章自動分類到幾十個預定義的主題領域當中。客戶網站的內容、導航和搜索功能都將由這個每日自動提要檢索和分類結果驅動。
客戶建議使用機器學習,或許還會使用 Apache Mahout 和 Hadoop 來實現(xiàn)該任務,因為客戶最近閱讀了有關這些技術的文章。但是,客戶的開發(fā)團隊和我們的開發(fā)團隊都更熟悉 Ruby,而不是 Java? 技術。本文將介紹解決方案的技術之旅、學習過程和最終實現(xiàn)。
什么是機器學習?
我的第一個問題是,“究竟什么是機器學習?” 我聽說過這個術語,并且隱約知道超級計算機 IBM? Watson 最近使用該技術在一場 Jeopardy 比賽中擊敗了人類競爭者。作為購物者和社交網絡活動參與者,我也知道 Amazon.com 和 Facebook 根據(jù)其購物者數(shù)據(jù)在提供建議(如產品和人)方面表現(xiàn)良好。總之,機器學習取決于 IT、數(shù)學和自然語言的交集。它主要關注以下三個主題,但客戶的解決方案最終僅涉及前兩個主題:
- 分類。根據(jù)類似項目的一組訓練數(shù)據(jù),將相關的項分配到任意預定義的類別
- 建議。根據(jù)類似項目的觀察來建議采用的項
- 集群。在一組數(shù)據(jù)內確定子組
Mahout 和 Ruby 的選擇
理解了機器學習是什么之后,下一步是確定如何實現(xiàn)它。根據(jù)客戶的建議,Mahout 是一個合適的起點。我從 Apache 下載了代碼,并開始了學習使用 Mahout 及其兄弟 Hadoop 實現(xiàn)機器學習的過程。不幸的是,我發(fā)現(xiàn)即使對于有經驗的 Java 開發(fā)人員而言,Mahout 的學習曲線也很陡峭,并且不存在可用的樣例代碼。同樣不幸的是,機器學習缺乏基于 Ruby 的框架或 gem。
發(fā)現(xiàn) Python 和 NLTK
我繼續(xù)搜索解決方案,并且在結果集中一直遇到 "Python"。作為一名 Ruby 開發(fā)人員,雖然我還沒有學過該語言,但我也知道 Python 是一個面向相似對象的、基于文本的、可理解和動態(tài)的編程語言。盡管兩種語言之間存在一些相似之處,但我多年來都忽視了學習 Python,將它視為一項多余的技能集。Python 是我的 “盲點”,我懷疑許多 Ruby 開發(fā)人員同行都是這樣認為的。
搜索機器學習的書籍,并更深入研究它們的目錄,我發(fā)現(xiàn),有相當高比例的此類系統(tǒng)在使用 Python 作為其實現(xiàn)語言,并使用了一個被稱為 Natural Language Toolkit(NLTK,自然語言工具包)的庫。通過進一步的搜索,我發(fā)現(xiàn) Python 的應用比我意識到的還要廣泛,如 Google App Engine、YouTube 和使用 Django 框架構建的網站。它甚至還預安裝在我每天都使用的 Mac OS X 工作站上!此外,Python 為數(shù)學、科學和工程提供了有趣的標準庫(例如,NumPy 和 SciPy)。
我決定推行一個 Python 解決方案,因為我找到了非常好的編碼示例。例如,下面這一行代碼就是通過 HTTP 讀取 RSS 提要并打印其內容所需的所有代碼:
print feedparser.parse("http://feeds.nytimes.com/nyt/rss/Technology")回頁首
快速掌握 Python
在學習一門新的編程語言時,最容易的部分往往是學習語言本身。較難的部分是了解它的生態(tài)系統(tǒng):如何安裝它、添加庫、編寫代碼、構造代碼文件、執(zhí)行它、調試它并編寫單元測試。本節(jié)將簡要介紹這些主題;請務必參閱?參考資料,以獲得有關詳細信息的鏈接。
pip
Python Package Index (pip) 是 Python 的標準軟件包管理器。您可以使用該程序將庫添加到您的系統(tǒng)。它類似于 Ruby 庫的 gem。為了將 NLTK 庫添加到您的系統(tǒng),您可以輸入以下命令:
$ pip install nltk為了顯示在您的系統(tǒng)上已安裝的 Python 庫的列表,請運行以下命令:
$ pip freeze運行程序
執(zhí)行 Python 程序同樣很簡單。獲得一個名稱為?locomotive_main.py?的程序和三個參數(shù),然后您就可以使用 Python 程序編譯并執(zhí)行它:
$ python locomotive_main.py arg1 arg2 arg3Python 使用?清單 1?中的?if __name__ == "__main__":?語法來確定文件本身是從命令行執(zhí)行的還是從其他代碼導入的。為了讓文件變得可以執(zhí)行,需要添加?"__main__"?檢測。
清單 1. Main 檢測
import sys import time import locomotiveif __name__ == "__main__":start_time = time.time()if len(sys.argv) > 1:app = locomotive.app.Application()... additional logic ...virtualenv
大多數(shù) Ruby 開發(fā)人員熟悉系統(tǒng)范圍的庫或 gem 的問題。使用一組系統(tǒng)范圍內的庫的做法一般是不可取的,因為您的其中一個項目可能依賴于某個給定的庫的版本 1.0.0,而另一個項目則依賴于版本 1.2.7。同樣,Java 開發(fā)人員都知道系統(tǒng)范圍的 CLASSPATH 存在同樣的問題。就像 Ruby 社區(qū)使用其?rvm?工具,而 Python 社區(qū)使用?virtualenv?工具(請參閱?參考資料,以獲得相關鏈接)來創(chuàng)建獨立的執(zhí)行環(huán)境,其中包含特定版本的 Python 和一組庫。清單 2?中的命令顯示了如何為您 p1 項目創(chuàng)建一個名為?p1_env?的虛擬環(huán)境,其中包含feedparser、numpy、scipy?和?nltk?庫。
清單 2. 使用 virualenv 創(chuàng)建一個虛擬環(huán)境的命令
$ sudo pip install virtualenv$ cd ~$ mkdir p1$ cd p1$ virtualenv p1_env --distribute$ source p1_env/bin/activate (p1_env)[~/p1]$ pip install feedparser(p1_env)[~/p1]$ pip install numpy(p1_env)[~/p1]$ pip install scipy(p1_env)[~/p1]$ pip install nltk(p1_env)[~/p1]$ pip freeze每次在一個 shell 窗口使用您的項目時,都需要 “獲得” 您的虛擬環(huán)境激活腳本。請注意,在激活腳本被獲得后,shell 提示符會改變。當在您的系統(tǒng)上創(chuàng)建和使用 shell 窗口,輕松地導航到您的項目目錄,并啟動其虛擬環(huán)境時,您可能想在您的 ~/.bash_profile 文件中添加以下條目:
$ alias p1="cd ~/p1 ; source p1_env/bin/activate"代碼庫結構
在完成簡單的單文件 “Hello World” 程序的編寫之后,Python 開發(fā)人員需要理解如何正確地組織其代碼庫的目錄和文件名。Java 和 Ruby 語言在這方面都有各自的要求,Python 也沒有什么不同。簡單來說,Python 使用包?的概念對相關的代碼進行分組,并提供了明確的名稱空間。出于演示目的,在本文中,代碼存在于某個給定項目的根目錄中,例如 ~/p1。在這個目錄中,存在一個用于相同名稱的 Python 包的 locomotive 目錄。清單 3?顯示了這個目錄結構。
清單 3. 示例目錄結構
locomotive_main.py locomotive_tests.pylocomotive/__init__.pyapp.pycapture.pycategory_associations.pyclassify.pynews.pyrecommend.pyrss.pylocomotive_tests/__init__.pyapp_test.pycategory_associations_test.pyfeed_item_test.pycrss_item_test.py請注意名稱古怪的?__init__.py?文件。這些文件指示 Python 為您的包加載必要的庫和特定的應用程序代碼文件,它們都位于相同的目錄中。?清單 4?顯示了文件 locomotive/__init__.py 的內容。
清單 4. locomotive/__init__.py
# system imports; loads installed packagesimport codecsimport localeimport sys# application imports; these load your specific *.py filesimport appimport captureimport category_associationsimport classifyimport rssimport newsimport recommend有了結構如?清單 4?所示的 locomotive 包之后,在項目的根目錄中的主程序就可以導入并使用它。例如,文件 locomotive_main.py 包含以下導入:
import sys # >-- system libraryimport time # >-- system libraryimport locomotive # >-- custom application code library in the "locomotive" directory測試
Python?unittest?標準庫提供一個非常好的測試解決方案。熟悉 JUnit 的 Java 開發(fā)人員和熟悉 Test::Unit 框架的 Ruby 開發(fā)人員應該會覺得?清單 5?中的 Python?unittest?代碼很容易理解。
清單 5. Python unittest
class AppTest(unittest.TestCase):def setUp(self):self.app = locomotive.app.Application()def tearDown(self):passdef test_development_feeds_list(self):feeds_list = self.app.development_feeds_list()self.assertTrue(len(feeds_list) == 15)self.assertTrue('feed://news.yahoo.com/rss/stock-markets' in feeds_list)清單 5?中的代碼還演示了 Python 的一個顯著的特點:所有的代碼必須一致縮進,否則無法成功編譯。tearDown(self)?方法可能在開始時看起來有點古怪。您可能會問,為什么測試總是被硬編碼為通過?事實上并非如此。這只是在 Python 中編寫空方法的一種方式。
工具
我真正需要的是一個具備語法突出顯示、代碼完成和斷點調試功能的集成開發(fā)環(huán)境 (IDE),用該環(huán)境幫助我掌握我的 Python 學習曲線。作為使用 Eclipse IDE 進行 Java 開發(fā)的一名用戶,pyeclipse?插件是我考慮的下一個工具。雖然該插件有時比較慢,但它工作得相當不錯。我最終投資了 PyCharm IDE,它滿足了我的所有 IDE 要求。
在掌握了 Python 及其生態(tài)系統(tǒng)的基本知識之后,終于來到開始實現(xiàn)機器學習解決方案的時候。
回頁首
使用 Python 和 NLTK 實現(xiàn)分類
實現(xiàn)解決方案涉及捕獲模擬的 RSS 提要、整理其文本、使用一個?NaiveBayesClassifier?和 kNN 算法對類別進行分類。下面將會介紹這些操作中的每一個。
捕獲和解析提要
該項目特別具有挑戰(zhàn)性,因為客戶還沒有定義目標 RSS 提要列表。因此,也不存在 “訓練數(shù)據(jù)”。所以,在初始開發(fā)期間必須模擬提要和訓練數(shù)據(jù)。
我用來獲得示例提要數(shù)據(jù)的第一個方法是只提取在某個文本文件中指定的列表中的 RSS 提要。Python 提供了一個很好的 RSS 提要解析庫,其名稱為?feedparser,它抽象不同的 RSS 和 Atom 格式之間的差異。簡單的基于文本的對象序列化的另一個有用的庫被幽默地稱為pickle(泡菜)。這兩個庫在?清單 6?的代碼中均有使用,清單 6 中的代碼將每一個 RSS 提要捕獲為 “腌制過的” 對象文件,以備后用。如您所見,Python 代碼非常簡潔,且功能強大。
清單 6. CaptureFeeds 類
import feedparser import pickleclass CaptureFeeds:def __init__(self):for (i, url) in enumerate(self.rss_feeds_list()):self.capture_as_pickled_feed(url.strip(), i)def rss_feeds_list(self):f = open('feeds_list.txt', 'r')list = f.readlines()f.closereturn listdef capture_as_pickled_feed(self, url, feed_index):feed = feedparser.parse(url)f = open('data/feed_' + str(feed_index) + '.pkl', 'w')pickle.dump(feed, f)f.close()if __name__ == "__main__":cf = CaptureFeeds()下一步的挑戰(zhàn)性之大是出乎意料的。現(xiàn)在,我有了樣例提要數(shù)據(jù),必須對它進行分類,以便將它用作訓練數(shù)據(jù)。訓練數(shù)據(jù)?是向您的分類算法提供的數(shù)據(jù)集,以便您能從中進行學習。
例如,我使用的樣例提要包括了體育電視網絡公司 ESPN。提要的項目之一是關于 Denver Broncos 橄欖球隊的 Tim Tebow 被轉會到 New York Jets 橄欖球隊,在同一時間,Broncos 簽了他們新的四分衛(wèi) Peyton Manning。提要結果中的另一個項目是 Boeing Company 和它的新噴氣式飛機 (jet)。所以,這里的問題是,應該將哪些具體的類別值分配給第一個故事?tebow、broncos、manning、jets、quarterback、trade和?nfl?這些值都是合適的。但只有一個值可以在訓練數(shù)據(jù)中被指定為訓練數(shù)據(jù)類別。同樣,在第二個故事中,類別應該是?boeing?還是?jet?困難的部分在于這些細節(jié)。如果您的算法要產生精確的結果,那么大型訓練數(shù)據(jù)集的準確手工分類非常關鍵。要做到這一點,不應該低估所需的時間。
我需要使用更多的數(shù)據(jù),而且這些數(shù)據(jù)必須已進行了準確的分類,這種情況很快就變得明顯。我可以在哪里找到這樣的數(shù)據(jù)呢?進入 Python NLTK。除了是一個出色的語言文本處理庫之外,它甚至還帶有可下載的示例數(shù)據(jù)集,或是其術語中的文集,以及可以輕松訪問此下載數(shù)據(jù)的應用程序編程接口。要安裝 Reuters 文集,可以運行如下所示的命令。會有超過 10,000 篇新聞文章將下載到您的 ~/nltk_data/corpora/reuters/ 目錄中。與 RSS 提要項目一樣,每篇 Reuters 新聞文章中都包含一個標題和一個正文,所以這個 NLTK 預分類的數(shù)據(jù)非常適合于模擬 RSS 提要。
$ python # enter an interactive Python shell >>> import nltk # import the nltk library >>> nltk.download() # run the NLTK Downloader, then enter 'd' Download Identifier> reuters # specify the 'reuters' corpus特別令人感興趣的是文件 ~/nltk_data/corpora/reuters/cats.txt。它包含了一個列表,其中包含文章文件名稱,以及為每個文章文件分配的類別。文件看起來如下所示,所以,子目錄 test 中的文件 14828 中的文章與主題?grain?有關。
test/14826 trade test/14828 grain自然語言是混亂的
RSS 提要分類算法的原始輸入,當然是以英語書寫的文本。原始,確實如此。
從計算機處理的角度來看,英語或任何自然語言(口語或普通的語言)都是極不規(guī)范和不準確的。首先,存在大小寫的問題。單詞?Bronco?是否等于?bronco?答案是,也許是。接下來,您要應付標點和空格。bronco.?是否等于?bronco?或?bronco,?算是吧。然后,有復數(shù)形式和相似的單詞。run、running?和?ran?是否相等?這取決于不同的情況。這三個詞有一個共同的?詞根。如果將自然語言詞匯嵌入在標記語言(如 HTML)中,情況會怎么樣呢?在這種情況下,您必須處理像?<strong>bronco</strong>?這樣的文本。最后,還有一個問題,就是那些經常使用但基本上毫無意義的單詞,像?a、and?和?the。這些所謂的停用詞非常礙事。自然語言非常凌亂;在處理之前,需要對它們進行整理。
幸運的是,Python 和 NLTK 讓您可以收拾這個爛攤子。在?清單 7?中,RssItem?類的?normalized_words?方法可以處理所有這些問題。請?zhí)貏e注意 NLTK 如何只使用一行代碼就能夠清潔嵌入式 HTML 標記的原始文章文本!使用一個正則表達式刪除標點,然后每個單詞被拆分,并規(guī)范化為小寫。
清單 7. RssItem 類
class RssItem:...regex = re.compile('[%s]' % re.escape(string.punctuation))...def normalized_words(self, article_text):words = []oneline = article_text.replace('\n', ' ')cleaned = nltk.clean_html(oneline.strip())toks1 = cleaned.split()for t1 in toks1:translated = self.regex.sub('', t1)toks2 = translated.split()for t2 in toks2:t2s = t2.strip().lower()if self.stop_words.has_key(t2s):passelse:words.append(t2s)return words只需這一行代碼就可以從 NLTK 獲得停用詞列表;并且還支持其他自然語言:
nltk.corpus.stopwords.words('english')NLTK 還提供了一些 “詞干分析器” 類,以便進一步規(guī)范化單詞。請查看有關詞干、詞形歸并、句子結構和語法的 NLTK 文檔,了解有關的更多信息。
使用 Naive Bayes 算法進行分類
算法在 NLTK 中被廣泛使用并利用nltk.NaiveBayesClassifier?類實現(xiàn)。Bayes 算法根據(jù)特性在其數(shù)據(jù)集中的每個存在或不存在對項目進行分類。在 RSS 提要項目的情況下,每一個特性都是自然語言的一個給定的(清潔過的)單詞。該算法是 “樸實” 的,因為它假設特性(在本例中,單詞)之間沒有任何關系。
然而,英語這種語言包含超過 250,000 個單詞。當然,我不希望為了將 RSS 提要項目傳遞給算法就要為每個 RSS 提要項目創(chuàng)建一個包含 250,000 個布爾值的對象。那么,我會使用哪些單詞?簡單來說,答案是在培訓數(shù)據(jù)組中除了停用詞之外最常見的單詞。NLTK 提供了一個優(yōu)秀的類,即?nltk.probability.FreqDist,我可以用它來識別這些最常用的單詞。在?清單 8?中,collect_all_words?方法返回來自所有培訓文章的所有單詞的一個數(shù)組。
然后,此數(shù)組被傳遞給?identify_top_words?方法,以確定最頻繁的單詞。nltk.FreqDist?類的一個有用的特性是,它實質上是一個散列,但是它的鍵按其對應的值或計數(shù)?排序。因此,使用?[:1000]?Python 語法可以輕松獲得最頻繁的 1000 個單詞。
清單 8. 使用 nltk.FreqDist 類
def collect_all_words(self, items):all_words = []for item in items:for w in item.all_words:words.append(w)return all_wordsdef identify_top_words(self, all_words):freq_dist = nltk.FreqDist(w.lower() for w in all_words)return freq_dist.keys()[:1000]對于利用 NLTK Reuters 文章數(shù)據(jù)模擬的 RSS 提要項目,我需要確定每個項目的類別。為此,我讀取前面提到的 ~/nltk_data/corpora/reuters/cats.txt 文件。用 Python 讀取一個文件非常簡單,如下所示:
def read_reuters_metadata(self, cats_file):f = open(cats_file, 'r')lines = f.readlines()f.close()return lines接下來的步驟是獲得每個 RSS 提要項目的特性。RssItem?類的?features?方法(如下所示)可以做到這一點。在該方法中,在文章中的all_words?數(shù)組首先被減少到一個較小的?set?對象,以消除重復的單詞。然后會遍歷?top_words,并在該 set 中進行比較,確定是否存在重復的單詞。隨后返回 1000 個布爾值組成的一個散列,以?w_?為鍵,后面是單詞本身。這個 Python 非常簡潔。
def features(self, top_words):word_set = set(self.all_words)features = {}for w in top_words:features["w_%s" % w] = (w in word_set)return features接下來,我收集了訓練集的 RSS 提要項目和它們各自的特性,并將它們傳遞給算法。清單 9?中的代碼演示了這個任務。請注意,分類器被訓練成為只有一行代碼。
清單 9. 訓練 nltk.NaiveBayesClassifier
def classify_reuters(self):...training_set = []for item in rss_items:features = item.features(top_words)tup = (features, item.category) # tup is a 2-element tuplefeaturesets.append(tup)classifier = nltk.NaiveBayesClassifier.train(training_set)NaiveBayesClassifier?在運行中的 Python 程序的內存中,它現(xiàn)在是經過訓練的。現(xiàn)在,我只需遍歷需要進行分類的 RSS 提要項目集,并要求分類器猜測每個項目的類別。這很簡單。
for item in rss_items_to_classify:features = item.features(top_words)category = classifier.classify(feat)變得不那么樸實
如前所述,算法假設每個特性之間是沒有關系的。因此,像 "machine learning" 和 "learning machine",或者 "New York Jet" 和 "jet to New York" 這樣的短語是等效的(to?是一個停用詞)。在自然的語言上下文中,這些單詞之間有明顯的關系。所以,我怎么會讓算法變得 “不那么天真”,并識別這些單詞的關系?
其中一個技巧是在特性集內包括常見的雙字詞(兩個單詞為一組)和三字詞(三個單詞為一組)。NLTK 以?nltk.bigrams(...)?和nltk.trigrams(...)?的形式對此提供了支持,現(xiàn)在我們對此應該不再感到驚訝了。正如可以從訓練數(shù)據(jù)組收集最常用的?n?個單詞那樣,也可以識別最常用的雙字詞和三字詞,并將它們用作特性。
您的結果會有所不同
對數(shù)據(jù)和算法進行完善是一門藝術。您是否應該進一步規(guī)范化單詞集,也許應該包括詞根?或者包括超過 1000 個最常用單詞?少一點是否合適?或者是否應該使用更大的訓練數(shù)據(jù)集?是否應該添加更多信用詞或 “停用詞根”?這些都是您要問自己的正確問題。使用它們進行實驗,通過試錯法,您可以會為您的數(shù)據(jù)實現(xiàn)最佳算法。我發(fā)現(xiàn),85% 是一個很好的分類成功率。
利用 k-Nearest Neighbors 算法提出建議
客戶希望顯示在選定類別或相似類別中的 RSS 提要項目。現(xiàn)在,這些項目已經用 Naive Bayes 算法進行分類,這一要求的第一部分已得到了滿足。較難的部分是實現(xiàn) “或相似類別” 的要求。這是機器學習建議器系統(tǒng)開始發(fā)揮作用的地方。建議器系統(tǒng)?根據(jù)其他項目的相似性來建議一個項目。Amazon.com 的產品建議和 Facebook 的朋友建議就是此功能的很好的示例。
k-Nearest Neighbors (kNN) 是最常用的建議算法。思路是向它提供一組標簽(即類別),并且每個標簽都對應一個數(shù)據(jù)集。然后,該算法對各數(shù)據(jù)集進行了比較,以識別相似的項目。數(shù)據(jù)集由多個數(shù)值數(shù)組構成,數(shù)值的范圍往往被規(guī)范化為從 0 到 1。然后,它可以從數(shù)據(jù)集識別相似的標簽。與只產生一個結果的 Naive Bayes 不同,kNN 可以產生一個有排名的列表,其中包含若干(即,k?的值)個建議。
我發(fā)現(xiàn),建議器算法比分類算法更容易理解和實現(xiàn),但對于本文來說,其代碼過于冗長,并且有復雜的數(shù)學,無法在這里詳述。請參閱由 Manning 出版的一本很好的新書?Machine Learning in Action,獲取 kNN 編碼示例(請參閱?參考資料?中的鏈接)。在 RSS 提要項目實現(xiàn)的過程中,標簽值是項目類別,而數(shù)據(jù)集是最常用的 1000 個單詞的值數(shù)組。同樣,在構建這個數(shù)組時,一部分屬于科學范疇,一部分屬于數(shù)學范疇,還有一部分屬于藝術范疇。在數(shù)組中,每個單詞的值都可以是簡單的 0 或 1 的布爾值、文章中單詞出現(xiàn)次數(shù)的百分比、該百分比的指數(shù)值,或一些其他值。
回頁首
結束語
探索 Python、NLTK 和機器學習一直是一個有趣的、令人愉快的經驗。Python 語言強大而又簡潔,現(xiàn)在已成為我的開發(fā)工具包的核心部分。它非常適合于機器學習、自然語言和數(shù)學/科學應用程序。雖然本文中并沒有提到,但我還發(fā)現(xiàn) Python 對于圖表和繪圖非常有用。如果 Python 同樣是您的盲點,我建議您了解一下它。
參考資料
學習
- 從 Wikipedia 了解有關?機器學習?的更多信息。
- 查看?Python 的官方網站。
- 閱讀 Peter Harrington 的?Machine Learning in Action(Manning,2012)。
- 查看?Natural Language Processing with Python,由 Steven Bird、Ewan Klein 和 Edward Loper 合著(O'Reilly,2009)。
- 查看?Implement Bayesian inference using PHP(Paul Meagher, developerWorks, 2009 年 3 月至 5 月)。這是一個由三部分組成的系列文章,討論了一些有趣的應用程序,旨在幫助您了解 Bayesian 推理概念的力量和潛力。
總結
以上是生活随笔為你收集整理的探索 Python、机器学习和 NLTK 库 开发一个应用程序,使用 Python、NLTK 和机器学习对 RSS 提要进行分类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Apache Mahout 简介 通过可
- 下一篇: websocket python爬虫_p