barefoot

技術のことを書いていく

業務で感じた「あ!これkaggleで見たやつだ!」

f:id:tenajima:20191221145615p:plain こちらの記事はKaggle Advent Calendar 2019の21日目の記事になります。
昨日の記事はあっきーさんさんのデータに含まれる異常値を検出してみようでした。

kaggleを始めたのが入社してからなのでそろそろ1年半くらい経過します。
kaggleを通して得た知見が実際の業務で「あ!これkaggleで見たやつだ!」ってなった例を紹介します。
これを通して「お、kaggle始めてみようかな」って人が出てくれたり、「あるある~、私はこういうところが役に立った」というつながりが生まれることを期待しています。

余談ですが、僕は某学習教材のマンガすごく好きでした。

はじめに

僕がどんな仕事をしているかが以下の記事に大きく関わってくるので紹介しておきます。
Fringe81という会社でアドネットワークの分析、アルゴリズムの開発や、UniposというHRプロダクトの分析、機能開発を行っています。
1年目が広告プロダクトの方を担当しており、2年目の現在がUniposを担当しています。
使うデータはテーブルデータが多く、kaggleでもテーブルコンペを好んで参加しています。

「あ!これkaggleで見たやつだ!」

評価指標

実務では「これで評価してね」ってのが天から降りてくることはないので、「この問題を解くのに必要な評価指標ってなんだろう?」って考えることからのスタートとなります。
その引き出しをたくさんつくっておけるという点でkaggleでいろんな指標を知っておくのは非常に有用だなと感じています。

AUC

圧倒的によく使っています。
正例と負例の偏りが大きいという場合のデータを扱うことが非常に多いのでAUCはよく参考にしています。

www.kaggle.com

RMSE

回帰問題のときにはよくつかいます。そりゃそうだってかんじかもしれませんが、よく使います。

www.kaggle.com

おまけ

次点でnDCGとF1スコアをたまーに使います。

pandas技

jsonを展開

テーブルの中身にjsonが入ってることというのは実務だとけっこうあることだと思います。
その際にjsonを適切にパースするということはkaggleでやっていたなぁと感じています。

以下のカーネルの初っ端でpandas.io.jsonjson_normalizeを使ったjsonのパースが行われているので是非参考にしてみてください。

www.kaggle.com

groupby

特徴量を作る際にいろんな作り方で特徴量を作っていて、そういったkernelを読んでいくのもすごく参考になります。
kaggleを始めてから知ったgroupby技を2つ紹介します。

import pandas as pd
df = pd.DataFrame({"name": ["hoge", "hoge", "fuga", "fuga", "fuga", "piyo", "piyo"], 
                  "score": pd.np.random.rand(7)})
df
name score
0 hoge 0.462346
1 hoge 0.837340
2 fuga 0.632214
3 fuga 0.599127
4 fuga 0.642452
5 piyo 0.125139
6 piyo 0.072438

いろんな統計量を一気にとるaggメソッド

agg = {"score": ["sum", "mean", "var"]}
df.groupby("name").agg(agg)
score
sum mean var
name
fuga 1.873793 0.624598 0.000513
hoge 1.299686 0.649843 0.070310
piyo 0.197577 0.098788 0.001389

pandas0.25からは次のようなこともできるようになりました。

df.groupby("name").agg(score_sum=("score", "sum"), tenajima=("score", "mean"))
score_sum tenajima
name
fuga 1.873793 0.624598
hoge 1.299686 0.649843
piyo 0.197577 0.098788

groupごとに処理をする

恥ずかしながらこれを最近まで知らなかったのですが、これめちゃくちゃ便利ですね...

for groupby_key, group_df in df.groupby('name'):
    print(f"{groupby_key}の平均値は{group_df['score'].mean()}だよ")
fugaの平均値は0.6245975900622805だよ
hogeの平均値は0.6498428673222854だよ
piyoの平均値は0.0987884793002905だよ

おまけ

ネットワークを考える際に、計算の都合上sourceとtargetのように有向グラフのように考えて計算しなきゃいけないのですが、実際に出したい値としてはsourceとtargetの値が逆でも同じ値という場合にMolecular Predictionコンペの以下のカーネルが参考になったのでおまけとしてあげさせてもらいます。

www.kaggle.com

その他で身についたこと

GCEまわりの扱い

kaggleで計算するときはGCEを使って計算しています。
そのため、リモートでコードを書きやすくするためにVS CodeのRemote Developmentを使える方法を調べていたのが業務でも参考になったり、 複数のインスタンスでチューニングするための環境設定の手間を減らすためにdockerfileを用意しておいたことが業務でも活きた経験があります。

Pipelineの設計について悩んだり実践していたこと

kaggleのコンペは2ヶ月くらい続く中で苦しくならない設計をしないと途中でしんどくなってしまいます。
そのために作ったPipelineや使っているフレームワークは業務でも活きています。
現在はluigiをラップして作られているgokartを使ってPipelineを作っています。また、gokartは業務でも使用しています。

github.com

まとめ

強いデータサイエンティストが集まるkaggleという場所で得られる知識というのはすごくたくさんあるなと日々感じています。
メダルや称号を目指しながら業務でも使えるtipsを得られるこのプラットフォームはすごく素敵なプラットフォームだと思います。
今後もたくさんDiscussionやkernelを読んでいろんなことを自分の身にしていきたいと思います。
そして次のKaggle Days Tokyoに参加できるよう精進していきます!

ここまで読んでいただきありがとうございました。Kaggle Advent Calendarはまだ続きます!
明日はJun Kodaさんです。引き続きお楽しみください!

Machine Learning Production Pitch #5に参加しました

f:id:tenajima:20191212212204j:plain

[更新] (12/13) 中川さんの資料追加しました

概要

2日前に続きMachine Learning Production Pitchに参加してきたので、その備忘録です。 資料追加されましたら順次更新したいと思っています。

machine-learning-pitch.connpass.com

イントロ

  • 発表したかったらtwitterとかでつぶやくと見つけてくれるとのこと

gokartの紹介とgokartで失敗した事例

レポジトリはこちら

github.com

自分メモ

  • いつも使ってます!
  • データエンジニアとして機械学習以外全部やってるとのこと
  • luigiをwrapしたもの
  • エムスリーの機械学習バッチは全てこれにしたがって書いている
  • 1つのタスクはrequires output run を実装するだけ
  • タスクが終わることにファイルを吐くという思想
  • 再実行時などは中間ファイルが再利用される
  • ワークフローが失敗した場合そこから利用できる
  • MLエンジニアが余計なことを考えなくてすむ
    • ログ、ジョブのslack通知など本質的でないけど重要な部分をライブラリ側でサポートしている
  • レビューが楽になる
    • 型にはまったコードになり、レビューする側も楽になる
  • AIチームでは全員が全員のコードをレビューしている
  • 以下失敗事例
  • 開発時に起こりがち
  • computer scienceで難しい2つのことは「キャッシュの無効化」と「名前付け」
  • コードが新しくなってるのにキャッシュが使われてジョブが失敗することが多数
  • MLエンジニアとDataエンジニアの境目に落ちる部分
  • 早い段階ですり合わせることが大切
  • そもそもキャッシュは人類には早すぎる
  • 以下質疑応答
  • なぜluigiベース?
    • DigdagはJVM依存だからやめる
    • airflowはcloud composerのバグを踏んで重厚すぎてやめた
    • 薄い感じで自分たちも触れる点でluigiにした
    • metaflowも触ってみている
  • luigiにプルリク出さないの?
    • dynamoまわりのやつ書いたけど、置いておいたら色々変わってそのままになってしまった
  • luigiとgokartの思想の違いは?
    • outputを省略できるとか
    • 詳しくはtwitter

フリーランスだらけのML基盤開発

自分メモ

  • 最近使っているプロダクトの構成

    • 1API-1レポジトリ
    • devデプロイはcircleCIで自動化
    • なるべくシンプルな作りにしている
      • ジョインコスト低減
      • 本質的な開発に専念
    • 一方でなるべくモダンにしている
      • 新しい仲間に来てもらうための環境づくり
  • フリーランスが多いプロジェクトの悩み

    • 人材サイクルの速さ
      • 3ヶ月、6ヶ月でいなくなることも
      • キャッチアップ中にエンジニアがいなくなることも...
    • 専門領域の違い
      • 必ずしもML/サーバーサイドの両方の知識があるわけではない
      • 機械学習エンジニアにAPIの実装や並列化を任せるのはむずい
      • サーバーサイドに性能指標などを任せるのはむずい...
      • 非専門領域に積極的とは限らない
      • コミュニケーションコストがつらい
    • 残されたMLコード管理
      • 前提とされるディレクトリ構造/正解ラベル形式
      • 単一の数字化しづらい性能評価
  • 講じた解決策

  • 関心外に関与してもらわなくても良い構造
  • 異なる専門間でのコミュニケーションを削減し負担を減らす

  • 質疑応答

    • フリーランスの情報の管理はどうしている?
      • 個人情報はマスクしている
      • properから提供されない
    • type hintで制御しきれなかった例は?
      • type hintだけでなくisinstanceで見に行っている

楽しむために楽するアーキテクチャ

www.slideshare.net

自分メモ

  • リサーチャーとキャッチアップして最新の技術をプロダクトに活かせないか考えている
  • プロダクトにフィットするアーキテクチャの考察
  • 忙しい仕事内容の中で楽しく仕事するために楽するアーキテクチャを構成したい
  • statefullとstatelessが混在しているのが特徴
  • 平日と土日では負荷状況が変わる
  • 土日に負荷が大きいが、サラリーマンなので土日は遊びたい
  • 気づいたらサービスが成長しているぜって安心してみてられる開発状況を保ちたい
  • サービスの形態に応じて変更を容易にする
  • 負荷に対してエラスティックにスケールする
  • 障害が起きても勝手に回復する
  • 変更性、拡張性、回復性
  • 動画解析をマイクロサービスのDAGとして実装している
  • DAGを組み替えれば変更も容易
  • それぞれのタスクをオートスケールできるようにする
  • 冪等性を保ちつつリトライする
  • statefullなやつが厄介
  • データの層とロジックの層を分けて、SearchとUpdateのみでやりとりさせる
  • 楽しむために楽をしよう

クックパッドでの機械学習デプロイ&データフロー

自分メモ

  • 材料名や手順の正規化後ほど
  • まずはjupyeter notebookをスクリプトにする
  • 実験フローの構造化
  • Dockerで動かせるようにする
  • 最低限のテストは書く
  • 教師データを継続的に管理する
  • 大量のデータを安全に取得する(サービスに負荷をかけないようにする)
  • Redshiftに安全にクエリをするような社内ツールを使っている(サービスに負荷をかけないようにする)
  • Queury
  • HTTP APIでクエリを発行できる内製ツール
  • 機械学習エンジニア自身でデプロイまでやる
  • Hakoというデプロイツールを使っている
  • ECS上で動作する
  • 機械学習はバッチで実行している
  • dmemoを使ってDB・スキーマにメモを書いている
  • 推論結果をちゃんと使ってもらえるようにしている(使ってもらわなきゃ意味がない)
  • 機械学習エンジニアが最後まで面倒をみる
  • マイクロサービス化されているので他に迷惑をかけない

  • 質疑応答

    • 社内ツールを運用するチームがあるの?
      • SREチームなどが担当してるOSSにしてるのでPRきたりする
    • ライブラリのバージョン違いで死ぬことを管理してます?
      • pipのバージョンをちゃんと指定しておく

まとめ

普段使っているgokartの失敗事例を聞けたのはすごく貴重でした。キャッシュ、注意します。
いかに機械学習部分に集中できる環境づくりをするかというのは本当に重要だなと感じる今週となりました。

Machine Learning Night に参加してきました

f:id:tenajima:20191210200754p:plain

[更新] - 12/11 PFN @dtaniwakiさんの資料を追加しました

概要

Machine Learning NIGHTに参加してきたので備忘録です。 ザーッと書いたので誤字等あれば修正していきます。 また、資料が追加されたら順次追加したいと思っています。 machine-learning-pitch.connpass.com

「なんじゃこのおもしろそうなイベントは!?」ということですぐに申し込んだ記憶があります。
あのPFNのオフィスで開催されるということに前日に気づきドキドキしました。
会議室のあるスペースしか見れてないですが、ポップな色づかいがにじみ出てオフィススペースも入ってみたいなぁと思いました。

LT

LTが2本ありました

行動ログデータからのユーザーアンケート予測モデルを作り、ユーザーの嗜好分類をする

自分メモ

  • 医師向けのQAサイト
  • 推薦システム的課題としてのコールドスタート
  • 1つのプロダクトが成長したら他のプロダクトも成長するような思想がある
  • プロダクト名が偉人の名前
  • 情報が素な部分をembeddingして密な形にする
  • MF
  • 言語的な近さではなく疾患などの近さがほしい
  • 推薦システムの成長とタグ付の成長が相互作用としてある

アンケートと組み合わせて説明可能なログ分析を行う

こちらも

www.m3tech.blog

自分メモ

  • アンケートの結果をレコメンドエンジンやデザインの出し分けに使えるのではという未来がある
  • 製薬会社などのクライアント企業にも活用できるのではということ
  • 行動ログ分析
  • 行動ログからアンケートの回答を予測するモデルを作れれば、回答してない人の部分も埋められるのでは?
  • ある程度予測できる!
  • バッチリ予測できるわけではないが傾向がつかめる程度は見れる

MerpayにおけるML活用のポイント

自分メモ

メルペイについて

  • 2017年設立
  • いろんなところで使える
  • 信用を創造して、なめらかな社会を創る

MLチームについて

  • Data platform、 DataAnalystがMachine learningチーム以外にある
  • マイクロサービスを創るまでが仕事
  • 8名のチーム
  • 課題発見からモデリング、マイクロサービスの提供までが役割
  • 各プロジェクトは2~4名で
  • GCP縛りがある
  • APIはGoで

主なプロジェクト

  • メルペイスマート払い
    • 過去の利用実績をもとに与信枠を付与して後払いで払える
    • ひとりひとりの与信枠をMLで予測している(kaggleっぽい!)
  • AML(マネーロンダリング対策)
    • 不正行為や疑わしい取引の監視をしている
    • ルールベースの仕組みの他にAIでも検知している

ビジネス貢献のために気をつけていること

  • 施策を円滑に進行するために

    • チームの3カ年のロードマップを作成する
    • MLチームなにやってるか分からないって言われないようにしている
  • ソフトウェアエンジニアとして課題を解く

    • 実務で使われるMLシステムは、精度のよいもでるだけでは不十分
    • tensorflow validationを使ってvalidationを行ってる
    • けっこうDBのスキームが変わるから↑
  • その他大切にしていること
    • ビジネスインパクトが大きい解くべき課題にフォーカスする
    • おねだりを安易に受けないようにする
    • ショートサイクルで漸進的に磨き込みをかける。1st versionを1~3ヶ月以内にリリースする
    • 問題に適した正しい技術選定を重視する
    • 非効率なルールを排除する

Preferred Networksの顧客向けプロダクト開発

www.slideshare.net

自分メモ

PFNの研究開発

  • 民間企業計算資源として国内最大級(すげぇ...)
  • 多様な研究領域がある
  • 高い技術力ベースに企業との共同研究が主体だった
  • 今年からプロダクト開発チームの発足
  • 得意とする分野は研究
  • 研究、開発 -> 事業化を担っている

プロダクtokaihatuti-munituite

プロダクト開発チームについて

全体インフラ構成

  • AWSに乗せている
  • 本番環境は顧客ごとに用意している
  • terraform & kustomizeで環境開発を容易にできるようにしている
  • jupyterからアプリケーションに移植するためにpython推論サーバーを作っている
  • フロントはReactとtsで、バックエンドはGo

sansan紹介

  • 出会いからイノベーションを生み出す をミッションにしている
  • 名刺のやりとりをフックできればビジネスシーンのかなりの部分をフックできる
  • 出会いのレコメンデーションを作っている
  • ブログをいつも楽しく読ませてもらってます

パネルディスカッション

どのように事業化に結びつけてきたの?

  • PFN
    • 研究が先にある
    • いろんな企業と研究して結果が出たら、企業の人と事業化を考える
  • merpay
    • サービス開始時からデータがたまる環境があった
    • ビジネスのコアを提案するというのを機械学習エンジニアから出すことに意識している
    • 他の人からの提案はちゃんと断る
  • m3
    • 分析しっかりしてルールベースで行ってからアルゴリズムを導入する

研究からと事業からの一長一短あるけど考え方の特徴とは?

  • merpay
    • MLエンジニアは新しいもの好きなので勝手にR&D始めるのである程度「事業」という縛りを強くしても良い
    • 今の技術で解決できないものも解決したいというモチベーションはすごくある
  • PFN
    • 研究から事業にならないことがないこともない
    • 相手企業にはやりたいことがあって始めるので闇雲に始めるわけではない

merpay -> PFN クライアントが問題設定して解けねーよってときどうするのか

  • PFN
    • プロダクト開発チームが早い段階で入って、視野を提供することで方向性を修正する

ルールベースからだと地に足ついたものになる?

  • m3
    • 10月入社の人がもう開発、販売までできてるのは速い、地に足ついてる
    • もっといろんなことしたいけどまずは目の前の課題を一つづつ

プロダクションに組み込むときにどこまでカバーする?

  • m3
    • やらなきゃいけない
    • 障害とかも対応する
    • ML部分は落ちやすいけどフロント側でけっこう吸収してもらう
  • merpay
    • バッチシステムの開発までする
    • オンラインではなく、バッチシステムにして運用負荷を下げている
  • PFN
    • 運用することがミッションではなく、研究の自動化とその研究が世の中の課題とマッチすること
    • 運用については今後

プロダクションコードまでMLエンジニアはやりたがっているの?

  • PFN
    • ちょっと特殊で研究系のエンジニアは本当に研究一点突破で開発はしない
    • 開発チームがそれをカバー
  • merpay
    • モデルだけやりたいって人はいない(現在8名)
    • 得手不得手がある部分はチーム構成でカバー
    • 会社ではビジネスコミットしつつ大学院行ってる人もいる
  • m3
    • プロダクションコードまでやってもらうよって言って採用している
    • 得手不得手ある中でみんながんばっている
    • ML側ならdocker、CI、CDまで作ってdockerfileをSREチーム渡すようにしている

ML系の周辺サービス、ツールが充実してきたがどう?

  • merpay
    • コンテナ技術の発達とマネージドサービスの進歩でやりやすくなってきた
  • m3
    • バッチ処理してAPI提供の部分が大きいので今の所まだ多様性がない
    • gokartによって型がきまっているのでそれに乗っかる部分が多い
  • PFN
    • sagemakerとかはまだ使ってない
    • モデルをS3にアップしてそれをロードして使っている

今解決したいけど、難易度が高い課題

  • PFN
    • 推論サーバーをどう作るか
    • 研究者と開発側が完全に別れているのでjupyter -> プロダクションへの変換を解決したい
    • マルチスレッドとかを研究者側が考えてなかったりして、エラーが起きるとかが生じている
  • merpay
    • 与信モデルなどで完全に自動化とかはしていない
    • 人間ロジックが少し入っている部分との融合
  • m3
    • プロダクト開発
    • ビジネス上の発見

まとめ

みなさんがMLやっていて感じる辛みを共感することができたり、感じている課題感を聞けてすごくためになりました。 懇親会もすごく楽しかったです。 懇親会でかかわってくださった方本当に温かくて感謝です。 またぜひ参加したいとおもいます!#mlpp

janomeとmecabのいいとこどりラッパーを作っている話

こちらの記事はFringe81 Advent Calendar 20197日目の記事です。前日は期待の新星@lilpacy[Elm] PortをTaskで定義する思考実験でした。

僕はFringeのデータ分析チームでUniposの分析、開発を行っているtenajimaといいます。この記事ではUniposの分析を行っていく上で僕が作ったmecabのラッパーを紹介したいと思います。

きっかけ

なら自分でつくろう
となりました。

その名もwakame!

github.com

pypi.org

思想

janomeの「me」の部分とmecabの派生からwakameにしました。僕がわかめ好きだからという理由ではありません。

wakameにできること

まずimportします

from wakame.tokenizer import Tokenizer
from wakame.analyzer import Analyzer
from wakame.charfilter import *
from wakame.tokenfilter import *

tokenizerはjanomeと同様に使い回すので、最初に1回だけインスタンス化します。今回はNEologdを使うようにします。

tokenizer = Tokenizer(use_neologd=True)

特定の品詞をとってくる

「私は阪神の糸原選手が大好きです」という文章があったとします。この単語から「阪神」や「近本」のように名詞は重要だけど「私」のような代名詞は取ってきたくないとすると以下のようにできます。

text = "私は阪神の糸原選手が大好きです"
token_filters = [POSKeepFilter(['名詞']),POSStopFilter(['名詞,代名詞'])]
analyzer = Analyzer(tokenizer, token_filters=token_filters)
for token in analyzer.analyze(text):
    print(token)
阪神  名詞,固有名詞,組織,*,*,*,阪神,ハンシン,ハンシン
糸原  名詞,固有名詞,人名,姓,*,*,糸原,イトハラ,イトハラ
選手  名詞,一般,*,*,*,*,選手,センシュ,センシュ
大好き   名詞,形容動詞語幹,*,*,*,*,大好き,ダイスキ,ダイスキ

surface部分のみ分かち書きもできます

print(analyzer.analyze(text, wakati=True))
['阪神', '糸原', '選手', '大好き']

情報をDataFrameで取得したい

普段pandasのデータフレームを扱うことが多い場合はDataFrameに変換するメソッドも用意しています。

print(analyzer.analyze_with_dataframe(text))
  surface part_of_speech infl_type infl_form base_form reading phonetic
0      阪神   名詞,固有名詞,組織,*         *         *        阪神    ハンシン     ハンシン
1      糸原   名詞,固有名詞,人名,姓         *         *        糸原    イトハラ     イトハラ
2      選手      名詞,一般,*,*         *         *        選手    センシュ     センシュ
3     大好き  名詞,形容動詞語幹,*,*         *         *       大好き    ダイスキ     ダイスキ

特定の品詞を変換したい

文章から特定の品詞を置き換えることもできます。これは名前などをマスクしてあげるときに便利です。

text = "阪神の鳥谷選手とヤクルトの青木選手は大学の同級生です。"
token_filters = [
    POSReplaceFilter(["名詞,固有名詞,組織"], "某チーム"),
    POSReplaceFilter(["名詞,固有名詞,人名"], "名無しさん"),
]
analyzer = Analyzer(tokenizer, token_filters=token_filters)
print("".join(analyzer.analyze(text, wakati=True)))
某チームの名無しさん選手と某チームの名無しさん選手は大学の同級生です。

その他にも...

janomeに実装されているFilterや、URLを取り除く(置き換える)Filterなども作っています。次はハッシュタグを取り除くFilterとか作ろうかなと思っています。

最後に僕の2019年のツイートでワードクラウドを作ってみる

細かいインストール方法などはここでは触れずに、どんな感じで使えるかというのを2019年の僕のツイートを題材にして見ていこうと思います。

twitterでデータリクエストするとどかっとデータがもらえるのでそれを使います。

import matplotlib.pyplot as plt
import pandas as pd
from IPython.display import Image, display_png
from sklearn.feature_extraction.text import TfidfVectorizer
from wakame.tokenizer import Tokenizer
from wakame.analyzer import Analyzer
from wakame.tokenfilter import POSKeepFilter, POSStopFilter, LowerCaseFilter
from wakame.charfilter import URLReplaceFilter
from wordcloud import WordCloud
tweet = pd.read_json("./twitter/tweet.js")

# 時間とテキストデータだけ取得する
tweet = tweet[["created_at", "full_text"]]
# UTC時刻になっているので日本時間にする
tweet["created_at"] = tweet["created_at"].map(lambda utc: utc.tz_convert("Asia/Tokyo"))
# 2019年のデータだけとってくる
tweet = tweet[tweet['created_at'] > '2019-01-01'].sort_values('created_at').reset_index(drop=True)
print(tweet.head(1))
                 created_at                                          full_text
0 2019-01-01 00:15:18+09:00  あけましておめでとうございます\n今年も今年とて好き勝手楽しんでまいりますのでよろしくお願い...

ちゃんとあけましておめでとうございますと言えているので良さそうですね

print(tweet.shape[0], "ツイート")
483 ツイート

今年は12月7日時点で483ツイートしてるので1日1ツイート以上していますね。

それではここからwakameの出番です。

tokenizer = Tokenizer(use_neologd=True)
char_filters = [URLReplaceFilter("")]
token_filters = [
    LowerCaseFilter(),
    POSKeepFilter(["名詞"]),
    POSStopFilter(
        # ここの指定は割と泥臭くやっています...
        ["名詞,接尾,人名", "名詞,非自立,一般", "名詞,非自立,一般", "名詞,副詞可能", "名詞,代名詞", "名詞,非自立,形容動詞語幹"]
    ),
]
analyzer = Analyzer(
    tokenizer=tokenizer, char_filters=char_filters, token_filters=token_filters
)

単語のスペース区切りの文字列を用意します

tweet["word"] = tweet["full_text"].map(
    lambda text: " ".join([token.base_form for token in analyzer.analyze(text)])
)

tf-idfを使って重要単語に重み付けを行います

vectorizer = TfidfVectorizer(min_df=3, stop_words=["retweet"])
vectorizer.fit(tweet["word"])
TfidfVectorizer(analyzer='word', binary=False, decode_error='strict',
                dtype=<class 'numpy.float64'>, encoding='utf-8',
                input='content', lowercase=True, max_df=1.0, max_features=None,
                min_df=3, ngram_range=(1, 1), norm='l2', preprocessor=None,
                smooth_idf=True, stop_words=['retweet'], strip_accents=None,
                sublinear_tf=False, token_pattern='(?u)\\b\\w\\w+\\b',
                tokenizer=None, use_idf=True, vocabulary=None)
vec = vectorizer.transform(tweet["word"])
importance = pd.DataFrame(vec.todense(), columns=vectorizer.get_feature_names()).sum()
wordcloud = WordCloud(
    width=480,
    height=320,
    background_color="white",
    font_path="/Users/tenajima/fonts/ipaexg.ttf",
    stopwords=set(stopwords),
)

wordcloud.fit_words(importance.to_dict())
wordcloud.to_file('wordcloud.png')
display_png(Image('./wordcloud.png'))

f:id:tenajima:20191207132355p:plain

こうやって振り返ってみると今年は確かに阪神最高でしたね。最後のCS滑り込みは感動でした。選手の名前もちょろちょろと入っていますね。「セクシー」とか入ってるのは某外国人助っ人のことを表しています(虎党にしか伝わらない...) 来シーズンが待ち遠しいです。 他にはPyConが目立ちますね。Pythonもあってよかった。

最後に

wakameはまだまだ至らぬところが多いですが、OSSとして公開していると「改善しよう」という気概が出るし、我が子のようにかわいいので作ってよかったなと感じています。また、修正や要望をすぐに反映できるフットワークの軽さがいいです。
まだドキュメントが整備されてないなどver1.0には遠いのですが、今後もかわいがって育てていこうと思っています。

さて、今回僕はこのへんで次は我らが巨匠ことkaz3284にバトンをつなぎます。
引き続きFringe81 Advent Calendar 2019をお楽しみください!

jupyter lab、これがないと辛くて耐えられない最低限のエクステンション

f:id:tenajima:20191130122700p:plain

概要

おすすめのjupyter labのエクステンションまとめはたくさんあるので、ここでは
「これがないと辛くて耐えられない」エクステンションをまとめておきたいと思います。
新しくvirtual envを作成してjupyter labを入れたらすぐさま入れないと辛いエクステンションたちです。
最低限入れたいのは2つ!

(※jupyter labでエクステンションを使うにはNode.jsが必要ですが、それは割愛します。また別でまとめるかも。)

1. jupyterlab-vim

github.com

jupyter上でvimライクな操作を行えるようにするものです。
新しいセルの追加などもvimライクに行えるものです。これがないとセルの追加などのショートカットも標準のままで頭がこんがらがってしまうので、必ずインストールしたいものです。

インストールは以下のコマンドで

jupyter labextension install jupyterlab_vim

2. jupyterlab_code_formatter

github.com

jupyterでformatterをかけられるエクステンションです。
実験コードはあんまりきれいに書こうと意識してないことが多いのでコードがざーっと長くなりがちです。
とはいえ、セルを横にスクロールしないと見れないのはすごく見づらいのでさっくりとなにも考えずにフォーマットをかけてもらえます。
これもないとセルがすごく見づらくなるので必ずインストールしたいエクステンションです。

インストールは以下のコマンドですが、別途自分が使いたいformatterをインストールしておく必要があります。 おすすめはblackです。

jupyter labextension install @ryantam626/jupyterlab_code_formatter
pip install jupyterlab_code_formatter
jupyter serverextension enable --py jupyterlab_code_formatter

まとめ

あんまりたくさんインストールするのも好きではないので、「これがないと辛くて耐えられない!」というエクステンションを慎重に少しずつ増やしていけたらいいなぁ。