iPX社員によるブログ

iPX社員が"社の動向"から"自身の知見や趣味"、"セミナーなどのおすすめ情報"に至るまで幅広い話題を投下していくブログ。社の雰囲気を感じ取っていただけたら幸いです。

録画用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) を利用して画像補完することで物体認識率を向上させるデモをご紹介させていただきました。
f:id:ipx-writer:20180925114137j:plain:w266:h398f:id:ipx-writer:20180925114123j:plain:w365:h274f:id:ipx-writer:20180925114100j:plain:w403:h302

また、テクニカルセッションでは、株式会社 SUBARU 小山様の「 SUBARU 将来の自動運転と知能化技術の取り組みについて」講演での強化学習部開発に弊社もご協力させていただきました。
講演の内容は Car Watch 様の以下記事に掲載されておりますので、こちらも是非ご覧ください。

f:id:ipx-writer:20180925114824j:plain:w380:h214

Simulinkによる順次シミュレーションを作る

今回のブログ担当のシロハです。
今回のテーマは、私が業務で使用することのあるMATLAB/Simulinkというツールについてです。

初めに

今回の記事で扱う内容は、mファイルを用いたSimulinkの順次シミュレーションの実行についてです。
また、MATLAB/Simulinkの基礎(mスクリプトの扱い方、Simulinkでのモデル作成やシミュレーションの実行方法)を知らないと理解が難しい内容が含まれます。

順次シミュレーションとは

初めに、順次シミュレーションとは、事前に複数パターンのシミュレーションの仕込みをしておいて、シミュレーションを1度実行すれば、全てのシミュレーションを終わらせてくれる、というものです。

順次シミュレーションの目的

1Dシミュレーションでは一般的に、3Dシミュレーションよりも1回のシミュレーションに時間が短いですが、その分複数パターンの検証が必要になることが多い、ということを何度か経験しました。
ただし3Dよりは早いといっても、モデルと検証条件によっては1パターンで1時間以上かかることもよくあります。
ということで今回の目標は、
順次シミュレーションを用いることで、帰宅前や金曜日の帰り際にシミュレーションを実行する⇒次の出勤時にシミュレーション結果が確認できる、というものを目指します。

順次シミュレーションの流れ

まず、順次シミュレーションを行う為にMATLAB/Simulinkにどのような作業をして欲しいのか、について考えます。

  1. 複数パターンのシミュレーションをコンピュータに順次行ってもらうために、mスクリプトからシミュレーションを実行する必要があります。また、実行したいパターン数だけシミュレーションを繰り返す必要があります。
  2. 全く同じシミュレーションを繰り返しても意味はないので、シミュレーションのたびにブロックの配置や結線・パラメータなどを書き換える必要があります。
  3. シミュレーションを実行した後で結果が残っていないのでは意味がありません。シミュレーション結果を保存して、外部にエクスポートする必要があります。

では、これらの作業をmファイルに書き込んでみましょう。

  1. matlabスクリプトSimulinkのシミュレーションを実行する場合は、sim関数を用います。
    使い方:sim('シミュレーションしたいSimulinkのモデル名')
    また、複数のパターンをシミュレーションする必要があるため、sim関数や、この後説明する要素をfor文の中に記述する必要があります。

  2. スクリプトからブロックの配置や結線・パラメータ書き換えを実行します。ブロックを配置・パラメータ変更するためにはブロックの持つパラメータ名を知っておく必要があります。
    知っておく必要のある関数について
    ブロックパラメータの変更:set_param
    ブロックパラメータの取得:get_param
    ブロックの配置:add_block
    ブロックの結線:add_line
    説明すると長くなるため、関数の詳細はヘルプを参照してください。

  3. :ブロックパラメータ名の調べ方
    その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列目に書いてあるのが目的のパラメータ名となります。

  4. シミュレーション結果を保存する方法はいくつかありますが、今回は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文の中に必要に応じて関数を追加すれば順次シミュレーションの完成です。

まとめ

MATLABは検索すると大体のことは知ることが出来るため、あえて今回は初心者向けではない内容にしております。MATLABの基本について知りたい方は「MATLAB 使い方」で検索すると良いと思います。

また、今回はあえてMATAB/Simulinkを連携させる形で順次シミュレーションを行っていますが、一般的にシミュレーションに掛かる時間を減らす場合は、シミュレーションの高速化や動的システムの並列シミュレーションを用いるようです。
尤も私がよく知らないために書けないのですが。

隠れマルコフモデルのお勉強

ご無沙汰しております。マルコフ部(非公認)部長の小川です。

業務上で隠れマルコフモデル(HMM)について理解する必要がでており、実装に際して理論の方のお勉強をしようと思います。

今回は第一回という事で条件付き確率についてお勉強した内容を記そうと思います。

続きを読む

NVIDIA GTC JAPAN 2018 のご案内

来週 9/13, 14 に NVIDIA 社主催の GPU Technology Conference (GTC) JAPAN 2018 が開催されます。
今年は弊社も SILVER SPONSOR として協賛させていただいております。

当日はスポンサーブースにて弊社の深層学習活動の一環として、 3D LiDAR でリアルタイムに取得した点群情報から GAN (Generative Adversarial Network) を利用して画像補完することで物体認識率を向上させるデモをご紹介させていただく予定です。

イベント参加の折には、是非弊社ブースへお立ち寄りください。

ねこ日記(3)

ご無沙汰しております、CPU(経営企画戦略室)所属のウメザワです。

前回ブログをいつ書いたのか調べてみたら約1年前でした。
(「ねこ日記(2)」が観たい方は"2017/7/7"をご参照ください)

「電気代を節約しながら朝まで起きずに快適に寝れるかどうかの瀬戸際をクーラーのおやすみタイマーで設定するのがプチブームです。」
とか書いてありましたが、そんなブームは過ぎ去り朝から晩まで(外出中も)つけっぱなしです。

まぁ今年はペットも危険なほどの猛暑なので、うちの可愛い子達の為にもつけっぱなしはやむを得ません。


ということでお待ちかねの癒し提供のターンに行ってみましょう!

続きを読む

Rustでデカルトの葉

近況

また出番が回ってきました砂子です。もう何回目の投稿になるのでしょうか?

今年は本当に暑いですね。普段エアコンは極力使わないようにしてきまたが、 さすがに暑かったのでを久しぶりに電源をいれ涼もうしました。しかし、どう も調子が悪いようなので修理を依頼しました。立ち会いの都合などで、一週間 ほど故障した状態が続いたのですがなんだか無性に暑く感じました。

新言語

さて、私はプログラマーであるわけで当然プログラム言語を記述して仕事をし ております。職務として長らく使ってきたのはC#言語となります。現職務は WEB開発のフロントエンドを担当しているのでTypeScriptをメインとしており ます。思えば、どちらもマイクロソフトに縁が深い言語ですね。

上記2つの言語を深く理解するのも大事ですが、新しいプログラミング言語を 習得し知見を広げることも大事と考え、Rustというものを学習をしてお ります。目下のところ、The Bookと呼ばれるオンラインドキュメントを 読みつつ学習しています。

公式ページにあるように速度、安全性、並行性を目的としてプログミン グ言語であるようです。最も学習を初めて間もないため3つのうち安全性に関 連した要素しか実感できておりません。此の実感した要素は安全性に関連する 「所有権」です。恐らく大半の言語では聞かない概念であると思います。

まあ、実感したというのはコードを書くうえで面倒だったということです。習得 しているプログランミング言語にもよりますが、2つ目以降の言語としてRust を学習する方々は必ずこの所有権の概念で同じことを思うでしょう。

Rustの学習がて簡単なプログラムを書いてこのブログ記事にしよと考えたち、 なにが題材としてよいか自宅にある書籍を物色しました。

デカルトの葉

いくつか書籍を眺めていたら古典的難問に学ぶ微分積分の序章にデカル トの葉が描かれてるのが目に止まりました。曲線を描くというのも難易度とし 難しくないと考えこれを題材にしようと考えました。

デカルトの葉とはWikipediaではデカルトの正葉線として説明がなされて いる代数曲線になります。大学で微積分を学んだ方なら教科書に描かれていたもの が記憶に残っているのではないでしょうか?

直行座標の方程式による定義は下記のようになります。

 { \displaystyle
   x^{3} + y^{3} - 3axy = 0
}

上記の数式はまたパラメータ表示として下記のようにも表わされます。

 { \displaystyle
   x = \frac{3at}{1+t{3}} \quad (t \neq -1)
}

 { \displaystyle
   y  = \frac{3at^{2}}{1+t^{3}} \quad (t \neq -1)
}

また、第一象限のループで囲まれる面積は下記のようになります。

 { \displaystyle
   S = \frac{3a^{2}}{2}
}

そこで3つのことをRustで実現しよう。

  • パラメータ表示による曲線のプロット
  • 直行座標の方程式を使用した乱数による曲線のプロット
  • ループで囲まれる面積の乱数を使用した近似値の計算

なお、以降では a=3として計算する。

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()で行った。プロットは下図のようになった。 緑は  - 100 \lt t \lt -2 で第一象限、 青は -0.5 \lt t \lt 0.0 で第二象限、赤は 0.0 \lt t \lt 5.0 で第4象限となります。 f:id:ipx-writer:20180727110853p:plain

しかし、曲線上に均等に点が描画されると予想したがそうはならなかった。方程式の形で見ているとまるで 曲線上に点が密に分布するイメージを持つがそんなことはなかった。

直行座標の方程式を使用した乱数による曲線のプロット

関数draw_curve_with_random()で乱数で大量の座標 (x,y)を生成し、 abs( x^{3} + y^{3} - 3axy ) \lt 0.001に適合する座標のみをプロットした。 f:id:ipx-writer:20180727110844p:plain

こちらは均等に点が分布にすると考えたがならなかった。考えてみれば曲線の変化率は場所ことに違うので確かに均等に分布しないことになる。つまり、ある曲線の部分では変化率が小さいため上記の判定が真になる面積が大きいが、またある場所では変化率が大きいため上記判定で真になる面積は少ない。それが場所ごとの点の分布に現れるのではないか?

ループで囲まれる面積の乱数を使用した近似値の計算

関数draw_area_with_random()で第一象限のループ状の内部の面積を求めてみた。 上記曲線描画と同様に乱数で大量の座標 (x,y)を生成し、 x^{3} + y^{3} - 3axy \lt 0.001で判定された座標の個数と 生成した座標の割合を乱数生成の範囲の面積にかけて算出している。 f:id:ipx-writer:20180727110739p:plain

期待値は S = \frac{3a^{2}}{2} = 13.5 \quad (a=3)であるので、近似値がえられている。

所感

学習中のプログラミング言語でも自分としては有益な結果がでた。学生時代にこうゆうことをやっていれば微積分にも もっと興味をもって取り組めたのではないだろうか?

Rustの習熟度は正直かなり問題ありですね。いろいろあるが早急に下記は対応したい。

  • ドキュメント、コメントの書き方
  • ライブラリのドキュメントの読み方
  • 開発環境(Emacs)の整備

曲線の描画は興味深いテーマであったと思う。Rustの学習を進めながら曲線を調べて描画を行っていこう。 できれば学生時代の卒論であつかったMD6の実装を最終ゴールとしたい。ではこれにて。