工作と競馬

電子工作、プログラミング、木工といった工作の記録記事、競馬に関する考察記事を掲載するブログ

カテゴリ: 4.ソフトウェア

Evernote デスクトップ版v10.4.4を使っていて、今更気付いたのだが、markdownが書けるようになってとても助かる。

昔も、少しは書けたような気がするが、いつの間にかかなり快適に書けるようになっている。

マークダウン書式を書くと、どんどんリアルタイムに変換していってくれる。それなりにいろんなものに対応している模様。

  • 見出し系は当然OK。#の数でレベルが変わって文字サイズが変わる。
  • 箇条書きもOK。番号付きリストもOK。というか、これはもともとMarkdownというかEvernoteの標準で書けたか。
  • 水平線もOK。
  • コードブロックも、バッククォート3つで出てきた。

```

テーブルは出し方がよくわからない。まあ、Markdownでテーブルを書くの自体、面倒なので、まあできなくてもいいか。

概要

kerasで、MNISTのサンプルを実装し、動かしてみた。


背景と目的

kerasを初めて使ってみる。手始めに、MNISTの手書き文字判別のNNを実装してみる。


詳細

0.環境

  • Jupyter
  • Python3

1.インポート

import os
import keras
from keras.models import Sequential
from keras.layers import Dense

2.ネットワーク

784ニューロンの入力層、中間層は128, 64, 出力層は10の全結合NNを定義

model = Sequential()

model.add(Dense(units=128, activation='relu', input_dim=784))
model.add(Dense(units=64, activation='relu', input_dim=128))
model.add(Dense(units=10, activation='softmax', input_dim=64))

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.SGD(lr=0.01, momentum=0.9, nesterov=True),
             metrics=['accuracy'])

3.データの取得

from keras.datasets import mnist
(xtrain, y_train), (x_test, y_test) = mnist.load_data()

4.学習

batch_size = 100
epochs = 10 # 終了エポック
initial_epoch = 0 # 開始エポック
x_train = x_train.reshape(60000, 784) # 2次元配列を1次元に変換
x_test = x_test.reshape(10000, 784)
x_train = x_train.astype('float32')   # int型をfloat32型に変換
x_test = x_test.astype('float32')
x_train /= 255                        # [0-255]の値を[0.0-1.0]に変換
x_test /= 255
y_train = keras.utils.to_categorical(y_train, 10)
y_test = keras.utils.to_categorical(y_test, 10)

from keras.callbacks import ModelCheckpoint
fpath = 'weights.{epoch:04d}.hdf5'
cb = ModelCheckpoint(
    fpath, # 保存先ファイルパス
    verbose=1, # コマンドライン出力
    savebestonly=True) # 精度が良くなった時だけ保存

weighthdf5 = "weights." + str(initialepoch).zfill(4) + '.hdf5'
if os.path.exists(weighthdf5):
    model.loadweights(weighthdf5)
    print(weighthdf5 + " loaded.")
else:
    print(weight_hdf5 + " not found.")

model.fit(xtrain, ytrain,
          epochs=epochs,
          initialepoch=initialepoch,
          batchsize=batchsize,
          validationdata=(xtest, y_test),
          callbacks=[cb, tsb])

classes = model.predict(xtest, batchsize=batch_size)

score = model.evaluate(xtest, ytest, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

5.結果

10エポックだけやってみた。ちゃんと学習できていそう。

weights.0000.hdf5 not found.
Train on 60000 samples, validate on 10000 samples
Epoch 1/10
60000/60000 [==============================] - 2s 35us/step - loss: 0.4187 - acc: 0.8800 - valloss: 0.2162 - valacc: 0.9380

Epoch 00001: valloss improved from inf to 0.21623, saving model to weights.0001.hdf5
Epoch 2/10
60000/60000 [==============================] - ETA: 0s - loss: 0.1933 - acc: 0.944 - 2s 35us/step - loss: 0.1931 - acc: 0.9440 - valloss: 0.1542 - val_acc: 0.9546

Epoch 00002: valloss improved from 0.21623 to 0.15421, saving model to weights.0002.hdf5
Epoch 3/10
60000/60000 [==============================] - 2s 33us/step - loss: 0.1426 - acc: 0.9578 - valloss: 0.1216 - val_acc: 0.9628

Epoch 00003: valloss improved from 0.15421 to 0.12159, saving model to weights.0003.hdf5
Epoch 4/10
60000/60000 [==============================] - 2s 26us/step - loss: 0.1128 - acc: 0.9667 - valloss: 0.1126 - val_acc: 0.9657

Epoch 00004: valloss improved from 0.12159 to 0.11258, saving model to weights.0004.hdf5
Epoch 5/10
60000/60000 [==============================] - ETA: 0s - loss: 0.0939 - acc: 0.972 - 2s 30us/step - loss: 0.0938 - acc: 0.9725 - valloss: 0.0992 - val_acc: 0.9697

Epoch 00005: valloss improved from 0.11258 to 0.09921, saving model to weights.0005.hdf5
Epoch 6/10
60000/60000 [==============================] - 2s 34us/step - loss: 0.0794 - acc: 0.9771 - valloss: 0.0882 - val_acc: 0.9737

Epoch 00006: valloss improved from 0.09921 to 0.08821, saving model to weights.0006.hdf5
Epoch 7/10
60000/60000 [==============================] - 2s 33us/step - loss: 0.0684 - acc: 0.9799 - valloss: 0.0880 - val_acc: 0.9726

Epoch 00007: valloss improved from 0.08821 to 0.08802, saving model to weights.0007.hdf5
Epoch 8/10
60000/60000 [==============================] - 2s 31us/step - loss: 0.0595 - acc: 0.9827 - valloss: 0.0803 - val_acc: 0.9741

Epoch 00008: valloss improved from 0.08802 to 0.08034, saving model to weights.0008.hdf5
Epoch 9/10
60000/60000 [==============================] - 2s 33us/step - loss: 0.0530 - acc: 0.9844 - valloss: 0.0779 - val_acc: 0.9751

Epoch 00009: valloss improved from 0.08034 to 0.07787, saving model to weights.0009.hdf5
Epoch 10/10
60000/60000 [==============================] - 2s 30us/step - loss: 0.0461 - acc: 0.9867 - valloss: 0.0826 - val_acc: 0.9749

Epoch 00010: val_loss did not improve from 0.07787
Test loss: 0.08257695595924743
Test accuracy: 0.9749

まとめ

kerasで、MNISTのサンプルを実装し、動かしてみた。

  • 自身のディレクトリ
cd /d %~dp0

概要

AWSのGreengrassを使い、遠隔でGPIOを操作しLEDの点滅ができた。


背景と目的

先日のGreengrass使い始めに続き、ドキュメントに沿っていろいろ試したところ、遠隔でエッジのLambda関数をトリガする方法もわかった。また、エッジのローカルリソース(ドライブや、シリアルポート、GPIOなど)にもアクセスできるとの記述がある。そこで、Raspberry PiのGPIOを遠隔で操作してみることにした。


詳細

0.参考資料

AWSドキュメント内の以下URLを参考にした。GPIOにアクセスできるとの旨が書いてある。

https://docs.aws.amazon.com/ja_jp/greengrass/latest/developerguide/access-local-resources.html


1.Lambda関数

Lambda関数は、基本的にRaspberry Pi上でGPIOをいじるときと同じコード。

# coding:utf-8
import sys
import greengrasssdk
import RPi.GPIO as GPIO
import time
import platform
import os
import logging

# Create a Greengrass Core SDK client.
client = greengrasssdk.client('iot-data')

# GPIOの設定
GPIO_NUM = 4
GPIO.cleanup()
GPIO.setmode(GPIO.BCM)
GPIO.setup(GPIO_NUM, GPIO.OUT)

def function_handler(event, context):
    try:
        client.publish(topic='LRA/test', payload="Sent from AWS Greengrass Core.")
        GPIO.output(GPIO_NUM, GPIO.HIGH)
        time.sleep(1)
        GPIO.output(GPIO_NUM, GPIO.LOW)
        time.sleep(1)
    except Exception as e:
        logging.error("Experiencing error :{}".format(e))
        client.publish(topic='LRA/test', payload="Experiencing error")
    return


2.リソースの設定

Greengrass>グループ>リソースで、/dev/gpionumというリソースに対して、Lambda関数がアクセスできるように設定した。

リソース


3.サブスクリプションの設定

以下2つを設定した。IoT Cloud側からLRA/test/triggerトピックに、送信することで、Lambdaが呼び出せる。

  • "LRA/test/trigger"トピックをIoT Cloud ⇒ Lambda関数で設定
  • "LRA/test"トピックをLambda関数 ⇒ IoTCloudで設定


4.テスト

以上の設定で、Greengrass CoreにLambdaをデプロイし、IoT Cloud側からLRA/test/triggerトピックにメッセージを送信した。ところ、GPIO4に接続したLEDが1秒間光り、"LRA/test"トピックに、Lambdaからのメッセージが来た。正しく、Lambdaが呼び出せている。


まとめ

AWSのGreengrassを使い、遠隔でGPIOを操作しLEDの点滅ができた。

概要

AWSのGreengrassを使ってエッジにLambdaをデプロイし、実行させてみた。


背景と目的

AWSのGreengrassを使ってみようと思っていながらしばらく時間がなくトライしていなかった。少し時間ができたので使ってみる。


詳細

0.参考

https://aws.amazon.com/jp/greengrass/features/

https://aws.amazon.com/jp/greengrass/faqs/

https://docs.aws.amazon.com/ja_jp/greengrass/latest/developerguide/what-is-gg.html

基本的なやり方は、上記のURLを参考に進めた。


1.Raspberry Piの設定

https://docs.aws.amazon.com/ja_jp/greengrass/latest/developerguide/module1.html

上記URLにある手順に従って実施したのだが、私の環境の場合、Memory cgroupという項目でDisabledが出た。そこで、

https://www.raspberrypi.org/forums/viewtopic.php?t=203128

に従って、/boot/cmdline.txtに以下を追記して再起動。

cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1


2.Greengrass Core SDKのインストール

https://docs.aws.amazon.com/ja_jp/greengrass/latest/developerguide/module2.html

上記URLに従って、作業を実施。

ただし、以下を追加で実施した。なぜかというと、はじめgreengrassdの起動がうまくいかず、トラブルシューティングを見ながら、権限の問題がありそうだったから。(ただし、これは本当に要るのか?はわからない。)

sudo chmod 755 /greengrass -R


3.Lambdaのデプロイ

https://docs.aws.amazon.com/ja_jp/greengrass/latest/developerguide/module3-I.html

次に、Lambda関数をデバイスにデプロイした。作業手順は上記URLに従っている。

コンソールのGreengrass groupで、正常に完了しましたという表示になればOK.


4.テスト

AWS IoTのコンソールで、テスト。

hello/worldトピックをサブスクライブした結果、定期的にエッジで実行されたLambda関数から、MQTTメッセージがパブリッシュされている。


b8b280c8

まとめ

AWSのGreengrassを使ってエッジにLambdaをデプロイし、実行させた。

概要

Pythonで.vntファイルの変換をした。


背景と目的

家族が機種変更のため、旧機種のandroidスマホのメモアプリからメモをエクスポートしたところ、vntというファイルでエクスポートされ、新機種側で読めなかった。変換アプリ等を探したところうまく見つけられたなかったので、PC上で無理やり変換する。


詳細

1.方法の検討

.vntファイルは、ちゃんと仕様があるだろうが、"="の後ろの数値がある文字コードに対応した16進文字列

=80=33blog...

(blogはasciiにあるのでそのまま)という感じなので、これを変換すればよさそうだ。


2.スクリプト作成

Pythonで出来そうなのでいろいろ調べた結果、

"="の後ろの2文字を16進文字列からバイナリに変換

していけばいけそうなので、

import binascii

x = binascii.unhexlify('16進文字列')

という感じの処理をすればよいことがわかった。


3.結果

というわけで、.vntファイルを読みこみ、"="の後ろ2文字にbinascii.unhexlifyをに適用してバイナリに変換し、それをすべて連結させてファイルに書き出したところ、無事変換ができた。

※出力ファイルの文字コードは適宜変換すること。今回、私の場合は.vntのヘッダらしき部分にShift-JISとの記述があったので、バイナリに変換後、shift-jisと解釈して扱ったところうまくいった。


まとめ

.vntファイルの変換をPythonでできた。雑多な処理テクニックがまた1つ増えた。もう使うことなさそうだけど。

概要

ニューラルネットワークライブラリKerasを導入して動く環境を整えた。


背景と目的

ニューラルネットワークのプログラミングを素早く行える環境を整えたくなったので、やってみる。


詳細

0.準備

ニューラルネットワークのプログラミングを素早く行える環境としては、いろいろあるようだが今回はKerasを使うことにした。PCは以下。

  • Lenovo Idea Pad Yoga 13
  • Windows10


1.各種インストール

1.1 Anacondaのインストール

まず、https://www.anaconda.com/download/から、64ビット版、バージョン3.6をダウンロードしてインストールした。裸のPython環境に入れてもいいが、Web上で紹介されていることが多いのがAnacondaなのでそれに従った。

また、これに伴いpipが古いだの、msgpackがないと言われたのでAnaconda Promptを立ち上げて、以下のコマンドを実行してアップデート。

python -m pip install --upgrade pip
pip install msgpack


1.2 Tensorflowのインストール

Kerasでは、Tensorflowをテンソル計算ライブラリに使用しているため、Anaconda Promptで以下を実行し、インストール。

pip install tensorflow


1.3 Kerasのインストール

いよいよKeras。

pip install keras


2.autoencoderのプログラムを動かす

とりあえず、MNISTの学習と判別をしてみるということで、こちらそのままをコーディングし、実行した。

そのままなので、コードは省略。


3.結果

実行結果は以下。所要時間は5分くらいだろうか。とりあえず、環境は整った。

Epoch 50/50
60000/60000 [==============================] - 5s 88us/step - loss: 0.1059 - val_loss: 0.1041

10個だけ、入力と出力の比較をしてみる。上が入力、下が出力。

20180822231358


まとめ

Kerasを導入して動く環境を整えられた。ちょっとずつプログラミングに慣れようと思う。

概要

フリーソフトなどを使用し、ある領域をまたいで存在していた2つのドライブを1つに統合するパーティション変更を行った。


背景と目的

私の手持ちのPCでは、SSDのパーティションが約100GBのCドライブと、4GBのDドライブに分かれているのだが、別れている意味がほとんどないので、パーティションを変更し、連続した1領域にする。


詳細

0.情報収集

私のPCの場合、以下の図のようにCとDの間にOEMパーティションなるものがあるので、これをどうにかする必要がある。2つの隣接する領域であれば、Windows付属のディスクの管理ツールから作業が可能なのだが、いろいろ調べた結果、こちらなるフリーソフトを使って作業可能なようなのでやってみる。

20180817140223

1.AOMEI Partition Assistantのインストール

AOMEI Partition Assistantをダウンロードし、インストールした。


2.Dドライブの割り当て削除

ディスクの管理ツールで、Dドライブを選択し、ボリュームの削除を行った。なお、当該領域のデータはすべて失われるとのことだったので、必要なものはバックアップを実施しておいた。


3.OEMパーティションの移動

この作業は、AOMEI Partition Assistantを使う。OEMパーティションを選択し、ボリュームの移動を選択すると、以下のような画面が出るので、一番右側に寄せ、Cドライブのすぐ右隣に未割当領域ができるようにした。

20180817140657


4.Cドライブの拡張

ディスクの管理ツールで、Cドライブを選択し、ボリュームの拡張を行った。設定は以下に示す通り、先ほどCの右隣に確保した未割当領域すべてを使う。

20180817141023

この結果、以下のようにCドライブの容量がおよそ4GB増加した。無事完了。

20180817141100


まとめ

無事パーティション変更ができてよかった。

概要

Pythonのloggingモジュールを使った際のメモ。

背景と目的

Pythonのloggingモジュールを使った際のメモ。


詳細

1.基本

import logging
# ルートオブジェクトを取得
logger = logging.getLogger()
# 名前を指定してロガーオブジェクトを取得
logger = logging.getLogger("名前")

2.モジュール間で参照

まず、参照される側のモジュール(test.pyとする)では、__name__としてオブジェクトを作成してしておく。

import logging

# __name__としてオブジェクトを作成して
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG) # レベル設定を忘れない(呼び出し側でやってもいいけどとにかく忘れないこと)

def hoge():
    logger.debug("hogehoge")

次に、呼び出し側のスクリプトで、testをインポートし、"test"という名前のロガーを取得

import logging
import test # 参照モジュール

# testモジュールのオブジェクトを取得
testLogger = logging.getLogger("test")
logger = logging.getLogger(__name__)

def hoge2():
    logger.debug("hoge2hoge2")

if __name__ == "__main__":

    test.hoge()
    
    hoge2()

こうすれば、以下のような出力になる。

hogehoge
hoge2hoge2


3.コンソールとファイルに同時に出力、フォーマット、レベル設定など


# フォーマット
format_string = "%(asctime)s %(levelname)s %(message)s"
formatter = logging.Formatter(format_string)

# コンソール
hConsole = logging.StreamHandler()
hConsole.setFormatter(formatter)
hConsole.setLevel(logging.DEBUG)
logger.addHandler(hConsole)

# ファイル
hFile = logging.FileHandler(ファイルパス)
hFile.setFormatter(formatter)
hFile.setLevel(logging.DEBUG)
logger.addHandler(hFile)


まとめ

ざっくりこんな感じ。

概要

湿温度計DHT22をESP-WROOM-32に接続して、温度と湿度を取得できた。


背景と目的

とある事情で、家の中の温度と湿度を測ってデータを蓄積する必要が出た。そのため、手持ちのESP-WROOM-32に湿温度センサを接続し、動作させる。


詳細

1.使用するデバイス

  • ESP-WROOM-32 DevKitC基板
  • DHT22

DHT22を選択したのは、Amazonで検索したら最初のほうに出てきたのと、ネット上に参考情報がたくさんあったため。(ちなみに、以前DHT11を持っていたのだが、電源逆接続という初歩的なミスで壊してしまったので、どうせならそれより精度の良いものを買ってしまえということで、買ったという経緯もある。)


2.接続方法

DHT22は、動作電圧範囲が最低3.3Vで、ESP-WROOM-32のGPIOレベル(だいたい3.3Vより低くなる)で確実に動作するのかよくわからないので、3.3V/5Vのレベルシフタをかませることにした。ただ、DHT22は独自の単線インターフェースなので、双方向レベルシフタが必要で、いろいろ考えた挙句、以下のような回路になった。(実は、最低動作電圧を多少下回っても動くのかな?やってないのでわからないが)

20180711184326

3.ソフトウェア

3.1 ライブラリのインストール

基本的に、arduino-esp32を使うが、DHT22は、Arduinoライブラリが存在しており、Arduino IDE>スケッチ>ライブラリをインクルード>ライブラリを管理から、インストールできた。

20180710210408

3.2 コーディング

都合もあり詳細は割愛するが、基本的には、以下の簡単なコードで取得できた。

// インクルード
#include "DHTesp.h"

// DHTespクラスインスタンスを作成
DHTesp dht;

// 初期化
dht.setup(GPIOピン番号, DHTesp::DHT22);

// 計測
TempAndHumidity newValues = dht.getTempAndHumidity();

// 結果表示
Serial.println(" T:" + String(newValues.temperature) + " H:" + String(newValues.humidity));

4.動作確認

以下が、動作確認した様子。暑くて30度を越えているが、手持ちの別の温度計もほぼ同じような値であり、湿度も自分の住んでいるエリアのリアルタイム湿度と比較してほぼ同じだったので、正しく動作しているようだ。

 T:30.90 H:54.90


まとめ

DHT22をESP-WROOM-32に接続して、動作させることができた。次は、Web上に蓄積する。

このページのトップヘ