数値計算
はじめに
実計算に誤差はつきものである。 誤差にはいくつか種類があり、それは計算機に特有のものもあれば、そうでないものもある。 まず背景知識として、計算機での数値表現を説明する。 その後、数種類の誤差を紹介し、それぞれの例と対策を簡単に考える。 最後に誤差対策に使えそうな手法をいくつか紹介する。
計算機上での数値表現
int 型
http://www.kab-studio.biz/Programing/JavaA2Z/Word/00000249.html
固定小数点
http://www.kab-studio.biz/Programing/JavaA2Z/Word/00000148.html
float 型
https://www.cc.kyoto-su.ac.jp/~yamada/programming/float.html
http://www.kab-studio.biz/Programing/JavaA2Z/Word/00000097.html https://itmanabi.com/fixed-floating/
参考
http://www.kab-studio.biz/Programing/JavaA2Z/List/index.html
そもそもの誤差
測定誤差
例) 最小メモリが 1mm の定規 https://kotobank.jp/word/%E6%B8%AC%E5%AE%9A%E8%AA%A4%E5%B7%AE-1181095 https://www.keyence.co.jp/ss/measure/hakaritai/basic/errors/
有効数字も参考のこと http://dsl4.eee.u-ryukyu.ac.jp/DOCS/error/node6.html
離散化による誤差
音をデジタル化するときなどに発生する
http://www.mb.ccnw.ne.jp/kontoshi/papa/gimon/oto.htm http://www.kumikomi.net/archives/2010/07/ep22onse.php
float による誤差
丸め誤差
真の値を取ることが出来ない。 1/2 の乗数は、真の値を取れる。
s = 0 v = 0.1 for i in range(10): s += v print(s) # 0.9999999 s = 0 v = 0.125 # 1/2 ** 3 for i in range(8): s += v print(s) # 0.9999999
http://www.kab-studio.biz/Programing/JavaA2Z/Word/00000521.html
情報落ち誤差
大きな数と小さな数の加算による誤差
big = 10 ** 15 + 0.1 print(big) # debug small = 0.1 ** 15 print(small) # debug v = big - small print(v) # debug if v == big: print(True) # こっちに入る else: print(False)
ALU は double より大きい bit 数で計算してたりするから、情報落ちしないこともある
//TODO 実際に試す tmp = big + small; res = tmp - big res == 0 // tmp という変数に起こすと情報落ちするけど res = big + small - big res == small // 変数に起こさなければ、ALU が大きな bit を扱ってる場合は、情報落ちしないことがある
桁落ち誤差
近い値を持つ数の減算
x = 0.99999 y = 0.99998 print('x') # debug print(x) # debug print('y') # debug print(y) # debug print('x - y') # debug print(x - y) # debug a = 0.9 b = 0.8 print('a') # debug print(a) # debug print('b') # debug print(b) # debug print('a - b') # debug print(a - b) # debug print('0.1') # debug print(0.1) # debug
その他の誤差
打ち切り誤差
漸化式を打ち切ることによる誤差 \sum 1/k2 = \pi ^2 / 6
その他の対策
分数 型 (有理数型) https://docs.python.org/ja/3/library/fractions.html
区間演算 https://ja.wikipedia.org/wiki/%E5%8C%BA%E9%96%93%E6%BC%94%E7%AE%97
golang
基本
実行
go run hello.go
実行ファイルは作成されない。
ビルド(コンパイル)
go build hello.go
実行ファイルが作成される。
Go のプログラムは package から始まる。
package を import とすると,公開された(export)名前を参照できる。
export するには,名前を大文字で始めること。小文字で始めると参照できない。
関数
func add(x int, y int) int { return x + y } // 同じ型ならまとめられる func add(x, y int) int { return x + y } // 複数返せる func swap(x, y string) (string, string) { return y, x } func main() { a, b := swap("hello", "world") } // named return values, 短い関数でのみ使ってよい (メリットが分からん) func split(sum int) (x, y int) { x = sum * 4/ 9 y = sum - x return }
デフォルト引数はない
変数宣言
var i int var c, python, java bool var i, j int = 1, 2 var ( s = 3 t = 5 ) k := 3 // 暗黙的な型宣言, 関数の中だけ
初期値を与えずに宣言すると,ゼロ値 (zero value)が与えられる
数値型:0, bool:false, string:""(空文字)
スライスのゼロ値は nil
型変換
T(v) // 変数 v を T 型に変換する, 明示的な変換が必要
定数
const Pi = 3.14 const ( Big = 1 << 100 Small = BIg >> 99 )
character, string, boolean, numeric のみ使える
:= は使えない
定数には型がなく,値として扱われる。その状況によって必要な型を取る。
basic types
bool
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
byte // uint8 の別名
float32 float64
complex64 complex128
制御
// dummy comment for i := 0; i < 10; i++ { } for sum < 1000 { // as while } for { // 無限ループ } if x < 0 { } if v := math.Pow(x, n); v < lim { // init scope is in if and else } // break はない(勝手に提供される) // 上から case を評価して,終わったら break switch os := runtime.GOOS; os { case "darwin": fmt.Println("OS X.") case "linux": fmt.Println("Linux.") default: fmt.Println("%s.", os) } switch { // as `switch true`. works as if-then-else case t.Hour < 12: fmt.Println("Good morning!") case t.Hour < 17: fmt.Println("Good afternoon.") default: fmt.Println("Good evening.") } func main() { file, err = os.Open("path/to/file") defer file.Close() } // defer は引数の評価は即時。実行は関数終了後。スタック順序
ポインタ
// ポインタ演算はない var p *int // ゼロ値は nil i := 42 p = &i *p = 21
データ構造
type Vertex struct { X int Y int // `X, Y int` is also ok. } v := Vertex{1, 2} v.X = 4 p := &v p.X = 1e9 v2 := Vertex{X: 1} // 部分的初期化, 他はゼロ値 v2 := Vertex{} // ゼロ値 初期化 ptr := &Vetrex{1, 2}
配列とスライス
var arr [2]string // 配列の長さは型の一部分。配列サイズは変えれない arr[0] = "Hello" primes := [6]int{2, 3, 5, 7, 11, 13} var s []int = primes[1:4] // size は 3 = 4 - 1, 後ろの index は -1 でアクセスされる fmt.Println(s) // [3 5 7] s[0] = 99 // スライスは配列への参照。primes は [2 99 5 7 11 13] [3]bool{true, true, false} // 配列リテラル []bool{true, true, false} // 上記と同じ配列を作り,そのスライスを作成する // スライスの値は省略できる // スライスには length len() と capacity cap() がある。 // python みたいに -1 とかは使えない s := []string{"a", "b", "c", "d", "e", "f",} s = s[1:4] // b, c, d s = s[:2] // b, c s = s[1:] // c, len(s) = 1, cap(s) = 4 s = s[:4] // capacity まで後ろに拡張できる。前にはできない // make はゼロ化された配列を割り当て,その配列のスライスを返す a := make([]int, 5) // len(a) = 5 b := make([]int, 0, 5) // len(b) = 0, cap(b) = 5 // 2次元配列スライス board := [][]string{ []string{"_", "_", "_"}, []string{"_", "_", "_"}, []string{"_", "_", "_"}, } // append, 返り値を受ける必要がある var s = []int s = append(s, 0) s = append(s, 1, 2, 3, 4, ) func printSlice(s []int) { fmt.Printf("len=%d, cap=%d, %v\n", len(s), cap(s), s) } // range for i, v := range s { fmt.Printf("index %d, value %d\n", i, v) } for i := range s { // index only fmt.Printf("index %d, value %d\n", i, v) } for _, v := range s { // skip index fmt.Printf("index %d, value %d\n", i, v) }
Map
type Vertex struct { Lat, Long float64 } var m_ map[string]Vertex m_["Bell Labs"] = Vertex{40.68433, -74.39967} var m = map[string]Vertex{ "Bell Labs": Vertex{ 40.68433, -74.39967, }, "Google": {37.42202, -122.08408}, // 型を推測できるときは省略できる } delete(m, "Google") v, ok := m["Google"] fmt.Println("The value:", v, "Present?", ok)
func
func compute(fn func(float64, float64) float64) float64 { return fn(3, 4) } hypot := func(x, y float64) float64 { return math.Sqrt(x*x + y*y) } fmt.Println(hypot(5, 12)) fmt.Println(compute(hypot))
closure
package main import "fmt" func adder() func(int) int { sum := 0 return func(x int) int { sum += x return sum } } func main() { pos, neg := adder(), adder() for i := 0; i < 10; i++ { fmt.Println( pos(i), // 0, 1, 3, 6, 10, ... neg(-2*i), // 0, -2, -6, -12, -20, ... ) } }
method
type Vertex truct { X, Y float64 } func (v Vertex) Abs() float64 { // copy instance return math.Sqrt(v.X*v.X + v.Y*v.Y) } func (v *Vertex) Abs() float64 { // pointer return math.Sqrt(v.X*v.X + v.Y*v.Y) } v.Abs() // どちらも同じように呼べる func Abs(v Vertex) float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y) } Abs(v) func Abs(v *Vertex) float64 { //TODO if v == nil { ... } return math.Sqrt(v.X*v.X + v.Y*v.Y) } Abs(&v) type MyFloat float64 func (f MyFloat) float64 Abs() float64 { if f < 0 { return float64(-f) } return float64(f) }
interface
type Abser interface { Abs() float64 } var a Abser f := MyFloat(-math.Sqrt2) v := Vertex{3, 4} a = f // a MyFloat implements Abser a = &v // a *Vertex implements Abser var abser Abser = &Vertex{} describe(abser) func describe(i I) { fmt.Printf("(%v, %T)\n", i, i) }
// type assertion var i interface{} = "hello" s := i.(string) fmt.Println(s) s, ok := i.(string) fmt.Println(s, ok) f, ok := i.(float64) fmt.Println(f, ok) f = i.(float64) // panic fmt.Println(f) // type switch func do(i interface{}) { switch v := i.(type) { case int: fmt.Printf("Twice %v is %v\n", v, v*2) case string: fmt.Printf("%q is %v bytes long\n", v, len(v)) default: fmt.Printf("I don't know about type %T!\n", v) } } // func (t Type) String() string // を実装すれば Println() できる
error
error は基本的に使わない。 予想できるものは if で分岐する。 予想できないものだけ error にする。
type MyError struct { When time.Time What string } func (e *MyError) Error() string { return fmt.Sprintf("at %v, %s", e.When, e.What) } func run() error { return &MyError{ time.Now(), "it didn't work", } } func main() { if err := run(); err != nil { fmt.Println(err) } }
Reader
func main() { r := strings.NewReader("Hello, Reader!") b := make([]byte, 8) for { n, err := r.Read(b) // func (T) Read(b []byte) (n int, err error) fmt.Printf("n = %v err = %v b = %v\n", n, err, b) fmt.Printf("b[:n] = %q\n", b[:n]) if err == io.EOF { break } } }
Image
type Image interface { ColorModel() color.Model Bounds() Rectangle At(x, y int) color.Color }
concurrency
package main import ( "fmt" "sync" "time" ) func say1(ch chan string, s string) { for i := 0; i < 3; i++ { time.Sleep(100 * time.Millisecond) ch <- s } close(ch) } func concurrency1() { ch := make(chan string) go say1(ch, "hello world") for s := range ch { fmt.Println(s) } fmt.Println("end") } func say3(ch chan string, s string) { for i := 0; i < 3; i++ { time.Sleep(100 * time.Millisecond) ch <- s } } func concurrency3() { ch1 := make(chan string) ch2 := make(chan string) go say3(ch1, "hello") go say3(ch2, "world") for i := 0; i < 20; i++ { select { case s := <-ch1: fmt.Println(s) case s := <-ch2: fmt.Println(s) default: fmt.Println("...") time.Sleep(100 * time.Millisecond) } } } type SafeCounter struct { value int mux sync.Mutex } func (c *SafeCounter) add(wg *sync.WaitGroup) { defer wg.Done() c.mux.Lock() defer c.mux.Unlock() c.value++ } func lock() { c := SafeCounter{} var wg sync.WaitGroup for i := 0; i < 100; i++ { wg.Add(1) go c.add(&wg) } wg.Wait() fmt.Println(c.value) } func main() { concurrency1() concurrency3() lock() }
other
golang は並列処理用。
_ust は高速処理用(c, c++ 後継) Rust は Go より圧倒的に速い。しかし,self キーワードが必要。
Karabiner-Elements で Mac を Ubuntu 風(Gnome)にする
参考
Karabiner-Elementsの設定項目をまとめました - Qiita
Karabiner-Elements で特定のアプリにだけキーバインドを変更する - モノラルログ
json
{ "title": "MacをUbuntu風に操作する", "rules": [ { "description": "hold terminal ctrl", "manipulators": [ { "type": "basic", "conditions": [ { "type": "frontmost_application_if", "bundle_identifiers": [ "^com\\.apple\\.Terminal" ] } ], "from": { "key_code": "left_control", "modifiers": { "optional": [ "any" ] } }, "to": [ { "key_code": "right_control" } ] }, { "type": "basic", "conditions": [ { "type": "frontmost_application_if", "bundle_identifiers": [ "^com\\.apple\\.Terminal" ] } ], "from": { "key_code": "c", "modifiers": { "mandatory": [ "control", "shift" ] } }, "to": [ { "key_code": "c", "modifiers": [ "left_command" ] } ] }, { "type": "basic", "conditions": [ { "type": "frontmost_application_if", "bundle_identifiers": [ "^com\\.apple\\.Terminal" ] } ], "from": { "key_code": "v", "modifiers": { "mandatory": [ "control", "shift" ] } }, "to": [ { "key_code": "v", "modifiers": [ "left_command" ] } ] } ] }, { "description": "全角半角でIME切り替え", "manipulators": [ { "type": "basic", "conditions": [ { "input_sources": [ { "language": "ja" } ], "type": "input_source_if" } ], "from": { "key_code": "grave_accent_and_tilde", "modifiers": { "optional": [ "any" ] } }, "parameters": { "basic.to_if_held_down_threshold_milliseconds": 100 }, "to_if_alone": [ { "key_code": "japanese_eisuu" } ] }, { "type": "basic", "conditions": [ { "input_sources": [ { "language": "en" } ], "type": "input_source_if" } ], "from": { "key_code": "grave_accent_and_tilde", "modifiers": { "optional": [ "any" ] } }, "parameters": { "basic.to_if_held_down_threshold_milliseconds": 100 }, "to_if_alone": [ { "key_code": "japanese_kana" } ] } ] }, { "description": "map left_control to command", "manipulators": [ { "from": { "key_code": "left_control", "modifiers": { "optional": [ "left_shift" ] } }, "to": [ { "key_code": "left_command" } ], "type": "basic" } ] }, { "description": "Maps Alt+Tab to Cmd+Tab", "manipulators": [ { "from": { "key_code": "tab", "modifiers": { "mandatory": [ "left_alt" ], "optional": [ "left_shift" ] } }, "to": [ { "key_code": "tab", "modifiers": [ "right_command" ] } ], "type": "basic" }, { "from": { "key_code": "left_shift", "modifiers": { "mandatory": [ "left_alt" ] } }, "to": [ { "key_code": "left_shift", "modifiers": [ "right_command" ] } ], "type": "basic" }, { "from": { "key_code": "escape", "modifiers": { "mandatory": [ "left_alt" ], "optional": [ "left_shift" ] } }, "to": [ { "key_code": "escape", "modifiers": [ "left_command" ] } ], "type": "basic" } ] }, { "description": "retrieve ctrl BS <- cmd BS", "manipulators": [ { "from": { "key_code": "delete_or_backspace", "modifiers": { "mandatory": [ "left_command" ] } }, "to": [ { "key_code": "delete_or_backspace", "modifiers": [ "left_control" ] } ], "type": "basic" } ] }, { "description": "retrieve ctrl tab <- cmd tab", "manipulators": [ { "from": { "key_code": "tab", "modifiers": { "mandatory": [ "left_command" ] } }, "to": [ { "key_code": "tab", "modifiers": [ "left_control" ] } ], "type": "basic" }, { "from": { "key_code": "tab", "modifiers": { "mandatory": [ "left_command", "left_shift" ] } }, "to": [ { "key_code": "tab", "modifiers": [ "left_control", "left_shift" ] } ], "type": "basic" } ] } ] }
{ "title": "key settings", "rules": [ { "description": "etc", "manipulators": [ { "type": "basic", "conditions": [ { "type": "frontmost_application_if", "bundle_identifiers": [ "^com\\.apple\\.Terminal" ] } ], "from": { "key_code": "international5" }, "to": [ { "key_code": "right_control" } ] }, { "type": "basic", "from": { "key_code": "international1" }, "to": [ { "key_code": "international3" } ] }, { "type": "basic", "from": { "key_code": "international5" }, "to": [ { "key_code": "left_command" } ] }, { "type": "basic", "from": { "key_code": "international5" }, "to": [ { "key_code": "left_command" } ] }, { "type": "basic", "from": { "key_code": "international4" }, "to": [ { "key_code": "escape" } ] }, { "type": "basic", "from": { "key_code": "international2" }, "to": [ { "key_code": "international1", "modifiers": [ "left_shift" ] } ] }, { "type": "basic", "from": { "key_code": "international3" }, "to": [ { "key_code": "4", "modifiers": [ "left_shift" ] } ] } ] } ] }
{ "title": "Caps を Fn にしつつ、かっこよく使う", "rules": [ { "description": "caps hjkl for arrow", "manipulators": [ { "type": "basic", "from": { "key_code": "caps_lock" }, "to": [ { "key_code": "fn" } ] }, { "type": "basic", "from": { "key_code": "h", "modifiers": { "mandatory": [ "fn" ] } }, "to": [ { "key_code": "left_arrow" } ] }, { "type": "basic", "from": { "key_code": "j", "modifiers": { "mandatory": [ "fn" ] } }, "to": [ { "key_code": "down_arrow" } ] }, { "type": "basic", "from": { "key_code": "k", "modifiers": { "mandatory": [ "fn" ] } }, "to": [ { "key_code": "up_arrow" } ] }, { "type": "basic", "from": { "key_code": "l", "modifiers": { "mandatory": [ "fn" ] } }, "to": [ { "key_code": "right_arrow" } ] } ] } ] }
{ "title": "yabai の設定", "rules": [ { "description": "cmd arrows", "manipulators": [ { "type": "basic", "from": { "key_code": "left_command" }, "to": [ { "key_code": "right_command" } ] }, { "type": "basic", "from": { "key_code": "b", "modifiers": { "mandatory": [ "right_command" ] } }, "to": [ { "shell_command": "/usr/local/bin/yabai -m space --layout bsp" } ] }, { "type": "basic", "from": { "key_code": "b", "modifiers": { "mandatory": [ "right_command" ] } }, "to": [ { "shell_command": "/usr/local/bin/yabai -m space --layout bsp" } ] }, { "type": "basic", "from": { "key_code": "down_arrow", "modifiers": { "mandatory": [ "right_command" ] } }, "to": [ { "shell_command": "/usr/local/bin/yabai -m space --layout bsp" } ] }, { "type": "basic", "from": { "key_code": "f", "modifiers": { "mandatory": [ "right_command" ] } }, "to": [ { "shell_command": "/usr/local/bin/yabai -m space --layout float" } ] }, { "type": "basic", "from": { "key_code": "up_arrow", "modifiers": { "mandatory": [ "right_command" ] } }, "to": [ { "shell_command": "/usr/local/bin/yabai -m window --grid 1:1:0:0:1:1" } ] }, { "type": "basic", "from": { "key_code": "left_arrow", "modifiers": { "mandatory": [ "right_command" ] } }, "to": [ { "shell_command": "/usr/local/bin/yabai -m window --grid 1:2:0:0:1:1" } ] }, { "type": "basic", "from": { "key_code": "right_arrow", "modifiers": { "mandatory": [ "right_command" ] } }, "to": [ { "shell_command": "/usr/local/bin/yabai -m window --grid 1:2:1:0:1:1" } ] }, { "type": "basic", "from": { "key_code": "r", "modifiers": { "mandatory": [ "right_command" ] } }, "to": [ { "shell_command": "/usr/local/bin/yabai -m space --rotate 90" } ] } ] } ] }
睡眠についてメモ
注意 産業医さんに聞いた話のまとめ。 一次情報は探していない。
概要
トリプトファン が セロトニン になり、セロトニン が メラトニン になる。 メラトニンは睡眠をよくする。
日中にトリプトファンがセロトニンに変化し、夜になるとメラトニンに変化する。
トリプトファン
トリプトファンからセロトニンを合成するときに、ビタミンB6が必要になる。 カツオやバナナは、トリプトファンとビタミンB6が含まれていて、都合がよい。
セロトニン
セロトニンは精神を安定させ、ストレスを軽減させる働きがある。 朝に日光や照明などの強いヒカリを浴びると、メラトニンの分泌が止まり、セロトニンの分泌が始まる。
抗重力筋(ふくらはぎ、横隔膜、顎を上げる筋肉)を一定のリズムで動かすと、セロトニンが増える。 散歩やヨガ(呼吸で横隔膜を動かす)、ガムを噛む などが効果的。
メラトニン
寝付きがよくなる。
参照
包摂アーキテクチャ subsamption
知の創成 R.Pfeifer, C.Scheier
7章 サブサンプション アーキテクチャ Myrmix の概念図の清書
自然言語処理で使えそうな例文の一覧
形態素
食べさせられたがらなかった。 食べたがらせられなかった。
分からないこと
す・せる・させる
多くの場合、せる・させる のみが紹介されるが、す も使役の助動詞になると思う。 す が方言なのか、接続に動詞の活用形による制約があるのか?
食う 食わす
起きる 起こす
食う 食わせる 食わさせる
食らわす 食らわせる 食らわせられる
走る 走らせる 走らせられる 走らす 走らさす 走らされる
こぼす こぼさせる こぼされる
こぼれる こぼれさせる
受け身
投げられる は「ボールを投げられる」「柔道の技で投げられる」と主語が違う格でも同じ られる
文法上では、 食べられさせる のように受け身の後に使役を接続することができる。 状況が想定できる動詞はあるのか?
論文 text-to-speech 2018
論文
EFFICIENTLY TRAINABLE TEXT-TO-SPEECH SYSTEM BASED ON DEEP CONVOLUTIONAL NETWORKS WITH GUIDED ATTENTION
Hideyuki Tachibana, Katsuya Uenoyama, Shunsuke Aihara
概要
text to speech を解く NN を開発。 従来は RNN を使うことが多かったが、CNN を使うことで 学習時間を短縮した。 精度は acceptable を維持している。 guide attention も紹介する。
モデル
Text2Mel
Attention の Key, Value, Query の考え方を使っている。 CNN で text から Key, Value を作る。 Query は mel spectrum を使う。 時系列でずれていく mel spectrum が RNN の代わりをしている。
SSRN (Spectrogram Super-resolution Network)
mel spectrum 行列を upsampling する。 圧縮を解凍するイメージ。
Guided Attention
時間に従って線形に Attention がズレるという、 text-to-speech の特性から、 学習の最初の方だけ、Attention 行列がだいたい対角になるように 損失を追加する。
評価
crowdworker にお願いした。
用語
mel : 音の高低の知覚的尺度。 メル尺度の差が同じであれば、人間が感じる音の高さの差が同じになることを意図している。
STFT: short-time fourier transform, 短時間フーリエ変換。
bibtex
@inproceedings{tachibana2018efficiently, title={Efficiently trainable text-to-speech system based on deep convolutional networks with guided attention}, author={Tachibana, Hideyuki and Uenoyama, Katsuya and Aihara, Shunsuke}, booktitle={2018 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP)}, pages={4784--4788}, year={2018}, organization={IEEE} }