Evaluate the Topic Model

Preparation


In [3]:
# enable showing matplotlib image inline
%matplotlib inline

# autoreload module
%load_ext autoreload
%autoreload 2

PROJECT_ROOT = "/"

def load_local_package():
    import os
    import sys
    root = os.path.join(os.getcwd(), "../../")
    sys.path.append(root)  # load project root
    return root

PROJECT_ROOT = load_local_package()

Load Topic Model


In [4]:
def load_corpus(file_name, test_size=0.3):
    import os
    from pola.machine.topic_model import GTopicModel
    
    path = os.path.join(PROJECT_ROOT, "./data/" + file_name)
    m = GTopicModel.load(path)    
    return m

model = load_corpus("cityspots_doc_edited_model.gensim")

Evaluate Topic Model


In [5]:
# show its perplexity
print("topic count is {0}. perplexity is {1}".format(model.topic_count, model.perplexity()))


topic count is 2. perplexity is 357.3167026134721

Visualize Topic Model

Check the distance between each topic

If we success to categorize the documents well, then the distance of each topic should be far apart.


In [6]:
def plot_distance_matrix(m):
    import numpy as np
    import matplotlib.pylab as plt
    
    # make distance matrix
    mt = []
    for i in range(m.topic_count):
        d = m.calc_distances(i)
        d = sorted(d, key=lambda _d: _d[0])
        d.insert(i, (i, 0))
        d = [_d[1] for _d in d]
        mt.append(d)

    mt = np.array(mt)
    
    # plot matrix
    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1)
    ax.set_aspect("equal")
    plt.imshow(mt, interpolation="nearest", cmap=plt.cm.ocean)
    plt.yticks(range(mt.shape[0]))
    plt.xticks(range(mt.shape[1]))
    plt.colorbar()
    plt.show()


plot_distance_matrix(model)


Check the topics in documents

If we success to categorize the documents well, each document has one mainly topic.


In [7]:
def show_document_topics(m, sample_size=200, width=1):
    import random
    import numpy as np
    import matplotlib.pylab as plt

    # make document/topics matrix
    document_topics = []
    samples = random.sample(range(len(m.doc.archives)), sample_size)
    for i in samples:
        ts = m.get_document_topics(i)
        document_topics.append([v[1] for v in ts])
    
    document_topics = np.array(document_topics)
    # draw cumulative bar chart
    fig = plt.figure(figsize=(20, 3))
    N, K = document_topics.shape
    indices = np.arange(N)
    height = np.zeros(N)
    bar = []
    for k in range(K):
        color = plt.cm.coolwarm(k / K, 1)
        p = plt.bar(indices, document_topics[:, k], width, bottom=None if k == 0 else height, color=color)
        height += document_topics[:, k]
        bar.append(p)
    
    plt.ylim((0, 1))
    plt.xlim((0, document_topics.shape[0]))
    topic_labels = ['Topic #{}'.format(k) for k in range(K)]
    plt.legend([b[0] for b in bar], topic_labels)
    plt.show(bar)

show_document_topics(model)


Visualize words in topics

To consider about the name of topic, show the words in topics.


In [8]:
def visualize_topic(m, word_count=10, fontsize_base=10):
    import matplotlib.pylab as plt
    from matplotlib.font_manager import FontProperties
    font = lambda s: FontProperties(fname=r'C:\Windows\Fonts\meiryo.ttc', size=s)

    # get words in topic
    topic_words = []
    for t in range(m.topic_count):
        words = m.get_topic_words(t, topn=word_count)
        topic_words.append(words)
    
    # plot words
    fig = plt.figure(figsize=(8, 5))
    for i, ws in enumerate(topic_words):
        sub = fig.add_subplot(1, m.topic_count, i + 1)
        plt.ylim(0, word_count + 0.5)
        plt.xticks([])
        plt.yticks([])
        plt.title("Topic #{}".format(i))
        
        for j, (share, word) in enumerate(ws):
            size = fontsize_base + (fontsize_base * share * 2)
            w = "%s(%1.3f)" % (word, share)
            plt.text(0.3, word_count-j-0.5, w, ha="left", fontproperties=font(size))
    
    plt.tight_layout()
    plt.show()

    
def show_city_spots(m, show_count=5):
    import os
    from application.models.spot import CitySpots
    
    path = os.path.join(PROJECT_ROOT, "./data/spots.json")
    cityspots = CitySpots.load(path)
    print(len(cityspots))
    
    for t in range(m.topic_count):
        indices = m.get_topic_documents(t)
        print("show topic {0} city spots".format(t))
        for i, r in indices[:show_count]:
            print("({0}): {1}".format(r, cityspots[i].city.name))
            for s in cityspots[i].spots:
                print("\t {0}".format(s.title))

visualize_topic(model)
show_city_spots(model)


311
show topic 0 city spots
(0.9956367990633604): ブルージュ
	 当時の栄華を伝える建造物や絵画を鑑賞
	 「北のベニス」と呼ばれる美しい街
(0.9942980996344052): ジャマイカ
	 豊かな水源が育む緑あふれるリゾート
	 滝を上って天然ウォータースライダー遊び
(0.9933328382846518): 拉薩(ラサ)
	 チベット仏教発祥地、ラサ三大寺院のひとつ
	 ダライ・ラマの夏の離宮は人々の憩いの場
	 ダライ・ラマの黄金の宮殿、チベットの華
	 世界的規模の大僧院は歴代ダライラマの母寺
	 チベット人の聖地と仲見世・巡礼の街
(0.9933081708614864): マンチェスター
	 イギリス最初のサッカー博物館
(0.9931186558707628): オークランド
	 登山、スキー、北島のアウトドアの中心地
	 露天風呂もある温泉レジャー施設
	 洞窟の暗闇に浮かぶ幻想的なツチボタルの光
	 まさに地球の鼓動、豪快に噴き上げる間欠泉
show topic 1 city spots
(0.9969898447129556): ロサンゼルス
	 山と湖が織りなす雄大な自然を堪能
	 宝石をちりばめたようなLAの夜景を観賞
	 海辺やお洒落な通りは1日かけて遊びたい
	 長寿の巨木セコイアが見どころの国立公園
	 ワールドプレミアが行われる中国風映画館
	 おもしろハリウッド映画をライドで体験
	 ファンタジーの世界が現実になった遊園地
	 水のない高温の盆地にできた死の谷
	 ドジャードッグや寿司をほおばり野球観戦
	 映画スターが豪邸を構える高級住宅街
	 世界最大の停泊数を誇る洗練されたマリーナ
	 映画にちなんだハイテクなアトラクション
	 プリティウーマンよろしく高級店でお買い物
(0.9963723531498054): パース
	 イルカと泳げるドルフィンパラダイス
	 小さな白い二枚貝でできた不思議なビーチ
	 海を思わせる穏やかな川をリバークルーズ
	 地球がつくった幻想的な光景が見られる入江
	 自然の驚異を感じずにはいられない奇岩群
	 開拓時代の港町の面影を残す平和な街
	 母子で遊びにくるイルカにタッチ!
	 車乗り入れ禁止の島は野生のクオッカが名物
(0.9946031771476381): ハミルトン島
	 青い海に浮かぶハート型を上空から眺めよう
	 真っ青な海に弧を描く純白のビーチ
(0.9942654820476103): ポカラ
	 白き神々の座、登山家憧れのヒマラヤ山脈
(0.993640437056423): ストラトフォードアポンエイボン
	 中世の英雄ロビン・フッドが活躍した舞台
	 シェークスピアが洗礼を受け、永眠する教会

In [ ]: