Bigquery上で行う文字列類似度計算 〜Levenshtein Distance〜
名寄せなどを行うために、しばしばlevenshtein distance通称編集距離による類似度比較が行われます。
私の場合bigquery上でこの処理を行いたかったのですが探しても探しても該当コードが見あたらなかったため簡単に関数を自作しました。
標準SQL文のみだと実装がめんどくさかったので、javascriptの関数ベースで実装しました。
幸いlevenshtein distance用のjavascript関数が
https://github.com/trekhleb/javascript-algorithms/blob/master/src/algorithms/string/levenshtein-distance/levenshteinDistance.js
こちらに掲載されておりました。ただこちらでは結果の正規化がなされていなかったので、本コードでは正規化コードを追記しました。
```
CREATE TEMP FUNCTION NormalizedLevenshteinDistance(a STRING, b STRING)
RETURNS FLOAT64
LANGUAGE js AS '''
const distanceMatrix = Array(b.length + 1).fill(null).map*1;
// Fill the first row of the matrix.
// If this is first row then we're transforming empty string to a.
// In this case the number of transformations equals to size of a substring.
for (let i = 0; i <= a.length; i += 1) {
distanceMatrix[0][i] = i;
}
// Fill the first column of the matrix.
// If this is first column then we're transforming empty string to b.
// In this case the number of transformations equals to size of b substring.
for (let j = 0; j <= b.length; j += 1) {
distanceMatrix[j][0] = j;
}
for (let j = 1; j <= b.length; j += 1) {
for (let i = 1; i <= a.length; i += 1) {
const indicator = a[i - 1] === b[j - 1] ? 0 : 1;
distanceMatrix[j][i] = Math.min(
distanceMatrix[j][i - 1] + 1, // deletion
distanceMatrix[j - 1][i] + 1, // insertion
distanceMatrix[j - 1][i - 1] + indicator, // substitution
);
}
}
let maxLen = Math.max(a.length, b.length)
return distanceMatrix[b.length][a.length] / maxLen;
''';
```
実際に使用する場合には以下のように使用してください。
```
CREATE TEMP FUNCTION NormalizedLevenshteinDistance(a STRING, b STRING)
RETURNS FLOAT64
LANGUAGE js AS '''
const distanceMatrix = Array(b.length + 1).fill(null).map*2;
// Fill the first row of the matrix.
// If this is first row then we're transforming empty string to a.
// In this case the number of transformations equals to size of a substring.
for (let i = 0; i <= a.length; i += 1) {
distanceMatrix[0][i] = i;
}
// Fill the first column of the matrix.
// If this is first column then we're transforming empty string to b.
// In this case the number of transformations equals to size of b substring.
for (let j = 0; j <= b.length; j += 1) {
distanceMatrix[j][0] = j;
}
for (let j = 1; j <= b.length; j += 1) {
for (let i = 1; i <= a.length; i += 1) {
const indicator = a[i - 1] === b[j - 1] ? 0 : 1;
distanceMatrix[j][i] = Math.min(
distanceMatrix[j][i - 1] + 1, // deletion
distanceMatrix[j - 1][i] + 1, // insertion
distanceMatrix[j - 1][i - 1] + indicator, // substitution
);
}
}
let maxLen = Math.max(a.length, b.length)
return distanceMatrix[b.length][a.length] / maxLen;
''';
WITH strings AS
(SELECT "おはよう" AS x, "おはよa" as y
UNION ALL
SELECT "おはよう" AS x, "おはうよ" as y
UNION ALL
SELECT "おはよう" as x, "おはう" as y
UNION ALL
SELECT "おはよう" as x , "おうはよ"
UNION ALL
SELECT "おはよう" as x, "おaaa" as y)
SELECT x,y, NormalizedLevenshteinDistance(x, y) as `NormalizedLevenshteinDistance`
FROM strings;
```
csvファイルからjsonファイルを出力するコード
import csv , json csvFilePath = "file.csv" jsonFilePath = "file.json" arr = [] #read the csv and add the arr to a arrayn with open (csvFilePath) as csvFile: csvReader = csv.DictReader(csvFile) print(csvReader) for csvRow in csvReader: arr.append(csvRow) print(arr) # write the data to a json file with open(jsonFilePath, "w") as jsonFile: jsonFile.write(json.dumps(arr, indent = 4))
リモートサーバのubuntuにおいてdockerで日本語自然言語処理環境を構築してjupyterを立ち上げてアクセスする
今回はGCPでubuntu16.04インスタンスを作成しました.
この過程に関しては他のブログをみてください
1.docker CEをインストール
https://docs.docker.com/install/linux/docker-ce/ubuntu/
こちらの通りにやれば大丈夫
2.docker imageをpullする
あたちの作ったimageをこのコマンドでpullしてくれい
$ docker pull baribariyusuke/python_japanese_nlp
3. 作業データを保存/継続利用するための適当なdocker volumeを作成する
$ docker volume create pythondata
このコマンドでpermisson errorが起こる場合は
以下のコマンドをうったのちにインスタンスに入り直してから上記のコマンドをうってくれい
- $ sudo usermod -a -G docker $USER
4. docker コンテナの作成/起動を行う
(※ssh接続してローカルPCのブラウザからjupyter notebookで分析したいんじゃ!という方は6に移行してね)
$ docker run --rm -it -p 8888:8888 -v pythondata:/pythondata baribariyusuke/python_japanese_nlp
5. pythonを起動する
(base) # python3
あとは好きにしてくれい!
6. jupyter notebookを立ち上げる
(ローカルPC) $ ssh ubuntu名@IPアドレス -L 1234:localhost:8888
リモートサーバにログイン後
$ docker run --rm -it -p 8888:8888 -v pythondata:/pythondata baribariyusuke/python_japanese_nlp
(base )# jupyter notebook
これでローカルPCのブラウザでlocalhost:1234と入力してくれたらリモートPCのjupyter notebookに接続できます.
またここでssh接続してて外部IPがほにゃらら〜というエラーが出たら
かわりにこちらのコマンドをうってください
(base )# jupyter notebook --ip="0.0.0.0"
これでたぶん接続できる
ssh接続時にjupyter notebookが403エラーで立ち上がらないときの対処法
jupyter notebookを不正に終了していることが原因ぽいです.
の
https://github.com/jupyter/notebook/issues/2844#issuecomment-385882596
こちらのコメントに従いましょう.
mysqlのroot userのpassowordを再設定する方法[ubuntu]
linuxconfig.org
こちらにのっとってやること.
SQLのSELECT文で最初と最後のレコードを取り出すクエリ
こんな感じ
(select * from market_Ohlc where currency_pair='btcjpy' order by close_time asc limit 1) union all (select * from market_Ohlc where currency_pair='btcjpy' order by close_time desc limit 1);
(select 任意のカラム from 任意のテーブル where 任意の条件 order by 並び替える基準となるカラム asc limit 1) union all (select 任意のカラム from 任意のテーブル where任意の条件 order by並び替える基準となるカラム desc limit 1);
VAEの損失関数の符号について
損失関数は最小化するものと一般には理解されていますが,VAEの損失関数は最大化するものとして扱われる場合が多いみたいです.これで混乱してしまう方がよくいます.
VAEの損失関数は対数尤度関数を変形したもので,
VAEの損失関数 = ReconstractionError - KLダイバージェンス
と定義される場合が多いです.対数尤度関数ですので最大化することが目的になります.
ただ,計算上VAEの損失関数を最小化するものと定義することも可能みたいです.
ロジスティック回帰では対数尤度関数 ln p(x)にマイナスをかけたものを損失関数としていました.
loss = - ln p(x)
この場合対数尤度関数を最大化,つまり損失関数を最小化していくのが正しくなります.
VAEではロジスティック回帰と同じようなことをしない場合が多く
対数尤度関数の符号を逆転させません.
よって
VAEの損失関数 = ReconstractionError - KLダイバージェンス
と定義される場合が多いと考えられます.
もし損失関数は最小化しないと気持ち悪い!という場合は単純に
VAEの損失関数 = -ReconstractionError + D_KL
と定義して損失関数を最小化するようにすればいいです.
参考文献
https://qiita.com/kenchin110100/items/7ceb5b8e8b21c551d69a
https://qiita.com/iss-f/items/c43b23815fc6d15ae22e
http://tkengo.github.io/blog/2016/06/04/yaruo-machine-learning5/