角度は周期があるのでよくよく考えると平均や分散を出すのがむずかしい。いろいろやりかたがあるみたいだけど「単位ベクトル合算法」で計算してみる。

#!/usr/bin/env python
import numpy as np

deg = np.array([80, 170, 175, 200, 265, 345])
rad = deg * np.pi / 180

# ベクトル化 (計算が楽になるので複素数に)
cmp = np.cos(rad) + np.sin(rad)*1j
# 平均をとる
mean_complex = np.mean(cmp)

# このときの複素数の角度が平均角度
avg = np.angle(mean_complex)
# 絶対値(ベクトル長)小さいほどばらつきは大きい ( [0, 1] )
var = 1 - np.absolute(mean_complex)
print(avg * 180 / np.pi + 360) #=> 190.65
print(var) #=> 0.68

平均角度は分散も考えないと意味がないことがある。90°と270°の平均は↑の計算で180°になるが、ベクトル長さが0なので、平均として妥当な角度は存在してない。

ref

  1. トップ
  2. tech
  3. 角度の平均・分散

こういう感じのコードをコピペする。本体は xorshift128、seed から初期値を xorshift32 で設定する (seed をそのまま初期値にすると、近い seed から似たような乱数が始まるので)

Math.random.seed = (function me (s) {
	// Xorshift128 (init seed with Xorshift32)
	s ^= s << 13; s ^= 2 >>> 17; s ^= s << 5;
	let x = 123456789^s;
	s ^= s << 13; s ^= 2 >>> 17; s ^= s << 5;
	let y = 362436069^s;
	s ^= s << 13; s ^= 2 >>> 17; s ^= s << 5;
	let z = 521288629^s;
	s ^= s << 13; s ^= 2 >>> 17; s ^= s << 5;
	let w = 88675123^s;
	let t;
	Math.random = function () {
		t = x ^ (x << 11);
		x = y; y = z; z = w;
		// >>>0 means 'cast to uint32'
		w = ((w ^ (w >>> 19)) ^ (t ^ (t >>> 8)))>>>0;
		return w / 0x100000000;
	};
	Math.random.seed = me;
	return me;
})(0);

console.log('seed', 1);     //=> seed 1
Math.random.seed(1);
console.log(Math.random()); //=> 0.9905915781855583
console.log(Math.random()); //=> 0.24318050011061132
console.log(Math.random()); //=> 0.00421533826738596
console.log(Math.random()); //=> 0.7972566017415375

console.log('seed', 2);     //=> seed 2
Math.random.seed(2);
console.log(Math.random()); //=> 0.620286941062659
console.log(Math.random()); //=> 0.3181322005111724
console.log(Math.random()); //=> 0.7347465583588928
console.log(Math.random()); //=> 0.9439261923544109

console.log('seed', 1);     //=> seed 1
Math.random.seed(1);
console.log(Math.random()); //=> 0.9905915781855583
console.log(Math.random()); //=> 0.24318050011061132
console.log(Math.random()); //=> 0.00421533826738596
console.log(Math.random()); //=> 0.7972566017415375

備考

JSの数値型はすべて浮動小数点だけど、ビット演算は32bit整数で行われる。ほとんどの場合、ビット演算の結果は signed 32bit 整数として見たときの値になる。

// not not なのでビット表現は変化しないが、符号ビットが立っているので -1 になる
~~0xffffffff //=> -1

その中で 符号なし右ビットシフト演算子は「The result is an unsigned 32-bit integer.」と書いてあって、珍しい。

// 0ビットシフトなのでビット表現は変化しないが、符号ビットを無視するので 0xffffffff になる
(-1)>>>0 //=> 4294967295
  1. トップ
  2. tech
  3. Math.random を seed 付きに置き換える

keras を使ってみたらすんなりモデルを書けたので、少し遊んでいる。入出力の shape の意味を理解できれば、詳しいアルゴリズムまで知ることなく遊べるぐらいまで簡単になっていた (だからといって最適なモデルが作れるわけではないけど)

過去の信号列から現在の信号状態を学習した結果、出力として各時点での再構築された信号列が出るわけだけど、これを並べていくと、ネットワークがどういう特徴を学んでいるか伺い知れるところがある。

  1. トップ
  2. tech
  3. RNN (時系列) AutoEncoder で遊んでいる

メモ書き。試行錯誤の途中でコードが消えさったりしていてよくないので、やったことだけ書いておく

モールスの特徴

  • 信号周波数が固定されており正弦波。キャリアの有無で信号を伝える
    • 「信号のOFF」と「信号がない」ことは区別できない
  • 聴覚受信で必要な SNR は 6 (カジュアル)〜1dB (定型) 程度 https://en.wikipedia.org/wiki/Minimum_detectable_signal http://kf6hi.net/radio/SNR.html
  • 定型文が多い
  • 符号速度は15wpm〜40wpm ぐらいの範囲。1dot [ms] = 1200 / wpm なので、40wpm=66Hz程度。100Hzの帯域で十分 (無線機のフィルタも100Hzが下限)。

波形の処理でなんとかする

検出したい周波数を中心として0Hzに正規化 (検波)し、振幅を得る。100Hz のローパスフィルタをかけ、ダウンサンプル (200Hz 程度) する。

これを Denoising AutoEncoder のネットワークに順次入力し、デコーダ出力列から信号列を復元する (出力はある程度重なるので、最終的に平均を出す)。

出力は文字データではなく、フェージングや符号ゆらぎなどを解決した符号列とする。つまり入力数と出力数は必ず一致し、実際に文字化する処理は含まない。

入力

こういうデータ。これはノイズが少ないのでわかりやすい。

モデル

適切なパラメータが一切わからないが試行錯誤してこんな形になった。RNN の場合、入力シェイプがやや難解でググったり他の人のコードを読んだりして理解した。最初は LTSM を使っていたけど時間がかかるのでGRUにしてみた。

実際の入力データは keras.preprocessing.sequence.TimeseriesGenerator を使うのが楽だった。(最初は知らなくて自力でつくっていた)。timestep は 32、つまり過去の信号 32 サンプル分を1サンプルずつずらしながら入力している。

RepeatVector の前まではエンコーダで、その後がデコーダ。

学習

node.js と web-audio-engine を組合せて大量にノイズ+信号のデータと正解データを作って学習させた。

結果

学習はちゃんとできて、認識できるのは認識できる。

ただ、ノイズがかなり多い信号はやはりどうしようもなかった。聴覚だと聞きとれても、そもそも 0Hz に正規化した時点でノイズに埋もれてしまっていて、学習しようがなさそうだった。


ということでこの方法ではなく他の方法を考えてみることにした。

備考

とりあえずできるのかな〜ベースでやったため、ちゃんとした評価方法を考えてなかった。SNRなど評価の指標を立てたい。しかしSNRは求めかたが難しくてこまってる。

  1. トップ
  2. tech
  3. RNN モールスデコーダの試作

binary_crossentropy 使ってるのに、target 値が 0/1 ではない

binary_crossentropy を loss function にして、出力層を sigmoid にしているにも関わらず、肝心の target (y_train) が 0/1 ではなく、0/0.9999... みたいな値になっていた。当然誤差が常に発生することになる。

acc が一生上がらなくて???と思っていたらこれが原因だった。

  1. トップ
  2. tech
  3. 機械学習ハマったところ (一生 acc 上がらない)

nvidia driver のインストールまわりで Ubuntu が起動しなくなったり操作不能になったりする。OS 再インストールを何度かしなおす必要があった。機械学習専用のマシンに Ubuntu だけインストールするのがおすすめ。

Ubuntu は最新版ではなく LTS を入れること。事例が少なくて面倒なことになる。

とりあえずサードパーティドライバをインストールしてみる

sudo apt update
sudo ubuntu-drivers autoinstall
sudo reboot

これで nvidia-smi はできるが古いのが入ってしまった。

ppa から nvidia-driver-* でグラボにあった最新のドライバをいれる。

sudo add-apt-repository ppa:graphics-drivers/ppa
sudo apt update
sudo apt install nvidia-driver-430

ドライバが入ったら、tensorflow-gpu などを入れるが、各ツールキットのバージョンがうまく一致していなければ動かない。

自分でやろうとせず、余計なことをしないで Anaconda を使うのが正解。Anaconda が nvidia の外部ツールキットも含めて必要なものをすべて入れてくれる。

# これですべてが入る
conda install tensorflow-gpu
$ python
>> import tensorflow as tf
>> tf.test.gpu_device_name()

なおドライバが古いと CUDA driver version is insufficient for CUDA runtime version と怒られる。

  1. トップ
  2. tech
  3. Ubuntu 18.04 LTS に Tensorflow GPU

プリントがうまくいかなかったのかな? と思ってしまうが、実はシリコンスプレーを使うとびっくりするほどすんなり入る

KURE [ 呉工業 ] シリコンスプレ- (420ml) [ For Mechanical Maintenance ] 潤滑・離系剤 [ KURE ] [ 品番 ] 1046 - KURE(呉工業)

KURE(呉工業)

5.0 / 5.0

  1. トップ
  2. tech
  3. PETG で 3D プリントしたネジがうまく入っていかないとき

2018-01-12 に beyerdynamic DT770PRO 250Ω を買ってたらしい。らしい、というか使っているのに日記に記録が残っていなかったのでメモしておく。

【国内正規品】beyerdynamic 密閉型オーバーヘッドヘッドホン レコーディングモニター用 DT 770 PRO 250 - beyerdynamic

beyerdynamic

5.0 / 5.0

パッドが布で良さげなのを探した結果これになったと思う。

側圧が強い以外は満足

メモ

X: 1
T: きらきらぼし
M: C
L: 1/4
Q: 1/4=110
K: C
!1!C C !4!G G | !5!A A G2 | !4!F F E E | D D C2 ||
w:ド ド ソ ソ ラ ラ ソ ファ ファ ミ ミ レ レ ド
w:き ら き ら ひ か る お そ ら の ほ し よ
!5!G G F F | E E D2 | G G F F | E E D2 ||
w: ソ ソ ファ ファ ミ ミ レ ソ ソ ファ ファ ミ ミ レ
w: ま ば た き し て は み ん な を み て る
!1!C C !4!G G | !5!A A G2 | !4!F F E E | D D C2 |]
w:ド ド ソ ソ ラ ラ ソ ファ ファ ミ ミ レ レ ド
w:き ら き ら ひ か る お そ ら の ほ し よ
X: 1
T: メリーさんのひつじ
M: C
L: 1/4
Q: 1/4=120
K: C
!3!E3/2 D/2 C D | E E E z | D D D z | E G G z ||
w:ミ レ ド レ ミ ミ ミ レ レ レ ミ ソ ソ
w: メ リー さん の ひ つ じ ひ つ じ ひ つ じ
E3/2 D/2 C D | E E E z | D D E D | C2 z2 |]
w:ミ レ ド レ ミ ミ ミ レ レ ミ レ ド
w: メ リー さん の ひ つ じ か わ い い ね
  1. トップ
  2. piano
  3. きらきらぼし メリーさんのひつじ

サイクリングで多摩川、浅川、南浅川と上っていくとサイクリングロードの終点が武蔵陵墓地あたりになる。特に行こうと思っていたわけではないが、行ったことがなかったので寄ってみた。

中が想像以上に広かった。それに結構ぱらぱらと参拝する人がくるみたい。

かすかに中央線か京王線の電車の音がするぐらいで非常に静かで良い環境だった。

天皇陵って意識しはじめたのが京都にいたころなので、どうもそこらじゅうにあるイメージがあったが、関東だとここにしかない。 (明治神宮は陵ではなく、明治天皇は伏見桃山陵)

パナソニック LED電球 E26口金 電球60形相当 電球色相当(7.8W) 一般電球・人感センサー LDA8LGKUNS - パナソニック(Panasonic)

パナソニック(Panasonic)

3.0 / 5.0

500 Can't connect to lowreal.net:443 (certificate verify failed) 6年ほど前に買ったアイリスオーヤマの人感センサー付き LED ライトが激しく点滅するようになってしまったので買い替え。

アイリスオーヤマのは購入直後からいまいちセンサーの感度に不満があったので、別のメーカーにしようと、今回はちょっと高いがパナソニックにしてみた。今のところは不満なし。

http://xmlstar.sourceforge.net/

コマンドラインで XML を操作できるツール。-t が便利。

ごく稀に XML を処理して加工してなにかにしたいことがあると思う。今回の場合、雑に FindBugs の結果を ignore したかったのだが、そこそこ数があってめんどい。

SpotBugs(FindBugs) の結果 XML から ignore filter を雑に出力する

SpotBugs の report XML は以下のような感じ。ほとんどはしょっている。

<BugCollection ...>
  <BugInstance type="...">
    ...
  </BugInstance>
</BugCollection>

これを

<Match>
  <Bug pattern="..."/>
  <Class name="..."/>
</Match>

という filter のルールに変換したい。XML to XML なので XSLT で出番だ!! しかし XML は書きたくない!!!!


xmlstarlet ではこれは以下のようにできる。ようは XSLT のテンプレートをコマンドライン引数からつくってるだけなのだけど、これがなかなか便利。

xmlstarlet select --indent \
	-t -m '//BugInstance' \
	-n \
	-e 'Match' \
		-e 'Bug' \
			-a 'pattern' -v '@type' \
			-b \
		-b \
		-e 'Class' \
			-a 'name' -v './Class/@classname' \
 build/reports/spotbugs/*.xml


-t の説明を読めばなにが起こっているかすぐわかるでしょう。

やっていることは

  • //BugInstance にマッチさせてそれぞれに対して
  • Match 要素を生成
  • Bug 要素を生成
  • Bug 要素に pattern 属性を生成
  • code 属性の値を ./@type (BugInstance の type 属性) から生成
  • "-b" で pattern 属性のネストを抜ける
  • "-b" で Bug 要素のネストを抜ける
  • Class 要素を生成
  • Class 要素に name 属性を生成
  • name 属性の値を ./Class/@classname から生成
  • (自動的にネストは閉じられる)

まぁ XSLT を簡単に書けるというだけなので、XSLT の知識なしでうまく書けるかというと疑問がある。(僕はアホみたいにXSLT書いてた時期があるので気持ちよく書けます!!)

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" version="1.0" extension-element-prefixes="exslt">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:template match="/">
    <xsl:for-each select="//BugInstance">
      <xsl:value-of select="'&#10;'"/>
      <xsl:element name="Match">
        <xsl:element name="Bug">
          <xsl:attribute name="pattern">
            <xsl:call-template name="value-of-template">
              <xsl:with-param name="select" select="@type"/>
            </xsl:call-template>
          </xsl:attribute>
        </xsl:element>
        <xsl:element name="Class">
          <xsl:attribute name="name">
            <xsl:call-template name="value-of-template">
              <xsl:with-param name="select" select="./Class/@classname"/>
            </xsl:call-template>
          </xsl:attribute>
        </xsl:element>
      </xsl:element>
    </xsl:for-each>
  </xsl:template>
  <xsl:template name="value-of-template">
    <xsl:param name="select"/>
    <xsl:value-of select="$select"/>
    <xsl:for-each select="exslt:node-set($select)[position()&gt;1]">
      <xsl:value-of select="'&#10;'"/>
      <xsl:value-of select="."/>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

この XSLT テンプレートと同様のことになる。xmlstarlet のコマンドラインのほうがはるかに書くのは楽ですね。

  1. トップ
  2. tech
  3. XML をコマンドラインからクエリー (XSLT) したいときに使える xmlstarlet