読者です 読者をやめる 読者になる 読者になる

(ブログ名 '未定)

プログラミングとかのメモ帳

ニューラルネットのアイディア

背景

実際の脳では誤差逆伝播法をしていないという考えのもと、以下のようなネットワークを考えた。
このネットワークでは、物理の法則を参考にし、ニューロンを惑星、バイアスを重力加速度もしくは電流の伝播と考えてみた。
物理の専門でも、人工知能の専門でもないただの学生が書いたものなので、間違えや誤用が多いです。
現状では、ただの妄想(実装もしていない)なので、効果の保証は全くない。ただのアイディアとして。うん。はい。もしかして、前例ある?

説明

構造

このネットワークでは、層の概念は無く、それぞれのニューロンは座標に存在していて、座標、自分の活性化状態、接続されるバイアスの情報を持つ。
バイアスは、伝播する元、伝播先、重さ(抵抗値orジーメンス)、電流値の保持、位置ごとの電圧をもち、t<-t+1ごとに、位置ごとの電圧が伝播していく。

Neuron :: (x,y,z), activity, [Adj]
Adj :: from, to, +-register, [voltage]

アルゴリズム

ニューロンには、以下のような法則がある

  1. |活性値|が高くなると、他のニューロンと距離を置く(原子間斥力)
  2. |活性値|が閾値以上で、ニューロンが分裂する(核分裂)
  3. |活性化|すると、接続されているAdjのWが活性の方向に強化される(重力加速度変化)
  4. 活性化したニューロン同士にAdjが発生する(重力加速度発生)
  5. 活性化した同士のニューロンは近づく(万有引力)

画像

メモをスキャンしたもの
f:id:ikemaki:20170114105838p:plain

雑感

実際にこのモデルが学習に有効かどうかを確かめる必要がある。
上のアルゴリズムに更に調整が必要
4分木空間分割、Trie木などが実装に有効だと思う

mbedでI2C通信

プログラミング 組み込み

 作成中のシステムでI2Cのプログラムが必要になり、勉強しがてら、簡単なテストモジュールを作ってみた。

作ったもの

マスター側のマイコンはスイッチの情報を読み込み(ジャンパー線と抵抗で代用している)、I2Cでその情報を送る。
スレーブ側のマイコンは、I2Cで送られてきた情報を読み込み、対応したLEDを点灯させる。
f:id:ikemaki:20161030144149p:plain

材料

名前 備考
LPC1768 1 マスター側のマイコン
LPC1114 1 スレーブ側のマイコン
LED 4 対応した情報を表示する
抵抗330Ω 4 LEDの抵抗
抵抗1kΩ  4 スイッチの代用品
抵抗2.2kΩ 2 I2Cのプルアップ抵抗

ソース

マスター側(LPC1768)

// test with lpc1768 

#include "mbed.h"

#define in_1 p5
#define in_2 p6
#define in_3 p7
#define in_4 p8

#define sda p28
#define scl p27
#define addr 0x0A

DigitalIn in1(in_1);
DigitalIn in2(in_2);
DigitalIn in3(in_3);
DigitalIn in4(in_4);

I2C master(sda, scl);

int main() {
    char cmd[4];
    DigitalIn inputs[4]={in1, in2, in3, in4};
    while(1) {
        // reset input_val
        for (int i=0; i<4; i++){
            cmd[i]=inputs[i];
        }
        // I2C tuusin
        master.write(addr, cmd, 4);
        
        wait(0.2);
    }
}

スレーブ側(LPC1114)

// test with lpc1114

#include "mbed.h"

#define led_1 dp10
#define led_2 dp11
#define led_3 dp13
#define led_4 dp14

#define sda dp5
#define scl dp27
#define addr 0x0A

DigitalOut led1(led_1);
DigitalOut led2(led_2);
DigitalOut led3(led_3);
DigitalOut led4(led_4);

I2CSlave slave(sda, scl);

int main() {
    char buff[4];
    DigitalOut leds[4]={led1, led2, led3, led4};
    
    int receive;
    
    slave.address(addr);
    while(1){
        // I2C tuusin
        receive = slave.receive();
        
        if(receive==I2CSlave::WriteAddressed){
            slave.read(buff, 4);
        }
        // led_ reset
        for(int i=0; i<4; i++){
            leds[i]=buff[i];
        }
        wait(0.1);
    }   
}

感想、考察など

  • mbed同士なら、ピン番号を変えるだけで、同じマイコンでも動作するようになるはず、、、。
  • I2Cののプルアップ抵抗を忘れて、何時間も苦労した。
  • 長年の疑問を解決したような感覚で、嬉しい。

参考文献

このモジュールを作成するにあたっては、以下のサイトが参考になりました。ありがとうございました。

I2Cの原理を動画で分かりやすく解説しています。

mbedでI2Cのライブラリを使う方法を解説しています。

プロコンの反省を書き連ねるだけの雑記

プロコン

プロコンの反省や経験など書き連ねただけの雑記
思いついつく度に追加します

やったこと

第27回プログラミングコンテスト競技部門に参加した
第27回 高専プロコン 競技部門 - Google 検索
公式サイトの競技内容を簡単に内容を説明すると、
1).パズルの欠片の画像を取り込むと、自動的に置き方を表示するプログラムを作成して下さい
2).パズルを人力で埋めて下さい(作成したプログラムを使えとは言っていない)
と言うものである。

いつ、何をやっていたか

予選資料作成(4〜5月頃)

 ピースの画像を頂点データに変換する役割、与えられた頂点データを用いてパズルを解く役割、解いたパズルを表示する役割の内、私はパズルを解く役割を担当することになった。
 この頃から、n-1解(職人の経験と勘により巨大なピースを一つ抜かして、職人の経験と勘によりピースを適当に埋める方式)の有効性について知っていて、プログラムする以上は唯一解を探す方式を取らなければならないと思っていた。
 当時は唯一解を出すためには、二角の和が180度となる場合を探す方式も、等しい長さの辺を探す方式も、特別な場合を考えた時に唯一解に至らなくなると考えていて、考えうる全てのパターンを試す必要があると考えていた。 そうなると、探索空間も膨大になるわけで、、、。(以下ドキュメントに記載予定) とにかく、このことを考えながら、後の空白の三ヶ月に突入することとなる

空白の三ヶ月(6〜9月中盤)

 この間には、夏休みを始め多くの休日が存在していたが、ほとんどコードを書けなかった。理由としては、時間を遊びに使ってしまったこと、まだ時間があると考えてしまったこと、とりあえず指を動かさなかったこと、問題を解く気にならなかった事にある。 根本的には、問題を解く気にならなかった事が原因だと思っている。
 先延ばし魔の威力は絶大なものだったと今でも反省している。
 

精神と時の部屋(9月終盤〜プロコン当日)

 結局、夏休みの最終盤までコードを書くことはせず、地獄の二週間が始まることとなった。ここまでに実装されていたのは、ピースの定義・当たり判定・座標をピースに変換する関数だけで、言ってしまえば、他の関数は実装されていなかった。

ピースの結合(プロコン二週間前〜プロコン一週間前ぐらい)

 まず取り掛かったのは、ピースの結合である。
 ピースの結合とは、ピースAのある点Anと、ピースBのある点Bmを、合わせることにより、新しいピースに変換する動作である。角度と裏表を付けたピースを2つ用意し、誤差範囲以下にある2つの点を原則一つの点にした後、角度が360度か180度になった点を排除する。このことにより実装した
 最も基礎的な部分であるが、考えた項目(辺の上にある点、点が辺に接触する場合、図形の中に図形を内包する場合など)が多く、結合の時に発生する全ての事象を考慮しようとし、多くの時間がかかり、思考に苦労した。

誤差と探索 (プロコン1週間前ぐらい〜プロコン4日前)

 この時から、パズルのピースとモニタを 二対一 でにらめっこすることとなる。
 画像を取り込む時に発生する誤差、それをプログラムすることは楽に出来た。ただ、誤差の調整と全探索は、両者は矛盾しているものだと思うこととなる。
 問題は、プログラムは、現実は異なるピースを誤差が原因で、同じピースであると判断すること、もしくは、本来は同じ座標にある点が誤差が原因で、合成されなくなることであった。 ピースの結合が狂うことの問題は、全探索しようとする時に発生し、誤差と全探索の間に発生する矛盾を考えていた。

手動動的計画法(プロコン4日前)

 大会まで残り4日になった中、私は、探索を動的計画法(当時は、ピース一つ一つの結合を小さな問題と考えていた)で書こうと思っていた。ただ、誤差を考えると、プログラムが書けなくなることも知っていたわけである。 そんな中、部活に参加してある声を聞くこととなる
>> 人力をサポートするプログラムを作れば?
 まぁ、こんな感じの声だったと思う。動的計画法・全探索・誤差・残りの時間・人力のサポート・自分の現状・・・そんな事を考えながら、お風呂から上がると、突然と指が動き始めた。私が手動動的計画法と名付けるアルゴリズムの設計が、微小な時間にて書き上げられたのである。
 
手動動的計画法は、誤差と全探索の矛盾を埋め合わせるために考えたアルゴリズムで、動的計画法で言う"小さな問題を解くこと":このプログラムで言う"確定されたピースの結合"は人間が行う。プログラムの機能は表面上、1)結合できるかもしれないピースを候補として表示する事と、2)人間が他にパターンが無いと判断したピースの候補を、コマンドライン上に打ち込ませること、3)そして内部的なピースの状態を更新することの3つである。

ここに画像を追加する予定

新たなる実装(プロコン3日前〜競技部門本戦中)

 新しいアイディアを考えてから、他の人の手を借りながら実装を始めた。そして、三日三晩の徹夜や、特急コーディング、そして、会場コーディングを経て、実装が終わることとなる。

戦いの終焉(プロコン競技部門終了〜数日後)

 結果として、プログラムはつまらない理由(ファイルシステムの違い)で動作しなかった。他のいかなるプログラムも人力に圧倒された事、もっと計画的にやっておけば良かったという反省・・・などと、残念な気持ちに支配されながら、今年のプロコンは終わった。

反省点

  • 大会前のデスマはするべきでない。そもそもやった時点で負けだと思うべき
  • チームメートとのコミュニケーションをもっと取っておけばよかった。
  • 緊張により、大会中にいつも通りのパフォーマンスを出せなかった。練習を予め積んでおけば、緊張はほぐされたと思う
  • 長期休業中にプロコンの準備ができると思わないほうがいい。可能なら、休業前に作るべき
  • 先延ばし魔の恐怖を味わう前に片付ける
  • 完全に動くと思われたプログラムが、つまらないミス(文字コードの互換性)で動作しなかった。練習を予め積んでおけば、問題に対処できたと思う。
  • もっと他の高専生達と交流したかった(ただし運営側のシステムにも問題がある。)
  • 計画性がなかった。もっと早い時期から書いていたら、徹夜も軽いものになっただろうし、練習の時間もとれ、プログラムの質が上がっただろう
  • モチベーションの維持が出来なかった(運営にも問題がある気がするが...。)やる気さえあれば、計画無視で急速にプロジェクトが進むと思った。

成果物

二回戦開始直前に作り終えたプログラム。
本番では、Windowsとのファイルシステムの違いにより、データを読み込めなかったと言う悲劇が発生した。
簡単にシステム概要を説明すると、
ピース毎の頂点座標を入力すると、ピース(枠を含む)に変換し、合体出来るピースの候補を探索・表示してくれる。
そこで、どのピースを合体したか?コマンドラインから入力することで、ピースの数がどんどん減っていく仕組み
f:id:ikemaki:20161014193441p:plain

ソースコードはこちら
github.com

微修正やドキュメント整備は後日やります。
アルゴリズムの詳細なども追加する予定

その他

デバイスの通信量を記録するツールを作ってみた

プログラミング ruby

 学校でネットワークの通信量を日ごとに見られるソフトをインストールせよ、との指令が出た。Windows版なら学校側から推奨されているソフトがあったが、Linuxには自分の体に合いそうなものは存在しなかった。
 仕方ない。自作るか

github.com

機能について

このツールには以下のような機能がある、

  1. 独自の形式のログファイルを作成し、そこに日ごとのデバイスの通信量(受信・送信)を記録する
  2. /proc/net/dev にはシステムが起動した以降に、それぞれのデバイスが何バイト分の通信をしたかの情報が出力される。この差分を一定時間ごとに取得し、ログに書き込む
  3. GUIの実行が可能で、日ごとの通信量が表として表示される

ドキュメントなど

Githubに追加予定

その他

出来たてホヤホヤで多分バグの宝石箱
何れ直していくさ。

追記 2016/05/29

案の定重大なバグが発生した。日付変更時に連続して起動していても、次の日のログへの変更が発生しない と言うものである。 しばらくの間は所用により変更できないため、6/10以降にバッチを作成しようと思う

Open Data Day 2016 in GEEKLAB.NAGANO に参加したためメモ書き

Open Data Day 2016 in GEEKLAB.NAGANO feat.NSEG に参加したためメモ書きします
glnagano.doorkeeper.jp

Open Data Day について

Open Data Dayの公式サイトには、オープンデータデイについて以下のようにあります

オープンデータデイは、オープンな公開データを使ってアプリケーションを書いたり、データを開放したり、視覚化したり、分析結果を公開するために世界中の市民が集まって、世界の地方、地域、そして中央政府によるオープンデータに関する政策の導入を支援、奨励します。

International Open Data Hackathon
おそらく、オープンデータを活用してプレゼンやハッカソンをするイベントを同時開催するという趣旨のイベントです

今回、GeekLabNaganoではMonacaとニフティクラウドを使った簡潔にアプリを作成する方法が紹介されました
これを元に、ハッカソンでは自分がいたチームは災害時支援アプリを作っていくことになります

おおよその日程

2016 3月5日に実施

時刻 やったこと
10:00~10:20 オープニング + ODD2016とGEEKLAB.NAGANOの紹介
10:30~12:00 ハンズオン(ニフティクラウド様)
13:50~17:30 ハッカソン (チームに別れて制作)
18:00〜20:00 懇親会・成果発表

ハンズオン

ハンズオンではニフティクラウドの川原 史識 さんが、Monacaとニフティクラウドを合わせた、オープンデータを用いたスマホアプリを簡単に作る方法が紹介されました。
sssslide.com
Monacaは、スマホアプリを作るツールで、HTML5とJSで開発するものです。それぞれの環境にビルドするという方式をとっているらしく、センサにアクセスする機能があり、WEBで開発できます。
ニフティクラウドは、無料から使えるクラウドサービスで、楽にサーバー構築でき、SDKを入れるだけで簡潔にサーバーとのやりとりができるというサービスです。
このMonacaとニフティクラウドを合わせると、楽に○○マップが作れる。そして、除雪マップの市民に除雪させるアプリや、Pepperの観光案内、鎌倉今昔写真というアプリなどに、活用されている。ということが紹介されました。
この時、Monacaやニフティクラウドの登録をし、サンプルアプリをいじってみた といったことが今回のハンズオンの内容でした。

ハッカソン

ハッカソンでは、2〜4人程度のチームに別れて制作したり、設計したりしました。
ルールは、オープンデータを使った地域に役立ちそうなものを作るということでした。

アイディアの例

チームごとの制作の前に、オープンデータを活用するアイディアについて紹介さました。以下に例の一例を出します 

  • おくやみ情報
    • 友人が死亡していた時とかに通知してくれると便利かもしれないと思った。
  • Wifiマップ,充電器の場所 
    • フリーWifiの場所とか知りたいときは多い。
  • 緑の自転車の乗り捨て場 停車所とかを表示 
    • 長野市内の無料で借りられる自転車。観光客とかには停車所の位置情報は必須だと思った。

自分のいたチームについて

自分のいたチームでは、色々と議論した後、災害時の助け合いをすすめるアプリを作成することに決定しました。
ここから、各々に作業を分担し、1人はプレゼン資料作成、1人は地図への表示機能、そして自分はアンケート機能を制作していきました

制作しようとしたもの 概要

災害時に活用するアプリ
支援を必要とする要支援者と、要支援者を支援する支援者を橋渡しするツール。主に2つのモードがある

  1. 要支援者のためのアンケートを入力フォーム
    • 名前や緯度・経度、緊急度のレベル付、必要な支援の登録、メッセージの入力を行う
  2. 支援者のためのマップ
    • 入力されたデータを元に、マップに情報を表示する
    • 火事場泥棒対策のため、詳しい位置は最初からは表示しない。円でぼかしておく
    • 緊急度のレベルに基づく色分け
    • 特定のニーズに合わせた絞り込み

といった機能を考えました
アプリ上での実装目標です
f:id:ikemaki:20160306005133p:plain

制作結果

自分は要支援者のためのアンケート入力フォームの作成を行いました。
フォームの型の作成は難なく出来ましたが、2時間近くJavaScriptが使えない謎の自体に陥りました。そこで、Monacaの確認のエミュレーターのようなものを利用してテストしていたところを、ブラウザを使ってテストをするようにすると、JavaScriptが使えるようになりました。たぶん、エミュレーターがJavaScirptの読み込みができないことによると思いました。
JavaScirptが使えるようになってから、サーバーへの送信関数を作ろうとしましたが、ここでタイムオーバーになりました。
成果物を上げておきます。 必要な機能を満たしていないため、これからも機能を追加できたらなぁと思います。
GitHub - Makinori/disaster_support

Lispで深さ優先探索

Lisp

Common Lisp深さ優先探索をしました
正しく説明できている自信がないので、間違えなどはご指摘いただけるとありがたいです
あまり参考にしないほうがいいと思います(汗
とりあえずコードから

(defparameter *graph*
  '((a b c d)
    (b c)
    (c d)
    (d a)))
    
(defun depth-search (passed-point goal graph)
  (let* ((now-point (car passed-point))
         (next-points (cdr (find-if #'(lambda (point)
                                        (equal now-point (car point)))
                                    graph)))
         (new-graph (remove-if (lambda (x)
                                 (equal now-point (car x)))
                               graph)))
    (cond ((eq now-point goal) (list (reverse passed-point)))
          (t (mapcan #'(lambda (point)
                         (depth-search
                          (cons point passed-point)
                          goal
                          new-graph))
                     next-points)))))

実行は

CL-USER> (depth-search (list 'a) 'd *graph*)
((A B C D) (A C D) (A D))

課題内容

ある点からある点までの考えうる全ての経路を表示せよ
以下のような形式のデータが与えられる

[(a b c d)
 (b a c e)
 (c a b f) ...]
X Y

それぞれの()内の構造は、
(点N 点Nから行ける点1 点Nから行ける点2 ...)
のようになっていて、この配列をグラフと言う。
このとき、点Xから点Yに到達できる経路すべてを表示せよ。
ただし、同じ点は2回以上通ってはいけないものとする

課題の例

たとえば、このデータが与えられたとする

[(a b c d) (b c) (c d) (d a)]
a d

グラフイメージするとこんな感じだ
f:id:ikemaki:20160208234346g:plain
この問題は、上のようなグラフの点aから点dまでの経路を考えるというものだ。
この時、考えられる経路は、はじめにa->bを通った場合、a->cを通った場合、a->dを通った場合の3つになるだろう。そうすると
a -> b -> c -> d 
a -> c -> d
a -> d
になる。このように、経路を探索するのが今回の課題だ

今回の考え

  1. 関数searchには、経過した点、ゴール、グラフの3つの情報が与えられる
  2. 経過した点の配列から、最後に通った点(点N)を抜き出す
    1. グラフから、点Nから行ける点の配列(配列G)を抜き出す
    2. グラフから、点Nを除いたグラフ(新グラフ)を作る
  3. これを元に、以下の動作をする
    • 点Nがゴールと同じなら、配列Pを返す
    • 配列Gが空なら、空配列を返す (明記されていない)
    • 配列Gのそれぞぞれの要素(点G)に同じことをし、空配列を取り除く
      1. 関数searchに、点Gと経過した点を合わせた配列、ゴール、新グラフを与える

というのが、上のコードを日本語に概訳したものだ。

改良すべき点

  • (equal now-point (car x)) が2つあって気持ち悪い。
  • 再帰呼出しごとに、グラフのコピーが発生していて、メモリを圧迫しかねない。そもそもnew-graphの存在自体が疑問
  • 同じことを同じ引数で処理している。メモ化すべき
  • わかりにくい。高速化の前に、更に行う処理をシンプルにしたい

とりあえず思いついたことです
このプログラムは巨大なグラフが与えられると、一発で死ぬと思われるので、全く実用的ではありません。
私の力不足を感じた次第であります

参考文献

Common Lispによるグラフの探索が細かく書かれています。この方は他にも多くの記事を書かれていて、プログラミングに関する様々なノウハウが詰まっています

ブログの公開について

長年作ろうと考えていましたが、実際に公開するのは初めてです。

個人的にはプログラミングや回路に興味があり、その方向で制作物や製作記、発見などの記事を書いていきたいと思っています。

よろしくお願いします