挑戰(zhàn):使用機(jī)器學(xué)習(xí)對RSS提要進(jìn)行分類
最近,我接到一項(xiàng)任務(wù),要求為客戶創(chuàng)建一個RSS提要分類子系統(tǒng)。目標(biāo)是讀取幾十個甚至幾百個RSS提要,將它們的許多文章自動分類到幾十個預(yù)定義的主題領(lǐng)域當(dāng)中??蛻艟W(wǎng)站的內(nèi)容、導(dǎo)航和搜索功能都將由這個每日自動提要檢索和分類結(jié)果驅(qū)動。
客戶建議使用機(jī)器學(xué)習(xí),或許還會使用ApacheMahout和Hadoop來實(shí)現(xiàn)該任務(wù),因?yàn)榭蛻糇罱喿x了有關(guān)這些技術(shù)的文章。但是,客戶的開發(fā)團(tuán)隊(duì)和我們的開發(fā)團(tuán)隊(duì)都更熟悉Ruby,而不是Java?技術(shù)。本文將介紹解決方案的技術(shù)之旅、學(xué)習(xí)過程和最終實(shí)現(xiàn)。
什么是機(jī)器學(xué)習(xí)?
我的第一個問題是,“究竟什么是機(jī)器學(xué)習(xí)?”我聽說過這個術(shù)語,并且隱約知道超級計(jì)算機(jī)IBM?Watson最近使用該技術(shù)在一場Jeopardy比賽中擊敗了人類競爭者。作為購物者和社交網(wǎng)絡(luò)活動參與者,我也知道Amazon.com和Facebook根據(jù)其購物者數(shù)據(jù)在提供建議(如產(chǎn)品和人)方面表現(xiàn)良好??傊?,機(jī)器學(xué)習(xí)取決于IT、數(shù)學(xué)和自然語言的交集。它主要關(guān)注以下三個主題,但客戶的解決方案最終僅涉及前兩個主題:
分類。根據(jù)類似項(xiàng)目的一組訓(xùn)練數(shù)據(jù),將相關(guān)的項(xiàng)分配到任意預(yù)定義的類別
建議。根據(jù)類似項(xiàng)目的觀察來建議采用的項(xiàng)
集群。在一組數(shù)據(jù)內(nèi)確定子組
Mahout和Ruby的選擇
理解了機(jī)器學(xué)習(xí)是什么之后,下一步是確定如何實(shí)現(xiàn)它。根據(jù)客戶的建議,Mahout是一個合適的起點(diǎn)。我從Apache下載了代碼,并開始了學(xué)習(xí)使用Mahout及其兄弟Hadoop實(shí)現(xiàn)機(jī)器學(xué)習(xí)的過程。不幸的是,我發(fā)現(xiàn)即使對于有經(jīng)驗(yàn)的Java開發(fā)人員而言,Mahout的學(xué)習(xí)曲線也很陡峭,并且不存在可用的樣例代碼。同樣不幸的是,機(jī)器學(xué)習(xí)缺乏基于Ruby的框架或gem。
發(fā)現(xiàn)Python和NLTK
我繼續(xù)搜索解決方案,并且在結(jié)果集中一直遇到"Python"。作為一名Ruby開發(fā)人員,雖然我還沒有學(xué)過該語言,但我也知道Python是一個面向相似對象的、基于文本的、可理解和動態(tài)的編程語言。盡管兩種語言之間存在一些相似之處,但我多年來都忽視了學(xué)習(xí)Python,將它視為一項(xiàng)多余的技能集。Python是我的“盲點(diǎn)”,我懷疑許多Ruby開發(fā)人員同行都是這樣認(rèn)為的。
搜索機(jī)器學(xué)習(xí)的書籍,并更深入研究它們的目錄,我發(fā)現(xiàn),有相當(dāng)高比例的此類系統(tǒng)在使用Python作為其實(shí)現(xiàn)語言,并使用了一個被稱為NaturalLanguageToolkit(NLTK,自然語言工具包)的庫。通過進(jìn)一步的搜索,我發(fā)現(xiàn)Python的應(yīng)用比我意識到的還要廣泛,如GoogleAppEngine、YouTube和使用Django框架構(gòu)建的網(wǎng)站。它甚至還預(yù)安裝在我每天都使用的MacOSX工作站上!此外,Python為數(shù)學(xué)、科學(xué)和工程提供了有趣的標(biāo)準(zhǔn)庫(例如,NumPy和SciPy)。
我決定推行一個Python解決方案,因?yàn)槲艺业搅朔浅:玫木幋a示例。例如,下面這一行代碼就是通過HTTP讀取RSS提要并打印其內(nèi)容所需的所有代碼:
printfeedparser.parse("http://feeds.nytimes.com/nyt/rss/Technology")
快速掌握Python
執(zhí)行Python程序同樣很簡單。獲得一個名稱為locomotive_main.py的程序和三個參數(shù),然后您就可以使用Python程序編譯并執(zhí)行它:
$pythonlocomotive_main.pyarg1arg2arg3
Python使用清單1中的if__name__=="__main__":語法來確定文件本身是從命令行執(zhí)行的還是從其他代碼導(dǎo)入的。為了讓文件變得可以執(zhí)行,需要添加"__main__"檢測。
清單1.Main檢測
importsys
importtime
importlocomotive
if__name__=="__main__":
start_time=time.time()
iflen(sys.argv)>1:
app=locomotive.app.Application()
...additionallogic...
virtualenv
大多數(shù)Ruby開發(fā)人員熟悉系統(tǒng)范圍的庫或gem的問題。使用一組系統(tǒng)范圍內(nèi)的庫的做法一般是不可取的,因?yàn)槟钠渲幸粋€項(xiàng)目可能依賴于某個給定的庫的版本1.0.0,而另一個項(xiàng)目則依賴于版本1.2.7。同樣,Java開發(fā)人員都知道系統(tǒng)范圍的CLASSPATH存在同樣的問題。就像Ruby社區(qū)使用其rvm工具,而Python社區(qū)使用virtualenv工具(請參閱參考資料,以獲得相關(guān)鏈接)來創(chuàng)建獨(dú)立的執(zhí)行環(huán)境,其中包含特定版本的Python和一組庫。清單2中的命令顯示了如何為您p1項(xiàng)目創(chuàng)建一個名為p1_env的虛擬環(huán)境,其中包含feedparser、numpy、scipy和nltk庫。
清單2.使用virualenv創(chuàng)建一個虛擬環(huán)境的命令
$sudopipinstallvirtualenv
$cd~
$mkdirp1
$cdp1
$virtualenvp1_env--distribute
$sourcep1_env/bin/activate
(p1_env)[~/p1]$pipinstallfeedparser
(p1_env)[~/p1]$pipinstallnumpy
(p1_env)[~/p1]$pipinstallscipy
(p1_env)[~/p1]$pipinstallnltk
(p1_env)[~/p1]$pipfreeze
每次在一個shell窗口使用您的項(xiàng)目時,都需要“獲得”您的虛擬環(huán)境激活腳本。請注意,在激活腳本被獲得后,shell提示符會改變。當(dāng)在您的系統(tǒng)上創(chuàng)建和使用shell窗口,輕松地導(dǎo)航到您的項(xiàng)目目錄,并啟動其虛擬環(huán)境時,您可能想在您的~/.bash_profile文件中添加以下條目:
$aliasp1="cd~/p1;sourcep1_env/bin/activate"
代碼庫結(jié)構(gòu)
在完成簡單的單文件“HelloWorld”程序的編寫之后,Python開發(fā)人員需要理解如何正確地組織其代碼庫的目錄和文件名。Java和Ruby語言在這方面都有各自的要求,Python也沒有什么不同。簡單來說,Python使用包的概念對相關(guān)的代碼進(jìn)行分組,并提供了明確的名稱空間。出于演示目的,在本文中,代碼存在于某個給定項(xiàng)目的根目錄中,例如~/p1。在這個目錄中,存在一個用于相同名稱的Python包的locomotive目錄。清單3顯示了這個目錄結(jié)構(gòu)。
清單3.示例目錄結(jié)構(gòu)
locomotive_main.py
locomotive_tests.py
locomotive/
__init__.py
app.py
capture.py
category_associations.py
classify.py
news.py
recommend.py
rss.py
locomotive_tests/
__init__.py
app_test.py
category_associations_test.py
feed_item_test.pyc
rss_item_test.py
請注意名稱古怪的__init__.py文件。這些文件指示Python為您的包加載必要的庫和特定的應(yīng)用程序代碼文件,它們都位于相同的目錄中。清單4顯示了文件locomotive/__init__.py的內(nèi)容。
清單4.locomotive/__init__.py
#systemimports;loadsinstalledpackages
importcodecs
importlocale
importsys
#applicationimports;theseloadyourspecific*.pyfiles
importapp
importcapture
importcategory_associations
importclassify
importrss
importnews
importrecommend
有了結(jié)構(gòu)如清單4所示的locomotive包之后,在項(xiàng)目的根目錄中的主程序就可以導(dǎo)入并使用它。例如,文件locomotive_main.py包含以下導(dǎo)入:
importsys#>--systemlibrary
importtime#>--systemlibrary
importlocomotive#>--customapplicationcodelibraryinthe"locomotive"directory
測試
Pythonunittest標(biāo)準(zhǔn)庫提供一個非常好的測試解決方案。熟悉JUnit的Java開發(fā)人員和熟悉Test::Unit框架的Ruby開發(fā)人員應(yīng)該會覺得清單5中的Pythonunittest代碼很容易理解。
清單5.Pythonunittest
classAppTest(unittest.TestCase):
defsetUp(self):
self.app=locomotive.app.Application()
deftearDown(self):
pass
deftest_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'infeeds_list)
清單5中的代碼還演示了Python的一個顯著的特點(diǎn):所有的代碼必須一致縮進(jìn),否則無法成功編譯。tearDown(self)方法可能在開始時看起來有點(diǎn)古怪。您可能會問,為什么測試總是被硬編碼為通過?事實(shí)上并非如此。這只是在Python中編寫空方法的一種方式。
工具
我真正需要的是一個具備語法突出顯示、代碼完成和斷點(diǎn)調(diào)試功能的集成開發(fā)環(huán)境(IDE),用該環(huán)境幫助我掌握我的Python學(xué)習(xí)曲線。作為使用EclipseIDE進(jìn)行Java開發(fā)的一名用戶,pyeclipse插件是我考慮的下一個工具。雖然該插件有時比較慢,但它工作得相當(dāng)不錯。我最終投資了PyCharmIDE,它滿足了我的所有IDE要求。
在掌握了Python及其生態(tài)系統(tǒng)的基本知識之后,終于來到開始實(shí)現(xiàn)機(jī)器學(xué)習(xí)解決方案的時候。
使用Python和NLTK實(shí)現(xiàn)分類
實(shí)現(xiàn)解決方案涉及捕獲模擬的RSS提要、整理其文本、使用一個NaiveBayesClassifier和kNN算法對類別進(jìn)行分類。下面將會介紹這些操作中的每一個。
捕獲和解析提要
該項(xiàng)目特別具有挑戰(zhàn)性,因?yàn)榭蛻暨€沒有定義目標(biāo)RSS提要列表。因此,也不存在“訓(xùn)練數(shù)據(jù)”。所以,在初始開發(fā)期間必須模擬提要和訓(xùn)練數(shù)據(jù)。
我用來獲得示例提要數(shù)據(jù)的第一個方法是只提取在某個文本文件中指定的列表中的RSS提要。Python提供了一個很好的RSS提要解析庫,其名稱為feedparser,它抽象不同的RSS和Atom格式之間的差異。簡單的基于文本的對象序列化的另一個有用的庫被幽默地稱為pickle(泡菜)。這兩個庫在清單6的代碼中均有使用,清單6中的代碼將每一個RSS提要捕獲為“腌制過的”對象文件,以備后用。如您所見,Python代碼非常簡潔,且功能強(qiáng)大。
清單6.CaptureFeeds類
importfeedparser
importpickle
classCaptureFeeds:
def__init__(self):
for(i,url)inenumerate(self.rss_feeds_list()):
self.capture_as_pickled_feed(url.strip(),i)
defrss_feeds_list(self):
f=open('feeds_list.txt','r')
list=f.readlines()
f.close
returnlist
defcapture_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ù),必須對它進(jìn)行分類,以便將它用作訓(xùn)練數(shù)據(jù)。訓(xùn)練數(shù)據(jù)是向您的分類算法提供的數(shù)據(jù)集,以便您能從中進(jìn)行學(xué)習(xí)。
例如,我使用的樣例提要包括了體育電視網(wǎng)絡(luò)公司ESPN。提要的項(xiàng)目之一是關(guān)于DenverBroncos橄欖球隊(duì)的TimTebow被轉(zhuǎn)會到NewYorkJets橄欖球隊(duì),在同一時間,Broncos簽了他們新的四分衛(wèi)PeytonManning。提要結(jié)果中的另一個項(xiàng)目是BoeingCompany和它的新噴氣式飛機(jī)(jet)。所以,這里的問題是,應(yīng)該將哪些具體的類別值分配給第一個故事?tebow、broncos、manning、jets、quarterback、trade和nfl這些值都是合適的。但只有一個值可以在訓(xùn)練數(shù)據(jù)中被指定為訓(xùn)練數(shù)據(jù)類別。同樣,在第二個故事中,類別應(yīng)該是boeing還是jet?困難的部分在于這些細(xì)節(jié)。如果您的算法要產(chǎn)生精確的結(jié)果,那么大型訓(xùn)練數(shù)據(jù)集的準(zhǔn)確手工分類非常關(guān)鍵。要做到這一點(diǎn),不應(yīng)該低估所需的時間。
我需要使用更多的數(shù)據(jù),而且這些數(shù)據(jù)必須已進(jìn)行了準(zhǔn)確的分類,這種情況很快就變得明顯。我可以在哪里找到這樣的數(shù)據(jù)呢?進(jìn)入PythonNLTK。除了是一個出色的語言文本處理庫之外,它甚至還帶有可下載的示例數(shù)據(jù)集,或是其術(shù)語中的文集,以及可以輕松訪問此下載數(shù)據(jù)的應(yīng)用程序編程接口。要安裝Reuters文集,可以運(yùn)行如下所示的命令。會有超過10,000篇新聞文章將下載到您的~/nltk_data/corpora/reuters/目錄中。與RSS提要項(xiàng)目一樣,每篇Reuters新聞文章中都包含一個標(biāo)題和一個正文,所以這個NLTK預(yù)分類的數(shù)據(jù)非常適合于模擬RSS提要。
$python#enteraninteractivePythonshell
>>>importnltk#importthenltklibrary
>>>nltk.download()#runtheNLTKDownloader,thenenter'd'Download
Identifier>reuters#specifythe'reuters'corpus
特別令人感興趣的是文件~/nltk_data/corpora/reuters/cats.txt。它包含了一個列表,其中包含文章文件名稱,以及為每個文章文件分配的類別。文件看起來如下所示,所以,子目錄test中的文件14828中的文章與主題grain有關(guān)。
test/14826trade
test/14828grain
自然語言是混亂的
RSS提要分類算法的原始輸入,當(dāng)然是以英語書寫的文本。原始,確實(shí)如此。
從計(jì)算機(jī)處理的角度來看,英語或任何自然語言(口語或普通的語言)都是極不規(guī)范和不準(zhǔn)確的。首先,存在大小寫的問題。單詞Bronco是否等于bronco?答案是,也許是。接下來,您要應(yīng)付標(biāo)點(diǎn)和空格。bronco.是否等于bronco或bronco,?算是吧。然后,有復(fù)數(shù)形式和相似的單詞。run、running和ran是否相等?這取決于不同的情況。這三個詞有一個共同的詞根。如果將自然語言詞匯嵌入在標(biāo)記語言(如HTML)中,情況會怎么樣呢?在這種情況下,您必須處理像bronco這樣的文本。最后,還有一個問題,就是那些經(jīng)常使用但基本上毫無意義的單詞,像a、and和the。這些所謂的停用詞非常礙事。自然語言非常凌亂;在處理之前,需要對它們進(jìn)行整理。
幸運(yùn)的是,Python和NLTK讓您可以收拾這個爛攤子。在清單7中,RssItem類的normalized_words方法可以處理所有這些問題。請?zhí)貏e注意NLTK如何只使用一行代碼就能夠清潔嵌入式HTML標(biāo)記的原始文章文本!使用一個正則表達(dá)式刪除標(biāo)點(diǎn),然后每個單詞被拆分,并規(guī)范化為小寫。
清單7.RssItem類
classRssItem:
...
regex=re.compile('[%s]'%re.escape(string.punctuation))
...
defnormalized_words(self,article_text):
words=[]
oneline=article_text.replace('','')
cleaned=nltk.clean_html(oneline.strip())
toks1=cleaned.split()
fort1intoks1:
translated=self.regex.sub('',t1)
toks2=translated.split()
fort2intoks2:
t2s=t2.strip().lower()
ifself.stop_words.has_key(t2s):
pass
else:
words.append(t2s)
returnwords
只需這一行代碼就可以從NLTK獲得停用詞列表;并且還支持其他自然語言:
nltk.corpus.stopwords.words('english')
NLTK還提供了一些“詞干分析器”類,以便進(jìn)一步規(guī)范化單詞。請查看有關(guān)詞干、詞形歸并、句子結(jié)構(gòu)和語法的NLTK文檔,了解有關(guān)的更多信息。
使用NaiveBayes算法進(jìn)行分類
算法在NLTK中被廣泛使用并利用nltk.NaiveBayesClassifier類實(shí)現(xiàn)。Bayes算法根據(jù)特性在其數(shù)據(jù)集中的每個存在或不存在對項(xiàng)目進(jìn)行分類。在RSS提要項(xiàng)目的情況下,每一個特性都是自然語言的一個給定的(清潔過的)單詞。該算法是“樸實(shí)”的,因?yàn)樗僭O(shè)特性(在本例中,單詞)之間沒有任何關(guān)系。
然而,英語這種語言包含超過250,000個單詞。當(dāng)然,我不希望為了將RSS提要項(xiàng)目傳遞給算法就要為每個RSS提要項(xiàng)目創(chuàng)建一個包含250,000個布爾值的對象。那么,我會使用哪些單詞?簡單來說,答案是在培訓(xùn)數(shù)據(jù)組中除了停用詞之外最常見的單詞。NLTK提供了一個優(yōu)秀的類,即nltk.probability.FreqDist,我可以用它來識別這些最常用的單詞。在清單8中,collect_all_words方法返回來自所有培訓(xùn)文章的所有單詞的一個數(shù)組。
然后,此數(shù)組被傳遞給identify_top_words方法,以確定最頻繁的單詞。nltk.FreqDist類的一個有用的特性是,它實(shí)質(zhì)上是一個散列,但是它的鍵按其對應(yīng)的值或計(jì)數(shù)排序。因此,使用[:1000]Python語法可以輕松獲得最頻繁的1000個單詞。
清單8.使用nltk.FreqDist類
defcollect_all_words(self,items):
all_words=[]
foriteminitems:
forwinitem.all_words:
words.append(w)
returnall_words
defidentify_top_words(self,all_words):
freq_dist=nltk.FreqDist(w.lower()forwinall_words)
returnfreq_dist.keys()[:1000]
對于利用NLTKReuters文章數(shù)據(jù)模擬的RSS提要項(xiàng)目,我需要確定每個項(xiàng)目的類別。為此,我讀取前面提到的~/nltk_data/corpora/reuters/cats.txt文件。用Python讀取一個文件非常簡單,如下所示:
defread_reuters_metadata(self,cats_file):
f=open(cats_file,'r')
lines=f.readlines()
f.close()
returnlines
接下來的步驟是獲得每個RSS提要項(xiàng)目的特性。RssItem類的features方法(如下所示)可以做到這一點(diǎn)。在該方法中,在文章中的all_words數(shù)組首先被減少到一個較小的set對象,以消除重復(fù)的單詞。然后會遍歷top_words,并在該set中進(jìn)行比較,確定是否存在重復(fù)的單詞。隨后返回1000個布爾值組成的一個散列,以w_為鍵,后面是單詞本身。這個Python非常簡潔。
deffeatures(self,top_words):
word_set=set(self.all_words)
features={}
forwintop_words:
features["w_%s"%w]=(winword_set)
returnfeatures
接下來,我收集了訓(xùn)練集的RSS提要項(xiàng)目和它們各自的特性,并將它們傳遞給算法。清單9中的代碼演示了這個任務(wù)。請注意,分類器被訓(xùn)練成為只有一行代碼。
清單9.訓(xùn)練nltk.NaiveBayesClassifier
defclassify_reuters(self):
...
training_set=[]
foriteminrss_items:
features=item.features(top_words)
tup=(features,item.category)#tupisa2-elementtuple
featuresets.append(tup)
classifier=nltk.NaiveBayesClassifier.train(training_set)
NaiveBayesClassifier在運(yùn)行中的Python程序的內(nèi)存中,它現(xiàn)在是經(jīng)過訓(xùn)練的?,F(xiàn)在,我只需遍歷需要進(jìn)行分類的RSS提要項(xiàng)目集,并要求分類器猜測每個項(xiàng)目的類別。這很簡單。
foriteminrss_items_to_classify:
features=item.features(top_words)
category=classifier.classify(feat)
變得不那么樸實(shí)
如前所述,算法假設(shè)每個特性之間是沒有關(guān)系的。因此,像"machinelearning"和"learningmachine",或者"NewYorkJet"和"jettoNewYork"這樣的短語是等效的(to是一個停用詞)。在自然的語言上下文中,這些單詞之間有明顯的關(guān)系。所以,我怎么會讓算法變得“不那么天真”,并識別這些單詞的關(guān)系?
其中一個技巧是在特性集內(nèi)包括常見的雙字詞(兩個單詞為一組)和三字詞(三個單詞為一組)。NLTK以nltk.bigrams(...)和nltk.trigrams(...)的形式對此提供了支持,現(xiàn)在我們對此應(yīng)該不再感到驚訝了。正如可以從訓(xùn)練數(shù)據(jù)組收集最常用的n個單詞那樣,也可以識別最常用的雙字詞和三字詞,并將它們用作特性。
您的結(jié)果會有所不同
對數(shù)據(jù)和算法進(jìn)行完善是一門藝術(shù)。您是否應(yīng)該進(jìn)一步規(guī)范化單詞集,也許應(yīng)該包括詞根?或者包括超過1000個最常用單詞?少一點(diǎn)是否合適?或者是否應(yīng)該使用更大的訓(xùn)練數(shù)據(jù)集?是否應(yīng)該添加更多信用詞或“停用詞根”?這些都是您要問自己的正確問題。使用它們進(jìn)行實(shí)驗(yàn),通過試錯法,您可以會為您的數(shù)據(jù)實(shí)現(xiàn)最佳算法。我發(fā)現(xiàn),85%是一個很好的分類成功率。
利用k-NearestNeighbors算法提出建議
客戶希望顯示在選定類別或相似類別中的RSS提要項(xiàng)目?,F(xiàn)在,這些項(xiàng)目已經(jīng)用NaiveBayes算法進(jìn)行分類,這一要求的第一部分已得到了滿足。較難的部分是實(shí)現(xiàn)“或相似類別”的要求。這是機(jī)器學(xué)習(xí)建議器系統(tǒng)開始發(fā)揮作用的地方。建議器系統(tǒng)根據(jù)其他項(xiàng)目的相似性來建議一個項(xiàng)目。Amazon.com的產(chǎn)品建議和Facebook的朋友建議就是此功能的很好的示例。
k-NearestNeighbors(kNN)是最常用的建議算法。思路是向它提供一組標(biāo)簽(即類別),并且每個標(biāo)簽都對應(yīng)一個數(shù)據(jù)集。然后,該算法對各數(shù)據(jù)集進(jìn)行了比較,以識別相似的項(xiàng)目。數(shù)據(jù)集由多個數(shù)值數(shù)組構(gòu)成,數(shù)值的范圍往往被規(guī)范化為從0到1。然后,它可以從數(shù)據(jù)集識別相似的標(biāo)簽。與只產(chǎn)生一個結(jié)果的NaiveBayes不同,kNN可以產(chǎn)生一個有排名的列表,其中包含若干(即,k的值)個建議。
我發(fā)現(xiàn),建議器算法比分類算法更容易理解和實(shí)現(xiàn),但對于本文來說,其代碼過于冗長,并且有復(fù)雜的數(shù)學(xué),無法在這里詳述。請參閱由Manning出版的一本很好的新書MachineLearninginAction,獲取kNN編碼示例(請參閱參考資料中的鏈接)。在RSS提要項(xiàng)目實(shí)現(xiàn)的過程中,標(biāo)簽值是項(xiàng)目類別,而數(shù)據(jù)集是最常用的1000個單詞的值數(shù)組。同樣,在構(gòu)建這個數(shù)組時,一部分屬于科學(xué)范疇,一部分屬于數(shù)學(xué)范疇,還有一部分屬于藝術(shù)范疇。在數(shù)組中,每個單詞的值都可以是簡單的0或1的布爾值、文章中單詞出現(xiàn)次數(shù)的百分比、該百分比的指數(shù)值,或一些其他值。
結(jié)束語
探索Python、NLTK和機(jī)器學(xué)習(xí)一直是一個有趣的、令人愉快的經(jīng)驗(yàn)。Python語言強(qiáng)大而又簡潔,現(xiàn)在已成為我的開發(fā)工具包的核心部分。它非常適合于機(jī)器學(xué)習(xí)、自然語言和數(shù)學(xué)/科學(xué)應(yīng)用程序。雖然本文中并沒有提到,但我還發(fā)現(xiàn)Python對于圖表和繪圖非常有用。
以上內(nèi)容為大家介紹了探索Python、機(jī)器學(xué)習(xí)和NLTK庫,希望對大家有所幫助,如果想要了解更多Python相關(guān)知識,請關(guān)注多測師。http://m.2667701.com/