録画用HDDを修復してみた話
EPLUのタキヤマです
もう夏も終わりですね
今年は夏らしいこと色々したので少し寂しいものがあります
冬は苦手でスノボくらいしか楽しみが無いので、来年の夏が待ち遠しいです
さて、前回はNoSQLについて書いてみたりもしましたが
技術者らしい真面目なネタはあまり持ち合わせていないので、今回は最近あった身近なことをそれっぽく書いてみます
NVIDIA GTC JAPAN 2018 にご来訪いただきありがとうございました
9/13, 14 に開催されました GPU Technology Conference (GTC) JAPAN 2018 におきましては、多くの方に弊社ブースへお立ち寄りいただきまして誠にありがとうございました。
弊社ブースでは、 NVIDIA 社の自立走行車開発プラットフォームである Drive PX 2 を用いて、 3D LiDAR でリアルタイムに取得した点群情報から GAN (Generative Adversarial Network) を利用して画像補完することで物体認識率を向上させるデモをご紹介させていただきました。
また、テクニカルセッションでは、株式会社 SUBARU 小山様の「 SUBARU 将来の自動運転と知能化技術の取り組みについて」講演での強化学習部開発に弊社もご協力させていただきました。
講演の内容は Car Watch 様の以下記事に掲載されておりますので、こちらも是非ご覧ください。
Simulinkによる順次シミュレーションを作る
今回のブログ担当のシロハです。
今回のテーマは、私が業務で使用することのあるMATLAB/Simulinkというツールについてです。
初めに
今回の記事で扱う内容は、mファイルを用いたSimulinkの順次シミュレーションの実行についてです。
また、MATLAB/Simulinkの基礎(mスクリプトの扱い方、Simulinkでのモデル作成やシミュレーションの実行方法)を知らないと理解が難しい内容が含まれます。
順次シミュレーションとは
初めに、順次シミュレーションとは、事前に複数パターンのシミュレーションの仕込みをしておいて、シミュレーションを1度実行すれば、全てのシミュレーションを終わらせてくれる、というものです。
順次シミュレーションの目的
1Dシミュレーションでは一般的に、3Dシミュレーションよりも1回のシミュレーションに時間が短いですが、その分複数パターンの検証が必要になることが多い、ということを何度か経験しました。
ただし3Dよりは早いといっても、モデルと検証条件によっては1パターンで1時間以上かかることもよくあります。
ということで今回の目標は、
順次シミュレーションを用いることで、帰宅前や金曜日の帰り際にシミュレーションを実行する⇒次の出勤時にシミュレーション結果が確認できる、というものを目指します。
順次シミュレーションの流れ
まず、順次シミュレーションを行う為にMATLAB/Simulinkにどのような作業をして欲しいのか、について考えます。
- 複数パターンのシミュレーションをコンピュータに順次行ってもらうために、mスクリプトからシミュレーションを実行する必要があります。また、実行したいパターン数だけシミュレーションを繰り返す必要があります。
- 全く同じシミュレーションを繰り返しても意味はないので、シミュレーションのたびにブロックの配置や結線・パラメータなどを書き換える必要があります。
- シミュレーションを実行した後で結果が残っていないのでは意味がありません。シミュレーション結果を保存して、外部にエクスポートする必要があります。
では、これらの作業をmファイルに書き込んでみましょう。
- matlabのスクリプトでSimulinkのシミュレーションを実行する場合は、sim関数を用います。
使い方:sim('シミュレーションしたいSimulinkのモデル名')
また、複数のパターンをシミュレーションする必要があるため、sim関数や、この後説明する要素をfor文の中に記述する必要があります。 - スクリプトからブロックの配置や結線・パラメータ書き換えを実行します。ブロックを配置・パラメータ変更するためにはブロックの持つパラメータ名を知っておく必要があります。
知っておく必要のある関数について
ブロックパラメータの変更:set_param
ブロックパラメータの取得:get_param
ブロックの配置:add_block
ブロックの結線:add_line
説明すると長くなるため、関数の詳細はヘルプを参照してください。 - :ブロックパラメータ名の調べ方
その1:以下のページでブロックパラメータ名を調べることが出来ます。
https://jp.mathworks.com/help/simulink/slref/block-specific-parameters.html
その2:get_param関数を用いてブロックパラメータ名を調べます。
ブロックパラメータは、関数add_blockでブロックを配置したり、set_paramでブロックパラメータを変更する際に必要になります。
a:パラメータ名を調べたいブロックをダブルクリックして、調べたいパラメータの値を適当な値(11111111など)にします。
b:パラメータ名を調べたいブロックをクリックします。
(手順b~cまでの間に他のブロックをクリックしないこと。分かる方向けにいうとgcbを用いているため)
c:次のコードをエディタ、またはコマンドウィンドウで実行します。
DATA=get_param(gcb,’ObjectParameters’);
PARAM=fieldnames(DATA);
for i=1:length(PARAM)
PARAM{i,2} = get_param(gcb,PARAM{i,1});
end
d:実行した結果がワークスペースのセル配列'PARAM'に保存されています。
PARAMの1列目がパラメータ名、2列目が1列目に対応したデータとなっています。
セル配列 PARAM の中に、先ほど設定した適当な値があるので、その隣の1列目に書いてあるのが目的のパラメータ名となります。 - シミュレーション結果を保存する方法はいくつかありますが、今回はSimulinkに「To Workspace」ブロックを配置してから、xlswriteでエクスポートすることでデータを保存します。
ちなみに、単純にデータを保存するだけならばSimulinkに「To File」ブロックを置くのが一番簡単です。ただ、Simulinkとの連携に限らず、xlswriteでデータをエクスポートするという手法が便利であること、またWorkSpaceに一度データを残すことで、WorkSpace上のデータを処理してからエクスポートすることが可能になるなど応用が利くため、今回はxlswriteを用います。
基本的な骨組み
先ほどの1~3を組み合わせて、順次シミュレーションの骨組みを作ると以下のようになります。
S = シミュレーションのパターン数;
for i=1:S %S回シミュレーションを実行する
switch i %case文の中にパラメータやソルバなどの、シミュレーション毎に変更する点を記述する
case 1
set_param(~)
add_block(~)
add_line(~)
case 2
set_param(~)
add_block(~)
add_line(~)
case 3
・・・
otherwise
end
sim(‘モデル名’) %シミュレーションを実行
xlswrite(~) %データをエクスポートする
end
この骨組みを基本として、Switch文の中に必要に応じて関数を追加すれば順次シミュレーションの完成です。
NVIDIA GTC JAPAN 2018 のご案内
来週 9/13, 14 に NVIDIA 社主催の GPU Technology Conference (GTC) JAPAN 2018 が開催されます。
今年は弊社も SILVER SPONSOR として協賛させていただいております。
当日はスポンサーブースにて弊社の深層学習活動の一環として、 3D LiDAR でリアルタイムに取得した点群情報から GAN (Generative Adversarial Network) を利用して画像補完することで物体認識率を向上させるデモをご紹介させていただく予定です。
イベント参加の折には、是非弊社ブースへお立ち寄りください。
Rustでデカルトの葉
近況
また出番が回ってきました砂子です。もう何回目の投稿になるのでしょうか?
今年は本当に暑いですね。普段エアコンは極力使わないようにしてきまたが、 さすがに暑かったのでを久しぶりに電源をいれ涼もうしました。しかし、どう も調子が悪いようなので修理を依頼しました。立ち会いの都合などで、一週間 ほど故障した状態が続いたのですがなんだか無性に暑く感じました。
新言語
さて、私はプログラマーであるわけで当然プログラム言語を記述して仕事をし ております。職務として長らく使ってきたのはC#言語となります。現職務は WEB開発のフロントエンドを担当しているのでTypeScriptをメインとしており ます。思えば、どちらもマイクロソフトに縁が深い言語ですね。
上記2つの言語を深く理解するのも大事ですが、新しいプログラミング言語を 習得し知見を広げることも大事と考え、Rustというものを学習をしてお ります。目下のところ、The Bookと呼ばれるオンラインドキュメントを 読みつつ学習しています。
公式ページにあるように速度、安全性、並行性を目的としてプログミン グ言語であるようです。最も学習を初めて間もないため3つのうち安全性に関 連した要素しか実感できておりません。此の実感した要素は安全性に関連する 「所有権」です。恐らく大半の言語では聞かない概念であると思います。
まあ、実感したというのはコードを書くうえで面倒だったということです。習得 しているプログランミング言語にもよりますが、2つ目以降の言語としてRust を学習する方々は必ずこの所有権の概念で同じことを思うでしょう。
Rustの学習がて簡単なプログラムを書いてこのブログ記事にしよと考えたち、 なにが題材としてよいか自宅にある書籍を物色しました。
デカルトの葉
いくつか書籍を眺めていたら古典的難問に学ぶ微分積分の序章にデカル トの葉が描かれてるのが目に止まりました。曲線を描くというのも難易度とし 難しくないと考えこれを題材にしようと考えました。
デカルトの葉とはWikipediaではデカルトの正葉線として説明がなされて いる代数曲線になります。大学で微積分を学んだ方なら教科書に描かれていたもの が記憶に残っているのではないでしょうか?
直行座標の方程式による定義は下記のようになります。
上記の数式はまたパラメータ表示として下記のようにも表わされます。
また、第一象限のループで囲まれる面積は下記のようになります。
そこで3つのことをRustで実現しよう。
- パラメータ表示による曲線のプロット
- 直行座標の方程式を使用した乱数による曲線のプロット
- ループで囲まれる面積の乱数を使用した近似値の計算
なお、以降ではとして計算する。
Rust 準備
Rustのインストール等の説明は公式ページを見てください。 以下ではプロジェクト作成と使用したライブラリだけを記述します。
プロジェクトを作成。引数でライブラリではなく実行可能なアプリとして設定しています。
cargo new folium_of_descartes --bin
使用する外部ライブラリを設定します。 出来上がったプロジェクトフォルダ内のCargo.tomlを下記のように編集します。
[package] name = "folium_of_descartes" version = "0.1.0" [dependencies] gnuplot = "0.0.26" rand = "0.5"
main.rsを編集後、プログラムを実行するには下記コマンド実行です。 初回はCargo.tomlで設定したライブラリのダウンロード等が行われます。 記述ミスがあった場合はこの段階でエラーなり、警告がでます。
cargo run
Rust ソースコード(main.rs)
そして、記述したコードを貼っておく。プロジェクトフォルダに出来上がったmain.rsに記述した。
extern crate gnuplot; extern crate rand; // プロット用のライブラリ use gnuplot::*; // 乱数発生用のライブラリ use rand::prelude::*; use rand::prng::XorShiftRng; //// パラメータにより曲線を描画する fn draw_curve_parameter() { // 3つの範囲で(x,y)を算出 // -100 < t < -2 let ts1 = get_parameter(-100., -2., 0.1); let xs1 = get_x_from_parameter(&ts1); let ys1 = get_y_from_parameter(&ts1); // -0.5 < t < 0.0 let ts2 = get_parameter(-0.5, 0.0, 0.05); let xs2 = get_x_from_parameter(&ts2); let ys2 = get_y_from_parameter(&ts2); // 0.0 < t < 5.0 let ts3 = get_parameter(0.0, 5.0, 0.1); let xs3 = get_x_from_parameter(&ts3); let ys3 = get_y_from_parameter(&ts3); // -5.0 < x < 5.0, -5.0 < y < 5.0 をプロット let mut fg = Figure::new(); // fg.axes2d() .set_aspect_ratio(Fix(-1.0)) .set_x_axis(true, &[]) .set_y_axis(true, &[]) .set_x_range(Fix(-5.), Fix(5.0)) .set_y_range(Fix(-5.), Fix(5.0)) .points(xs1, ys1, &[Color("green")]) .points(xs2, ys2, &[Color("blue")]) .points(xs3, ys3, &[Color("red")]); fg.show(); } /// 指定された範囲のパラメータを取得する fn get_parameter(start: f64, end: f64, step: f64) -> Vec<f64> { let mut tmp = Vec::new(); let mut x = start; while x < end { tmp.push(x); x = x + step; } tmp } /// パラメータに対応したXを取得する fn get_x_from_parameter(ts: &Vec<f64>) -> Vec<f64> { ts.into_iter().map(|t| (3.0*3.0*t)/(1.0+t.powi(3))).collect() } /// パラメータに対応したYを取得する fn get_y_from_parameter(ts: &Vec<f64>) -> Vec<f64> { ts.into_iter().map(|t| (3.0*3.0*t.powi(2))/(1.0+t.powi(3))).collect() } /// 乱数により曲線を描く fn draw_curve_random() { let seed = [0u8; 16]; let mut rng = XorShiftRng::from_seed(seed); let mut xs: Vec<f64> = Vec::new(); let mut ys: Vec<f64> = Vec::new(); let mut i = 10000000; while i != 0 { let x = rng.gen_range(-5., 5.) as f64; let y = rng.gen_range(-5., 5.) as f64; let z = x.powi(3) + y.powi(3) - 3.0 * 3.0 * x * y; if z.abs() < 0.001 { xs.push(x); ys.push(y); } i = i - 1; } let mut fg = Figure::new(); fg.axes2d() .set_aspect_ratio(Fix(-1.0)) .set_x_axis(true, &[]) .set_y_axis(true, &[]) .set_x_range(Fix(-5.), Fix(5.0)) .set_y_range(Fix(-5.), Fix(5.0)) .points(xs, ys, &[Color("blue")]); fg.show(); } /// 第一象限の面積を描く fn draw_area() { // 乱数初期化 let seed = [0u8; 16]; let mut rng = XorShiftRng::from_seed(seed); let mut xs: Vec<f64> = Vec::new(); let mut ys: Vec<f64> = Vec::new(); let size = 100000; let mut i = size; while i != 0 { let x = rng.gen_range(0., 5.) as f64; let y = rng.gen_range(0., 5.) as f64; let z = x.powi(3) + y.powi(3) - 3.0 * 3.0 * x * y; if z < 0.001 { xs.push(x); ys.push(y); } i = i - 1; } // 曲線内部と判定された割合から面積を算出する let area = 5.0 * 5.0 * xs.len() as f64 / size as f64; let mut fg = Figure::new(); fg.axes2d() .set_title(&format!("面積:{}", area), &[]) .set_aspect_ratio(Fix(-1.0)) .set_x_axis(true, &[]) .set_y_axis(true, &[]) .set_x_range(Fix(0.), Fix(5.0)) .set_y_range(Fix(0.), Fix(5.0)) .points(&xs, ys, &[Color("blue")]); fg.show(); } fn main() { draw_curve_parameter(); draw_curve_random(); draw_area(); }
結果
新言語とはいえ単純な文法だけでも曲線は十分に描け、簡単な数値実験を行な うことができた。やはりドキュメントを読むだけでは飽きが来ることや理解の 度合いが感じづらいので簡単なゴールを設定してみるとモチベーションに繋が りやすい。
パラメータ表示による曲線のプロット
パラメータによる曲線の描画は関数draw_curve_parameter()で行った。プロットは下図のようになった。 緑は で第一象限、 青はで第二象限、赤は で第4象限となります。
しかし、曲線上に均等に点が描画されると予想したがそうはならなかった。方程式の形で見ているとまるで 曲線上に点が密に分布するイメージを持つがそんなことはなかった。
直行座標の方程式を使用した乱数による曲線のプロット
関数draw_curve_with_random()で乱数で大量の座標を生成し、に適合する座標のみをプロットした。
こちらは均等に点が分布にすると考えたがならなかった。考えてみれば曲線の変化率は場所ことに違うので確かに均等に分布しないことになる。つまり、ある曲線の部分では変化率が小さいため上記の判定が真になる面積が大きいが、またある場所では変化率が大きいため上記判定で真になる面積は少ない。それが場所ごとの点の分布に現れるのではないか?
ループで囲まれる面積の乱数を使用した近似値の計算
関数draw_area_with_random()で第一象限のループ状の内部の面積を求めてみた。 上記曲線描画と同様に乱数で大量の座標を生成し、で判定された座標の個数と 生成した座標の割合を乱数生成の範囲の面積にかけて算出している。
期待値はであるので、近似値がえられている。
所感
学習中のプログラミング言語でも自分としては有益な結果がでた。学生時代にこうゆうことをやっていれば微積分にも もっと興味をもって取り組めたのではないだろうか?
Rustの習熟度は正直かなり問題ありですね。いろいろあるが早急に下記は対応したい。
- ドキュメント、コメントの書き方
- ライブラリのドキュメントの読み方
- 開発環境(Emacs)の整備
曲線の描画は興味深いテーマであったと思う。Rustの学習を進めながら曲線を調べて描画を行っていこう。 できれば学生時代の卒論であつかったMD6の実装を最終ゴールとしたい。ではこれにて。