中野智文のブログ

データ・マエショリストのメモ

トラフィックエクスチェンジの闇

背景

ad fraud を追う間に、「トラフィックエクスチェンジ」というサービスを知ることになった。

トラフィックエクスチェンジとは、サイト間でユーザを交換しようという試みである。 まだ検索エンジンがあまり発展していなかった時代などは、サイト間のリンクのみが唯一自分のサイトに訪れてもらえる方法だった。 そのようなときに相互リンクをはることで、お互いのページを行き来できるようになる。 相互リンクを貼る場合、お互いにメールや掲示板を利用して連絡をする必要がある。

トラフィックエクスチェンジのシステムはそのような背景があって、登録しておけば別の登録サイトにランダムにジャンプしてくれるツールだった。

トラフィックエクスチェンジの闇

検索エンジンSNSが発達した今、それは全く別物になっている。 詳しくは下記のページを御覧いただきたい。

https://ja.wikipedia.org/wiki/%E3%83%88%E3%83%A9%E3%83%95%E3%82%A3%E3%83%83%E3%82%AF%E3%82%A8%E3%82%AF%E3%82%B9%E3%83%81%E3%82%A7%E3%83%B3%E3%82%B8

トラフィックをやり取りすることで、将来的に換金可能なポイントがもらえるシステムになっている。 それも自動的に別サイトに遷移する仕組みになっていて、人間が不在でも時間が経てばどんどんポイントがたまるのだ。

こういう本もあるくらいだから、

初めから自動化されているのは、本当に素晴らしいことだと思う。 人間不在でページが遷移することになんの意味があるかわからないが、その自動化まですでに仕込んであるのは、素晴らしいとことだと思う。

ところが、Web広告を出す側にとっては大きな問題だ。人間が見ていない広告に価値はない。

トラフィックエクスチェンジを行っている方へお願い。

adblock を入れてください。

Chromeこちhttps://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&cad=rja&uact=8&ved=0ahUKEwjyiJb7r-XUAhWDerwKHc3CCi0QFgguMAE&url=https%3A%2F%2Fchrome.google.com%2Fwebstore%2Fdetail%2Fadblock-plus%2Fcfhdojbkjhnklbpkdaibdccddilifddb%3Fhl%3Dja&usg=AFQjCNHqQbwfsSRVUqnfKN4MDGPo2VCs5g

Firefoxこちhttps://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&cad=rja&uact=8&ved=0ahUKEwjyiJb7r-XUAhWDerwKHc3CCi0QFgg1MAI&url=https%3A%2F%2Faddons.mozilla.org%2Fja%2Ffirefox%2Faddon%2Fadblock-plus%2F%3Fsrc%3Dhp-dl-mostpopular&usg=AFQjCNGhrDoOldicKhr0a9YJbDWgsfvO8g

29戦中29連勝の勝率の信頼区間を求める

背景

仕事でどうしても必要になった(嘘)

Wilson score interval で計算する。

早速だけど、下記の式を使ってみよう。

nakano-tomofumi.hatenablog.com

今回は、p = 0.05 で求める。標準正規分布の分位数はZ=1.96となる。

よって、

UCB: (29+1.96*1.96/2+1.96*sqrt(29*(29-29)/29+1.96*1.96/4))/(29+1.96*1.96)
LCB: (29+1.96*1.96/2-1.96*sqrt(29*(29-29)/29+1.96*1.96/4))/(29+1.96*1.96)

これを python でそれぞれ求める。

$ python
>>> import math
>>> (29+1.96*1.96/2+1.96*math.sqrt(29*(29-29)/29+1.96*1.96/4))/(29+1.96*1.96)
1.0
>>> (29+1.96*1.96/2-1.96*math.sqrt(29*(29-29)/29+1.96*1.96/4))/(29+1.96*1.96)
0.8830264055344441
>>>

勝率は 88.3%から100%(p=0.05)となった。

結論

勝率は 88.3%から100%(p=0.05)

信頼上限より大きくないから、片側の信頼区間は両側の信頼区間と同じである。

勝率は 88.3%以上(p=0.025)

でもいいかもしれない。

BigQuery でテーブルを正規表現を指定して削除する

背景

BigQuery で特定のテーブルをワイルドカードで指定して削除したいことがある。ところが、CLIコマンドである bq はそのようなワイルドカード指定はできない。

データセットのファイル一覧を出して、それを egrep で抽出する

下記の <dataset_name> と、<regular expression> にそれぞれ、データセット名と正規表現を書く。

bq --format json ls -n 10000 <dataset_name> | jq -r 'map("<dataset_name>."+ .tableReference.tableId)|.[]' | egrep '<regular expression>' | xargs -L1 bq rm -f

ただし、本当に望ましいファイルが対象となっているかを最後の削除を除いたコマンドである、

bq --format json ls -n 10000 <dataset_name> | jq -r 'map("<dataset_name>."+ .tableReference.tableId)|.[]' | egrep '<regular expression>' 

で一旦確認したり、ファイル数を少なくして実行してみることをおすすめする。

追記

  • 2018-06-12 .tableId で取得できなくなっていたので、.tableReference.tableId に修正

pdf を送ると、「Kindleに送信された文書に問題がありました」

症状

次の論文をchromeでダウンロードして、

https://openreview.net/pdf?id=BkJsCIcgl

mail で kindle に送信すると次のようなエラーメールが届く

2017年6月19日(月) 午前 09:59(JST) に送信された以下のドキュメントは、指定されたKindle に送信できませんでした:
XXXXX.pdf

Kindle パーソナル・ドキュメントで変換・転送できるドキュメントは以下のファイル形式です:
Microsoft Word (.doc, .docx)
Rich Text Format (.rtf)
HTML (.htm, .html)
Text (.txt) documents
圧縮フォルダ (zip , x-zip)
Mobi book

画像ファイル: JPEG (.jpg)、GIF (.gif)、Bitmap (.bmp)、PNG (.png)。
Adobe PDF (.pdf) ドキュメントは、Kindle DX, 第二世代および最新の Kindle には変換されずに送信されます。

PDF ファイルの Kindle フォーマットへの変換・転送は試験段階の機能としてご提供しております。

転送に失敗したドキュメントが上記の形式だった場合は、ファイルがパスワード保護されていたり、暗号化されていたりしないかをご確認ください。最新の Kindle はパスワード保護された PDF ファイルの転送が可能です。

パーソナル・ドキュメントの添付ファイルに関するご注意:
添付ファイルは、それぞれ ZIP 圧縮前のサイズが50MB未満である必要があります。
一通のEメールで送信できるファイル数の上限は25個です。

パーソナル・ドキュメントの転送についての詳細は、ヘルプページをご覧ください:
http://www.amazon.co.jp/kindlepersonaldocuments/

調査

当初ファイル名の問題かと思われたが、同じエラーメールが来る。

解決

mac のプレビューワで 「ファイル」「pdf として書き出す」で送信後、問題なく、kindle で表示されることを確認。

原因(不明)

オリジナルのPDFに何かあったのか、chrome で一旦表示後、ダウンロードしたのがよくないのか、そのあたりは不明。

おまけ

kindle ではPDF版の論文を読むのは苦痛でしかない。スマホkindle アプリの方が無料にも関わらず、簡単に拡大縮小でき、はっきり言って楽。 でもこのページに来たということは、既に何かしらの kindle を持っているということかも。もし安 kindle で論文を読もうと思っているのであれば、 諦めてPDFをスマホで読むか、最低でも paper white を購入することをおすすめする。

Permission denied while globbing file pattern. のエラー

症状

BigQuery のWebコンソールでは特にエラーは出ないのに、redash だと Error running query: The job encountered an internal error during execution and was unable to complete successfully. みたいなエラー。

調査

コマンドコンソールにて同クエリーを実行。 すると、

Permission denied while globbing file pattern. 

のエラー。 そのエラーのクエリをヒストリから選び、Open Query から RUN QUERY を再実行するも、正常に返ってくる。

Webで調べてみると、google drive がらみの権限エラーの模様。

stackoverflow.com

Google Driveは全く使っていないが、たしかに 直接インポート した。

インポートしたテーブルを外すと、コマンドからでも正常にクエリは実行された。

該当テーブルの detail をwebコンソールから見ると、

External Data Configuration
Source URI(s)   https://docs.google.com/spreadsheets/d/XXXXXXXXXXXXX/edit#gid=0
Auto-detect Schema  true
Source Format   GOOGLE_SHEETS
Max Bad Records     10

となっており、たしかに外部から持ってきたデータであることと、source format も GOOGLE_SHEETS となっている。

対応

原因が分かったが、対応方法は不明。

まず、bq コマンドによりコピーを試みるが、当然失敗した。

次に、

SELECT * FROM [TABLE_NAME]

を実行し、その結果を別テーブルに保管した。そしてそのテーブルを参照するようにすると、bq コマンドで問題なくクエリは実行できた。 redashも問題なく動作した。

luigi の exit status

luigi の exit status

は失敗しても 0 が返ってくるので、make などから呼び出した場合、そのまま通過してしまう。

調べると、次のページが見つかる。

qiita.com

実はコマンドラインのオプションでも設定できる。

$ luigi --help-all
...
  --retcode-unhandled-exception RETCODE_UNHANDLED_EXCEPTION
                        For internal luigi errors.
  --retcode-missing-data RETCODE_MISSING_DATA
                        For when there are incomplete ExternalTask
                        dependencies.
  --retcode-task-failed RETCODE_TASK_FAILED
                        For when a task's run() method fails.
  --retcode-already-running RETCODE_ALREADY_RUNNING
                        For both local --lock and luigid "lock"
  --retcode-scheduling-error RETCODE_SCHEDULING_ERROR
                        For when a task's complete() or requires() fails, or
                        task-limit reached
  --retcode-not-run RETCODE_NOT_RUN
                        For when a task is not granted run permission by the
                        scheduler.
...

オプションで指定できることは、設定ファイルでも設定できるといったほうがいいのか、設定ファイルで設定できることはオプションで指定できるといったほうがいいのか。 いずれにしろ便利。

already_running については悩ましいが、とりあえず、全て非ゼロに設定ファイルにしておき、必要に応じてオプションで指定するなどがいいのでは。

Airflow と格闘中(15)

nakano-tomofumi.hatenablog.com

上記のように、もう使わない予定だが、エラーが出たので貼り付ける。

backfilldeadlocked エラー

Traceback (most recent call last):
  File "/XXX/bin/airflow", line 28, in <module>
    args.func(args)
  File "/XXX/lib/python2.7/site-packages/airflow/bin/cli.py", line 167, in backfill
    pool=args.pool)
  File "/XXX/lib/python2.7/site-packages/airflow/models.py", line 3330, in run
    job.run()
  File "/XXX/lib/python2.7/site-packages/airflow/jobs.py", line 200, in run
    self._execute()
  File "/XXX/lib/python2.7/site-packages/airflow/jobs.py", line 2031, in _execute
    raise AirflowException(err)
airflow.exceptions.AirflowException: ---------------------------------------------------
BackfillJob is deadlocked. These tasks have succeeded:
set([(u'dag_name', u'dag_name', datetime.datetime(2017, 6, 6, 0, 0)), (u'dag_name', u'task_name0', datetime.datetime(2017, 6, 6, 0, 0))])
 These tasks have started:
{}
 These tasks have failed:
set([])
 These tasks are skipped:
set([])
 These tasks are deadlocked:
set([<TaskInstance: dag_name.task_name1 2017-06-06 00:00:00 [scheduled]>, <TaskInstance: dag_name.task_name2 2017-06-06 00:00:00 [up_for_retry]>, <TaskInstance: dag_name.task_name3 2017-06-06 00:00:00 [scheduled]>, <TaskInstance: dag_name.task_name4 2017-06-06 00:00:00 [scheduled]>])

もう一度実行したらうまくいった。

何がデッドロックなのかは分からない。もしかしたら、仮想マシンの共有ディレクトリを使っているので、その関係上 sqlite などの更新が間に合わずおかしくなっているのかもしれない。

まとめは、

nakano-tomofumi.hatenablog.com