1. 程式人生 > >用Python實現文件聚類

用Python實現文件聚類

title

在本教程中,我會利用 Python 來說明怎樣聚類一系列的文件。我所演示的例項會識別出 top 100 電影的(來自 IMDB 列表)劇情簡介的隱藏結構。關於這個例子的詳細討論在初始版本里。本教程包括:

  • 對所有劇情簡介分詞(tokenizing)和詞幹化(stemming)
  • 利用 tf-idf 將語料庫轉換為向量空間(vector space)
  • 計算每個文件間的餘弦距離(cosine distance)用以測量相似度
  • 利用 matplotlibmpld3 繪製輸出的聚類
  • 對語料庫進行Ward 聚類演算法生成層次聚類(hierarchical clustering)
  • 繪製 Ward 樹狀圖(Ward dendrogram)

整個專案在我的 github repo 都可以找到。其中‘cluster_analysis ‘工作簿是一個完整的版本;‘cluster_analysis_web’ 為了建立教程則經過了刪減。歡迎下載程式碼並使用‘cluster_analysis’ 進行單步除錯(step through)。

在此之前,我先在前面匯入所有需要用到的庫

Python
12345678 importnumpy asnpimportpandas aspdimportnltkimportreimportosimportcodecsfromsklearn importfeature_extractionimportmpld3

出於走查的目的,想象一下我有 2 個主要的列表:

  • ‘titles’:按照排名的影片名稱
  • ‘synopses’:對應片名列表的劇情簡介

我在 github 上 po 出來的完整工作簿已經匯入了上述列表,但是為了簡潔起見,我會直接使用它們。其中最最重要的是 ‘synopses’

列表了,‘titles’ 更多是作為了標記用的。

Python
12 printtitles[:10]#前 10 個片名
Python
1 ['The Godfather','The Shawshank Redemption',"Schindler's List",'Raging Bull','Casablanca',"One Flew Over the Cuckoo's Nest",'Gone with the Wind','Citizen Kane','The Wizard of Oz','Titanic']

停用詞,詞幹化與分詞

本節我將會定義一些函式對劇情簡介進行處理。首先,我載入 NLTK 的英文停用詞列表。停用詞是類似“a”,“the”,或者“in”這些無法傳達重要意義的詞。我相信除此之外還有更好的解釋。

Python
12 # 載入 nltk 的英文停用詞作為“stopwords”變數stopwords=nltk.corpus.stopwords.words('english')
Python
1 printstopwords[:10]
Python
1 ['i','me','my','myself','we','our','ours','ourselves','you','your']
Python
123 # 載入 nltk 的 SnowballStemmer 作為“stemmer”變數fromnltk.stem.snowball importSnowballStemmerstemmer=SnowballStemmer("english")

以下我定義了兩個函式:

  • tokenize_and_stem:對每個詞例(token)分詞(tokenizes)(將劇情簡介分割成單獨的詞或詞例列表)並詞幹化
  • tokenize_only: 分詞即可

我利用上述兩個函式建立了一個重要的字典,以防我在後續演算法中需要使用詞幹化後的詞(stems)。出於展示的目的,後面我又會將這些詞轉換回它們原本的的形式。猜猜看會怎樣,我實在想試試看!

Python
1234567891011121314151617181920212223 # 這裡我定義了一個分詞器(tokenizer)和詞幹分析器(stemmer),它們會輸出給定文字詞幹化後的詞集合deftokenize_and_stem(text):# 首先分句,接著分詞,而標點也會作為詞例存在tokens=[word forsent innltk.sent_tokenize(text)forword innltk.word_tokenize(sent)]filtered_tokens=[]# 過濾所有不含字母的詞例(例如:數字、純標點)fortokenintokens:ifre.search('[a-zA-Z]',token):filtered_tokens.append(token)stems=[stemmer.stem(t)fortinfiltered_tokens]returnstemsdeftokenize_only(text):# 首先分句,接著分詞,而標點也會作為詞例存在tokens=[word.lower()forsent innltk.sent_tokenize(text)forword innltk.word_tokenize(sent)]filtered_tokens=[]# 過濾所有不含字母的詞例(例如:數字、純標點)fortokenintokens:ifre.search('[a-zA-Z]',token):filtered_tokens.append(token)returnfiltered_tokens

接下來我會使用上述詞幹化/分詞和分詞函式遍歷劇情簡介列表以生成兩個詞彙表:經過詞幹化和僅僅經過分詞後。

Python
12345678910 # 非常不 pythonic,一點也不!# 擴充列表後變成了非常龐大的二維(flat)詞彙表totalvocab_stemmed=[]totalvocab_tokenized=[]foriinsynopses:allwords_stemmed=tokenize_and_stem(i)#對每個電影的劇情簡介進行分詞和詞幹化totalvocab_stemmed.extend(allwords_stemmed)# 擴充“totalvocab_stemmed”列表allwords_tokenized=tokenize_only(i)totalvocab_tokenized.extend(allwords_tokenized)

利用上述兩個列表,我建立了一個 pandas 的 DataFrame,以詞幹化後的詞彙表作為索引,分詞後的詞為列。這麼做便於觀察詞幹化後的詞轉換回完整的詞例。以下展示詞幹化後的詞變回原詞例是一對多(one to many)的過程:詞幹化後的“run”能夠關聯到“ran”,“runs”,“running”等等。在我看來這很棒——我非常願意將我需要觀察的詞幹化過後的詞轉換回第一個聯想到的詞例。

Python
12 vocab_frame=pd.DataFrame({'words':totalvocab_tokenized},index=totalvocab_stemmed)print'there are '+str(vocab_frame.shape[0])+' items in vocab_frame'
Python
1 there are312209items invocab_frame

你會注意到有些重複的地方。我可以把它清理掉,不過鑑於 DataFrame 只有 312209 項,並不是很龐大,可以用 stem-index 來觀察詞幹化後的詞。

Python
1 printvocab_frame.head()
Python
123456 wordsplot  plotedit  editedit  editedit  editon      on

Tf-idf 與文字相似度

下面,我定義詞頻-逆向檔案頻率(tf-idf)的向量化引數,把劇情簡介列表都轉換成 tf-idf 矩陣。

為了得到 TF-IDF 矩陣,首先計算詞在文件中的出現頻率,它會被轉換成文件-詞矩陣(dtm),也叫做詞頻(term frequency)矩陣。dtm 的例子如下圖所示:

tf-idf

接著使用 TF-IDF 權重:某些詞在某個文件中出現頻率高,在其他文中卻不常出現,那麼這些詞具有更高的 TF-IDF 權重,因為這些詞被認為在相關文件中攜帶更多資訊。

注意我下面定義的幾個引數:

  • max_df:這個給定特徵可以應用在 tf-idf 矩陣中,用以描述單詞在文件中的最高出現率。假設一個詞(term)在 80% 的文件中都出現過了,那它也許(在劇情簡介的語境裡)只攜帶非常少資訊。
  • min_df:可以是一個整數(例如5)。意味著單詞必須在 5 個以上的文件中出現才會被納入考慮。在這裡我設定為 0.2;即單詞至少在 20% 的文件中出現 。因為我發現如果我設定更小的 min_df,最終會得到基於姓名的聚類(clustering)——舉個例子,好幾部電影的簡介劇情中老出現“Michael”或者“Tom”這些名字,然而它們卻不攜帶什麼真實意義。
  • ngram_range:這個引數將用來觀察一元模型(unigrams),二元模型( bigrams) 和三元模型(trigrams)。參考n元模型(n-grams)
Python
1234567891011 fromsklearn.feature_extraction.text importTfidfVectorizer# 定義向量化引數tfidf_vectorizer=TfidfVectorizer(max_df=0.8,max_features=200000,min_df=0.2,stop_words='english',use_idf=True,tokenizer=tokenize_and_stem,ngram_range=(1,3))%timetfidf_matrix=tfidf_vectorizer.fit_transform(synopses)# 向量化劇情簡介文字print(tfidf_matrix.shape)
Python
123 CPU times:user29.1s,sys:468ms,total:29.6sWall time:37.8s(100,563)

“terms” 這個變數只是 tf-idf 矩陣中的特徵(features)表,也是一個詞彙表。

Python
1 terms=tfidf_vectorizer.get_feature_names()

dist 變數被定義為 1 – 每個文件的餘弦相似度。餘弦相似度用以和 tf-idf 相互參照評價。可以評價全文(劇情簡介)中文件與文件間的相似度。被 1 減去是為了確保我稍後能在歐氏(euclidean)平面(二維平面)中繪製餘弦距離。

注意 dist 可以用以評估任意兩個或多個劇情簡介間的相似度。

Python
12 fromsklearn.metrics.pairwise importcosine_similaritydist=1-cosine_similarity(tfidf_matrix)

K-means 聚類

下面開始好玩的部分。利用 tf-idf 矩陣,你可以跑一長串聚類演算法來更好地理解劇情簡介集裡的隱藏結構。我首先用 k-means 演算法。這個演算法需要先設定聚類的數目(我設定為 5)。每個觀測物件(observation)都會被分配到一個聚類,這也叫做聚類分配(cluster assignment)。這樣做是為了使組內平方和最小。接下來,聚類過的物件通過計算來確定新的聚類質心(centroid)。然後,物件將被重新分配到聚類,在下一次迭代操作中質心也會被重新計算,直到演算法收斂。

跑了幾次這個演算法以後我發現得到全域性最優解(global optimum)的機率要比區域性最優解(local optimum)大。

Python
12345678910 fromsklearn.cluster importKMeans

相關推薦

Python實現

在本教程中,我會利用 Python 來說明怎樣聚類一系列的文件。我所演示的例項會識別出 top 100 電影的(來自 IMDB 列表)劇情簡介的隱藏結構。關於這個例子的詳細討論在初始版本里。本教程包括: 對所有劇情簡介分詞(tokenizing)和詞幹化(stemming)

python計算行數[裝載自http://www.centoscn.com/python/2013/0806/1110.html]

緩存 scn adl 讀取 col bsp 支持 p s file 一、計算文件的行數 最簡單的辦法是把文件讀入一個大的列表中,然後統計列表的長度.如果文件的路徑是以參數的形式filepath傳遞的,那麽只用一行代碼就可以完成我們的需求了: count = le

python實現夾遍歷

問題 dirname 元組 一個 操作 目錄下的文件 exist exists lena python 中os.path模塊用於操作文件或文件夾 os.path.exists(path) 判斷文件路徑是否存在 dir = "c:\windows"if os.path.exi

python實現一個層次方法

mac ima 優先隊列 () don 標簽 中位數 filepath normal 層次聚類(Hierarchical Clustering) 一.概念   層次聚類不需要指定聚類的數目,首先它是將數據中的每個實例看作一個類,然後將最相似的兩個類合並,該過程叠代計算只到剩

python實現命名

獲取 his highlight 文件名 for sta python實現 去除 light # coding:utf-8 ‘‘‘ 將文件名稱重命名 將上級的文件名稱添加到文件名稱中 ‘‘‘ import os file_path1 = r"

Python:實現歸檔

目錄 備份 實現功能: 將E:\123文件備份至E:\backup 文件夾下,以當前的日期為子目錄存放備份後的文件 1 #! /usr/bin/python 2 #Filename:backup.py 3 #功能說明:備份文件,以當前日期為子目錄存放備份後的文件 4 5 import os

python 替換中的git地址

python AC IT bin pla pan line utf encoding 有個需求要替換文件中git地址,要替換成的git地址是一個變量 本來想用sed替換但是git地址中有斜杠符號 需要轉義,提前知道還好弄,如果是變量就不好處理了 #!/usr/bin/py

使用Python 實現的上傳與下載

sport .get close OS imp down tran oca word 1,使用到Python的paramiko模塊 2,下面直接上代碼 import paramiko localpath =r‘/tmp/a.txt‘remotepath = r‘/mn

如何優雅的使用 Python 實現遞歸遍歷

globals 功能實現 lln 文件夾 except 如果 yield 優雅 files 今天有個腳本需要遍歷獲取某指定文件夾下面的所有文件,我記得很早前也實現過文件遍歷和目錄遍歷的功能,於是找來看一看,嘿,不看不知道,看了嚇一跳,原來之前我竟然用了這麽搓的實現。 先發出

c#實現的讀取和系列操作

static filename ros ima git int lin {0} ase Gitee代碼鏈接:https://gitee.com/hyr5201314/workcount 1.解題思路 首先要先讀取文件,然後調用函數實現返回文件的字符數,行數,單詞總數。用

python實現mean-shift演算法

新建MeanShift.py檔案 import numpy as np # 定義 預先設定 的閾值 STOP_THRESHOLD = 1e-4 CLUSTER_THRESHOLD = 1e-1 # 定義度量函式 def distance(a, b):

java實現加密解密

文件加密 import java.io.*; public class ToSecret { public static void main(String[] args) throws Exception { FileInputStre

利用Python實現K-Means並進行圖形化展示

利用K-means進行聚類,顯示聚類結果的各類別的數量,最終進行圖形化展示 。 import pandas as pd import numpy as np import matplotlib.pyplot as plt from scipy import stats import c

Python實現K-Means演算法

       宣告:程式碼的執行環境為Python3。Python3與Python2在一些細節上會有所不同,希望廣大讀者注意。本部落格以程式碼為主,程式碼中會有詳細的註釋。相關文章將會發布在我的個人部落格專欄《Python從入門到深度學習》,歡迎大家關注~

第11章 K-means(分析)

載入資料集 已標記好類別的四個文件資料集:(網路安全,電子學,醫學medical,太空) import matplotlib.pyplot as plt import numpy as np from time import time from sklearn.datasets

python實現Kmeans文字,通過PCA降維和Matplotlib顯示3d三維影象

首先感謝Eastmount寫的內容http://blog.csdn.net/Eastmount/article/details/50545937。點選開啟連結 在此基礎上,主要實現以下改進及結果 1.替換使用sklearn.feature_extraction.text.T

對比,SPSS/SPSS modeler/python 實現FRM,模型的使用者感受

SPSS計算FRM模型分值在spss的直銷模組下,可以對客戶資料進行FRM計算客戶的FRM的分值,1.交易資料                                                                                   

Flask+python實現上傳功能

type doc 文件上傳 pat path NPU ctype val success import os from flask import Flask, request from werkzeug import secure_filename # 獲取上傳

python實現讀取xml內容

import xlrd filePath = "E:\\python.xlsx" worksheet = xlrd.open_workbook(filePath) sheet_names = worksheet.sheet_names() for sh_name in sheet_names:

python調

color clas print .py cnblogs pat div class sys test_import_file.py,在當前目錄 import sys sys.path.append("..") import hello hello.printHell