soy-curd's blog

へぼプログラマーです [https://twitter.com/soycurd1]

PyCon JP 2015 カンファレンス二日目のメモ

pyconカンファレンス二日目のメモ。

keynote

BeProud、名刺に『魔法使い』とか役職を書くのがクレイジーで良い。 また、エンジニアが不安を乗り越える方法として、『技術力を身につける』というのが、 実践的だと感じた。

パネルディスカッション

えふしんさんとかが登壇。pythonを使い続けてエンジニアとしての市場価値が上がるか、など。 pythonレバレッジかける、とか言っていて、そういう言い方が最近流行っているのかな、と思った。 perlの転職エコシステムの説明で、perlの人はオンザエッジとmixiはてなの間だけで転職する、みたいな 話が面白かった。

カンファレンス

以下はスライドのメモ。公開されてるかどうかはまだチェックしてない。

Python で作って学ぶ形態素解析

janomeの話。

  • Janomeとは

    • Pure Pythonで書かれた、辞書内包の形態素解析器。
    • 辞書、言語モデルmecab-ipadicを使用
    • だいたいMeCabと同じ結果になる
    • 標準ライブラリのみを使用
    • ユーザ辞書サポート
      • 単語追加が試せる
  • 形態素解析

    • 形態素の列に分割し、それぞれの品詞を判別する
  • アルゴリズム

    • 辞書と言語モデルmecab-ipadicから借用
    • Janomeでは解析エンジン部分を実装している
      • 辞書引き
      • 解析実行
  • 辞書引き

    • ハッシュマップでもいいが...
    • Janomeは顧問プレフィックスマッチを用いている ("さくら"という文字列から"さ"、"さく"、... 等を一度に引くことができるデータ構造)

    • パトリシア木(JUMAN)

    • ダブル配列(Chasen
    • FST(Kuromoji, Lucene, Janome
  • FST

    • FSTを図解していた。
  • 解析

  • 開発

    • FST & 内包システム辞書の実装
    • FSTは「辺のあつまり」と見てバイナリにする。
      • 辞書エントリの詳細情報はFSTとは別ファイルにもつ
    • 隣接コストは二次元配列にして保存
  • 辞書サイズ

    • 13MB
  • 遅いところ

    • 辞書引き
    • 隣接コスト検索
    • ラティスのノード作成
  • 2/3系

    • string, bytesの非互換対応をすれば2系対応できた。

セカイノカオ by チーム・カオ

アート * Python

  • 東京都現代美術館

    • 会田誠と組んでやっている
    • 映像 + お面
  • Marsface Project

    • 火星に顔を探すプロジェクト
  • たくさんの顔が欲しい

    • TSVの47.7GBのCreativeCommons画像データがある。
  • カオ解析プロセス

    • カオ検出
    • 表情検出
      • CNNs(Convolutional Nerral Networks)
  • 地図上に表示

    • Leaflet:JSの地図データ関連のライブラリ
    • Folium = Python + Leaflet
    • -> 地図上に笑顔、泣き顔、怒り顔の分布が可視化されてる!(やばい)

アドネットワークのデータ解析チームを支える技術

VOYAGE GROUPの人。 + Zucksを作っている。

Ad Networkとは

  • 広告主とメディアを束ねて配信する仕組み。
  • Zucks Ad Network
    • コンバージョンがあると、CPC課金が生じる

データ解析チームの業務

  • 配信ロジックの改良
  • コンバージョン率を求めたい

    • マルチタスク学習、転移学習
    • 広告枠と相性の良い広告を探す:多腕バンディッド問題
    • 人と相性の良い広告を探す:CTR予測、ロジスティック回帰
    • 広告予算の有効活用:線形計画問題
  • 業務内容

    • 基盤構築
    • 施策検討
  • Pythonの使いところ

    • データ取り込み
    • 調査・実験・レポート
    • Ansible

分析基盤の構築

  • 方針

    • とりあえずGoogle BigQuery(DBサービス)に入れる
    • 配信システムに影響を与えないようにする
      • AWSのアカウントを分離
    • 雑に作り、雑に動かす
  • 稼働後にリリースされたもの

    • Embulk
    • ...
  • pandas.io.gbq

    • 一瞬でPandasの世界に行ける
  • 画面

    • BigQueryのWebUI

調査・実験

レポート

  • クリックログについて確率分布を比較
  • .ipynbファイルをGitHUbにpushするだけ(GitHub上でレンダリングされるようになった)

おわりに

トレンドを追えた雰囲気を感じれたので良かった。来年も参加したい。最後にPyConに参加してたゆるキャラの写真を貼って終わります。

PyCon JP 2015に行ってきた

PyCon JP 2015に行ってきた。 一日話聞いてる中で、ElastickSearchの話が三つくらいあったので、恐らく流行っているのだと思う。 今度暇な時に触ってみたい。

tseというpythonワンライナー書くツールの話は、超人気で床に直座りしないと聴けなかった。 内容はtseのチュートリアル的なかんじだったのだけれど、最後にBeautifulSoupをワンライナーで使うサンプルがチラ見していて、ワンライナー勢の執念を感じた。

最後の懇親会が良くて、いろんな人と話せるかんじで良い。適当に人を捕まえて適当に話すかんじ。 懇親会の途中でBeProudの人の話を聞いていた時が、最も知見が溜まって良かった。 ビールもたくさん飲めたので非常に良い日だった。

Pythonプロフェッショナルプログラミング 第2版

Pythonプロフェッショナルプログラミング 第2版

自動要約プログラムshucaを使ってニ郎コピペを要約した

はじめに

2chまとめを読んでいたら、"長い"みたいなレスを投げられていた二郎コピペがあった。せっかく名文なのに長いの一言で一蹴されては報われないので、日本語の自動要約をしてくれるshucaを用いて短く要約してみた。

shucaとは?

github.com

python2系で動く自動要約プログラム。shuca単体では動作せず、他に京大で開発されているjuman(形態素解析プログラム)とknp(構文解析プログラム)が必要。

実際に要約してみる

まずはコピペを以下から拾ってくる。

fullopen.blog.jp

■その50
今日、ついに二郎デビューしたんでレポっす!

川崎店に行ったらすごい行列でまずびっくり!
すっげえな!と思って店の中を見て、
みんなが食ってるラーメンのボリュームを見てまたびっくり!
これが二郎・・・と、思わずヨダレが出る。
待つ事20分、やっと席につくことができた。
「ヤサイマシマシ、ニンニクチョモランマ!」並んで待っている間に、
他の客から呪文はラーニングしていた。
聞き返されることなく店主にコールが伝わり、ただそれだけの事が嬉しい・・・!
イカンイカン、食う前から俺、既に二郎にハマっとるw
すると、俺より1分遅れて左側の席に着いたやつが、トントンと俺の肩を叩く。
「キミ、大豚頼んだでしょ。バトルしようよ。」と、
大豚はおまえだろ、と突っ込みたくなるような
デブが話しかけてきた。・・・バトル?何いきなり言ってきてるんだこいつ。
「ここ、ラーメン屋ですよね?バトルってどういうことですか?」
と聞き返すとその大豚は呆れ顔で
「へぁ?二郎って言ったらバトルは常識っしょ。
あ、キミのホームではデュエルって言うのかなw」
とブヒブヒ笑っている。

そこでハッと、俺はいつか見た二郎コピペを思い出した。
そうだ・・・あそこにも確か、バトルがどうのこうの書いてあったな・・・。
ここでバトルを断ったら、ロット乱し(?)と思われてしまうかもしれない・・・!
「OK、そのバトル受けよう。開始の合図は?」
「ブヒヒ。合図もなにも、目の前に二郎が出てきたらバトルスタートだよ。」
なるほどそういうものか。
そのとき、ドンッ!と目の前に野菜山盛りの二郎が置かれた。
バトルスタートだ!
すかさず俺は、左ひじを大豚の顔面に思い切り叩き込む。飛び散る血しぶき。
大豚の脂ぎった髪の毛をつかみ、何度もみぞおち目掛けヒザをブチ込む。
よろける大豚の軸足を正面から蹴りつけると、
ボクッ!っといい音がして脚の骨が砕けた。
大豚が床に突っ伏し、ぴくりとも動かなくなるまでわき腹を蹴り続けた後、
俺はゆうゆうと激ウマ二郎を二人分たいらげ、店主に軽く会釈して店を出た。
初二郎でしかもバトル勝利のおまけつき!二郎最高ー!

以上、チラ裏っす。

確かに長いかもしれないので、要約してみる。

インストール手順は以下(履歴の切り貼りなので適宜調節してください)。

その後、解析したい文章を適当なファイル(下例ではtmp.txt)に格納し、

cat tmp.txt |juman |knp -simple -anaphora | ./lib/Shuca.py 

すれば結果がとれる。

解析結果

■その50
今日、ついに二郎デビューしたんでレポっす!

これが二郎・・・と、思わずヨダレが出る。
「へぁ?二郎って言ったらバトルは常識っしょ。

そこでハッと、俺はいつか見た二郎コピペを思い出した。
「ブヒヒ。合図もなにも、目の前に二郎が出てきたらバトルスタートだよ。」
俺はゆうゆうと激ウマ二郎を二人分たいらげ、店主に軽く会釈して店を出た。
初二郎でしかもバトル勝利のおまけつき!二郎最高ー!

以上、チラ裏っす。

確かに、短くなった。 ストーリーがカットされているぶん、文章の勢いが増した気がする。『バトルスタートだよ→ゆうゆうと激ウマ二郎を二人分たいらげ〜』のくだりが非常に楽しい。

終わりに

他にもいろいろな文章で試してみたいが、knpが結構解析に時間かかるっぽいので試行錯誤中です。

入門 自然言語処理

入門 自然言語処理

python3で自然言語処理100本ノックの最初のほう その3

今日は正規表現のとこをやった。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
import json
import re


def main():
    filename = sys.argv[1]

    json_list = read_json(filename)
    text = abstract_england(json_list)
    print(text)

    category_obj = abstract_category(text)
    [print(x) for x in category_obj]

    [print(x) for x in abstract_categoryname(abstract_category(text))]

    [print(x) for x in abstract_section(text)]


# 20 JSONデータの読み込み
def read_json(filename):
    '''
    wikiのjsonを読み込む。
    記事毎のjsonデータをリストで返す。
    '''
    with open(filename, mode='r') as f:
        articles = f.readlines()

    data = [json.loads(x) for x in articles]
    return data


def abstract_england(json_list):
    return next(filter(lambda x: x['title'] == "イギリス", json_list))['text']


# 21 カテゴリ名を含む行を抽出
def abstract_category(text):
    texts = text.split("\n")
    pattern = r"Category"
    return filter(lambda x:re.search(pattern, x), texts)


# 22 カテゴリ名の抽出
def abstract_categoryname(text_iter):
    return map(search_categoryname, text_iter)


def search_categoryname(text):
    start = len("[[Category:")
    end = len("]]")
    return text[start:-end]


# 23 セクション構造
def abstract_section(text):
    texts = text.split("\n")
    return filter(lambda x:x, map(search_section, texts))


def search_section(text):
    pattern = r"^=+"
    match = re.search(pattern, text)
    if match:
        cnt = match.end()
        return (text[cnt:len(text) - cnt], cnt - 1)
    else:
        return None


if __name__=='__main__':
    main()

なにげにjsonのロードで詰まってしまった。このjson、行毎に別々にデコードする必要があるっぽい。解析する前にちゃんとデータ構造を確認しよう、が今回の教訓。

python3で言語処理100本ノックの最初のほう

以下のかんじ。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from functools import *

def main():
    print(revstr("mojimoji"))
    print(patoka("パタトクカシーー"))
    print(patatokukasi("パトカー", "タクシー"))
    print(pi("Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."))
    pp(element("Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can.",
               [1, 5, 6, 7, 8, 9, 15, 16, 19]))


# 00 文字列の逆順
def revstr(moji):
    return moji[::-1]


# 01 ぱたとくかしーー
def patoka(string):
    ret = ""
    for i, x in enumerate(string):
        if i%2 == 0:
            ret = ret + x

    return ret


# 02 ぱたとくかしーー2
def patatokukasi(str1, str2):
    strings = zip(str1, str2)
    return reduce(lambda a, x: a + x[0] + x[1], strings, "")


# 03 円周率
def pi(string):
    nodot_txt = string.replace(".", "")
    nocommma_txt = nodot_txt.replace(",", "")
    splited_txt = nocommma_txt.split(" ")
    return list(map(len, splited_txt))


# 04 元素記号
def element(string, indexes):
    nodot_txt = string.replace(".", "")
    splited_txt = nodot_txt.split(" ")

    element_map = {}
    for i, x in enumerate(splited_txt):
        if i + 1 in indexes:
            element_map[x[0]] = i + 1
        else:
            element_map[x[:2]] = i + 1

    return element_map


def pp(foo):
    if foo is list:
        map(pp, foo)
    elif foo is dict:
        map(pp, foo)
    else:
        print(foo)


if __name__=='__main__':
    main()

python3、reduceデフォルトで使えなくてびびった。ぱたとくかしー。