Pythonで文字列から全角や半角の記号を全て取り除く
そんな方法はない。普通なら。
半角記号のみであれば正規表現で取り除くことは可能ですが、
Twitterやブログなどのあまりきれいでない文章を扱う場合、日本語の文章には全角記号が混じってきます。
そもそも日本語の文章には必須の句読点「、」「。」ですら全角記号です。
これらの全角記号を指定して除去するような便利な関数やライブラリは存在しません。
じゃあどうするか
1文字ずつ「これは記号でこれは記号じゃない」と指定してやるほかありません。
「おいおいそんなこと時間なくてできないよ」という方のためにPythonで書いたスクリプトを用意しました。
github.com
用意したと言っても、(公式ではありませんが)googleが公開しているコードをPython用に置換したに過ぎません。
github.com
したがってこのコードはApacheライセンスに従い、もとの著作権がgoogleにあることをコード内に明記しておきます。
(何か問題があればお知らせください)
一応使い方ですが
>>>import unicode_script_map as usm >>>usm.get_script_type("あ") <ScriptType.U_Hiragana: 47>
これを文字列に応用し、記号除去に用いるならば
import unicode_script_map as usm from unicode_script import ScriptType test_str = "今日は郵便局に行った(^∀^)" removed_str = "".join([c for c in test_str if usm.get_script_type(c) != ScriptType.U_Common]) print(removed_str) #今日は郵便局に行った
当然ながらこの辞書に載っていない文字が入力されるとKeyErrorになります。
また、気をつけなければいけないのは日本語の長音である"ー"ですが、これが記号と判定されしまいます。
そのため長音を取り除きたくない場合は以下のように書く必要があります。
import unicode_script_map as usm from unicode_script import ScriptType test_str = "今日はボーリングに行ったー(^∀^)" removed_str = "".join([c for c in test_str if usm.get_script_type(c) != ScriptType.U_Common or c == "\u30fc"]) print(removed_str) #今日はボーリングに行ったー
以上です。
NLTKのsentence_bleuで送出される警告について
機械翻訳などの論文を読むと評価尺度としてBLEUというものが用いられています。
NLTKやMosesといった有名な言語処理ライブラリにBLEUを計算する関数が実装されており、私のようによく知らずとも簡単に翻訳文の評価を行うことができます。
その場合、NLTKでは以下のように警告されることがあります。
UserWarning: Corpus/Sentence contains 0 counts of 4-gram overlaps. BLEU scores might be undesirable; use SmoothingFunction(). warnings.warn(_msg)
これが発生する理由について、この記事では述べたいと思います。
sentence_bleuとcorpus_bleuの違い
pythonのライブラリであるNLTKにはbleuを計算する関数としてsentence_bleuとcorpus_bleuという2つの関数が実装されています。
ソースを読んでみるとsentence_bleuは1文をcorpus_bleuに渡しているだけなので基本的に処理自体は変わりません。
しかし、corpus_bleuで警告がでなくとも、一文ずつsentence_bleuで計算すると警告が発生してしまうことが多くあります。
この理由については、(気が向けば)別の記事で述べたいと思います。
BLEUの計算方法
BLEUの求め方は至って簡単です。
参照文(正しい翻訳)と仮定文(機械翻訳)があるとして、まずngram精度を求めます。
これはつまり、[a,b,c]と[a,d,a]があるとすれば
は
は
となるわけです。
このngram精度を使ってBLEU値は以下のように求めることができます。
ここでは考慮するngramの最大値です。NLTKでもMosesでもデフォルト値は4になっており、基本は4のようです。
また、短い文のngram精度は高くなるので、でペナルティを与えます。
計算できない
そうです、上の例におけるはになるのでとなり、計算することができないのです。
この時にNLTKから2gramの一致数が0であるためBLEUスコアが正しくない可能性があると、以下のように警告されます。
UserWarning: Corpus/Sentence contains 0 counts of 2-gram overlaps. BLEU scores might be undesirable; use SmoothingFunction(). warnings.warn(_msg)
算出される値は何か
この警告がなされた場合でもNLTKは無理やりBLEU値を計算して出力します。
の場合、NLTKではとして計算します。
また、ngramに分割できないの場合も0として計算します(したがって、文の長さが4未満なら必ず警告が出ます)。
上の例を用いて、NLTKのsentence_bleuで計算すると
from nltk.translate import bleu_score ref = [["a", "b", "c"]] hypo = ["a", "d", "a"] print(bleu_score.sentence_bleu(ref, hypo)) """ 出力 UserWarning: Corpus/Sentence contains 0 counts of 2-gram overlaps. BLEU scores might be undesirable; use SmoothingFunction(). warnings.warn(_msg) 0.7598356856515925 """
この値は
なので
この式は計算できないため
と同じになります。
from nltk.translate import bleu_score import math ref = [["a", "b", "c"]] hypo = ["a", "d", "a"] print("nltk:", bleu_score.sentence_bleu(ref, hypo)) print("math:", math.exp(math.log(1 / 3) / 4)) """ 出力 UserWarning: Corpus/Sentence contains 0 counts of 2-gram overlaps. BLEU scores might be undesirable; use SmoothingFunction(). warnings.warn(_msg) nltk: 0.7598356856515925 math: 0.7598356856515925 """
Mosesではどうなっているか
Mosesにはmulti-bleu.perlというプログラムが含まれており、これがbleuを計算するプログラムになっています。
上述のようなが含まれる場合、BLEU値は問答無用で0になります(警告文は出ます)。
警告を消す方法
警告を消す方法として最も簡単なものとして、sentence_bleu関数のemulate_multibleuのフラグをTrueにする方法が挙げられます。
これは、おそらくMosesのmulti-bleuと同じ動作にするフラグです(未調査)。
そのため、警告は出ませんがNLTKでもBLEU値が0になります。
from nltk.translate import bleu_score import math ref = [["a", "b", "c"]] hypo = ["a", "d", "a"] print("nltk:", bleu_score.sentence_bleu(ref, hypo, emulate_multibleu=True)) print("math:", math.exp( math.log(1/3) / 4)) """ 出力 nltk: 0.0 math: 0.7598356856515925 """
どちらが正しいのか
わかりません。
誰か詳しい方教えてくださいお願いします。
chainerのExtensionとslackのIncoming Webhookを使う
動機
僕は研究室の端末からどこかに置いてあるサーバに繋いで研究をしているんですが、
1回学習を始めてしまうとbashを落とせなくて困っていました。
よくよく調べてみると、なんかnohupとか言うのを使うとバックグラウンドでもジョブを継続できるらしい。
www.codereading.com
これは素晴らしいと飛びついてみると、「これじゃいつ学習が終わったかわかんねぇぞ」となるわけです。
ということでslackのIncoming WebhookとchainerのExtensionを組み合わせてepochが終了するごとにメッセージを送ろうとういうお話です。
コード
とは言っても世の中に賢い人はいっぱいいるので僕が思うことなんて大抵は実装されています。
nonbiri-tereka.hatenablog.com
この記事を参考にしつつかなり簡素化したものが以下のコードになります。
from chainer.training import extension import json import requests class SlackReport(extension.Extension): trigger = 1, "epoch" def __init__(self): self.post("実験を開始したよっ!") def __call__(self, trainer): log_report = trainer.get_extension("LogReport") log = log_report.log epoch = log[-1]["epoch"] self.post("{}epochが終了したよっ!".format(epoch)) def post(self, text): payload = {"text":text} requests.post("<Webhook URL>", data=json.dumps(payload))
後はこれをtrainerにextendしてやるだけです。
trainer.extend(SlackReport())
シンプルイズベストだなぁ。
Unity1週間ゲームジャム「積む」に参加してオンラインゲームっぽいのを作った話。
Unity 1週間ゲームジャム | ゲーム投稿サイト unityroom - Unityのゲームをアップロードして公開しよう
今回は論文と重なったりしていて参加は無理かな~と思っていたのですが、
論文の提出期限が伸びたおかげで参加できることになりました。
やったね。
前回は
実は前回も参加していて、
ていうのを公開しました。
お題「積む」について
発表されたときは今回もというか、Unityの物理エンジンを活かせそうなお題だなぁと感じました。
と思いつつも、
お金を積みまくってアイドルが総選挙の場で結婚発表しないようにするゲーム #unity1week
— ミッチー (@naomichi_mitti) 2017年6月18日
とか、
困っているおじいちゃんとおばあちゃんを
目的地まで連れて行くことで「徳を積む」ゲーム
とか変な方向で考えていました(良さげなおじいちゃんとおばあちゃんのアセットが無かったので諦めました)。
さらに実験しながら、「積む、積む」と考えていたのですが
ん?
「積み上げたものぶっ壊して」
確かに積んで壊すのもなかなか趣があります。さすがスキマスイッチ。
しかしゲームにおいて自分が積んだものを自分で壊して何が楽しいのか分かりません。
何か面白い案がないかとツイッターを見てみると、
今週のお題「積む」 | Unity 1週間ゲームジャム #unity1week https://t.co/2uhr9rdqDr
— naichi (@naichilab) 2017年6月18日
第三回お題公開しました。今週もよろしくお願いしまーす!
積む、積み重ねる、積み上げる、、、何も思いつかなければとりあえずCube重ねておけば大丈夫ですw
「Cube重ねておけば大丈夫」
なるほど。
やはりシンプルイズベスト、Cubeを重ねてぶっ壊せばよさそうですね。
さらにここで思い出したのはDomino Onlineというゲーム。
そうだ「Tsumiki Online」を作ろう!
立ちはだかる技術的課題
とりあえず先にオフラインで積んで壊せるゲームを作り始めました。
それでてきたのがこれです。
最初は積み木の色を自分で選択できてText Meshでラベルもつけれるようにしていました。
あわよくばテクスチャなんてアップロード出来たり、なんてのも考えていました。
しかしここで問題になってくるのはサーバーです。
そもそもサーバーサイドプログラムに知識が無く、
「AWS使えばなんとかなるでしょ」程度に思っていました。
しかし、AWSは超過料金は自動引き落とし制度らしいので怖くてさすがに手が付けられませんでした(WebGLで使えないことも後から判明しました)。
救世主NCMB
そんな時に目にとまったのが、
そうNCMBです。
なんと太っ腹、このデータベースは結構無料で使えてしまうのです。
しかもUnity用のSDKなどもあったりして完璧です。
今回必要な機能はデータベースだけでも十分満たしていると思っていたので使わない手はありませんでした。
やっぱりニフティなんだよなぁ。
NCMBの罠
NCMBを使って結構実装した後に気づいたのですが、
「NCMB for UnityはWebGLには対応していない」
のです。
もう少し調べてからやればよかったとかなり萎えました。
ここで一瞬折れかけましたが、やはり参加したいので代替手法を色々と模索することとなりました。
を応用するも、レコードの削除方法と速度の問題から採用を諦めました。
NCMB REST API
そして今の手法であるREST APIを叩くという手法にたどり着きました。
大変お世話になった杏zさんにはこの場でお礼申し上げたいと思います。
コアの部分をほとんど写経しながら利用させてもらいました。
しかしここで、さらに問題が出てきました。
REST APIからレコードを削除する場合、ユニークなobjectIDを指定する必要があるのです。
これはAPIコール数に制限のあるBasicプランにおいては大問題です。
もし積み木が10個積んであった場合、全部削除するためには10回もAPIをコールする必要があります(オブジェクトIDの検索をするので正確には11回です)。
リセット時には全部の積み木のデータを削除するので、削除は非現実的な手法と言わざるをえません。
データベースの使い方が間違っていたのではないかとここで気づかされました。
データベースは頻繁にレコードの削除を行わないのではないかと。
そしていまの仕様へと変更
レコードが削除できないとなると、RGB値やラベルなどは利用できません。
リセット時には最初から更新していくという手法も考えましたが、
なんかいろいろめんどくさそうなので諦めました。
しかし「今いくつ積み木が積んであるのか」という情報だけは、
リセット時に0にセットすればいいのですから、1回のAPIコールだけで実現できそうです。
ということでラベルは廃止、色は生成時にランダムという仕様に変更しました。
結局
という風に落ち着きました。
すごい企業や賢い人が公開してくれたツールやAPI、コードにおんぶにだっこで実装したため、あまりオンラインゲームの知見は得られませんでした。
…まぁそりゃそうなんですが。
次はサーバー借りてMySQL+PHPとかで色々できたらいいなぁと思いつつも、
自分が面白いと思ったことができたので良かったと思います。
今回ゲームとしての面白さは置いておきます。
主催者のnaichiさんには非常に感謝です。
ありがとうございました。
最後にゲームのリンク貼っておきます。
UnityとWindowsとVisualStudioと改行コードの話
初心者がWindows環境下でUnityを使っていると
There are inconsistent line endings in the 'File.cs' script. Some are Mac OS X (UNIX) and some are Windows. This might lead to incorrect line numbers in stacktraces and compiler errors. Many text editors can fix this using Convert Line Endings menu commands.
という警告がUnityEditorで発生します。スクリプトをCreateするたび発生するのでこれがとてもうざい。
意味は「改行コードが複数混じっているのでエラーの元になるよ」です。
で、UnityEditorでスクリプトを作成するときはテンプレートを参照して作ってます。
テンプレートはUnity\Editor\Data\Resources\ScriptTemplates
にあります。
普通のスクリプト作成に使われるテンプレートは81-C# Script-NewBehaviourScript.cs.txt
です。
このテンプレートのデフォルト改行コードがLFなんですね。
このテンプレートの改行コードをWindowsのデフォルトであるCR+LFに変えてやればすべて解決します。
権限が必要なので注意でエディタを管理者権限で実行してから開いてやりましょう。