TeratermでDvorak配列
はじめに
TeratermはWindows用SSHクライアントとして有名なソフトウェアです。
本記事ではTeraterm上でDvorak配列を実現する設定方法を紹介します。
Teratermにはキーボードショートカット編集機能があります。
設定ファイルを記述するこで、キーボードの機能を自由にカスタマイズが可能です。
https://ttssh2.osdn.jp/manual/ja/setup/keyboard.html
今回は上記のページを参考にQwerty配列Dvorak配列にkeymapする設定を書きました。
開発環境が、レジストリ変更権限がなくDvorakJのインストールができないWindows、かつSSH先がsudo権限のないLinux、である場合に有効です(涙)。需要あるかな?
しかし、keymapできる数は99個だったり、装飾キーとの組み合わせも一つのkeymapとして設定する必要があったりするため限界があります。
KEYBOARD.CNF
下記を既存のKEYBORD.CNFに追記してご利用ください。
[User keys] User1 = 16,0,$27 ; q to ' User2 = 17,0,$2c ; w to , User3 = 18,0,$2e ; e to . User4 = 19,0,$70 ; r to p User5 = 20,0,$79 ; t to y User6 = 21,0,$66 ; y to f User7 = 22,0,$67 ; u to g User8 = 23,0,$63 ; i to c User9 = 24,0,$72 ; o to r User10 = 25,0,$6C ; p to l User11 = 26,0,$2F ; @ to / User12 = 27,0,$3D ; [ to = User13 = 31,0,$6F ; s to o User14 = 32,0,$65 ; d to e User15 = 33,0,$75 ; f to u User16 = 34,0,$69 ; g to i User17 = 35,0,$64 ; h to d User18 = 36,0,$68 ; j to h User19 = 37,0,$74 ; k to t User20 = 38,0,$6E ; l to n User21 = 39,0,$73 ; ; to s User22 = 40,0,$2D ; : to - User23 = 43,0,$5C ; ] to \ User24 = 44,0,$3B ; z to ; User25 = 45,0,$71 ; x to q User26 = 46,0,$6A ; c to j User27 = 47,0,$6B ; v to k User28 = 48,0,$78 ; b to x User29 = 49,0,$62 ; n to b User30 = 51,0,$77 ; , to w User31 = 52,0,$76 ; . to v User32 = 53,0,$7A ; / to z User33 = 515,0,$40 ; " to @ User34 = 517,0,$5E ; & to ^ User35 = 520,0,$26 ; ' to & User36 = 521,0,$2A ; ( to * User37 = 522,0,$28 ; ) to ( User38 = 523,0,$29 ; to ) User39 = 524,0,$7D ; = to { User40 = 525,0,$7B ; ~ to } User41 = 125,0,$60 ; to ` User42 = 553,0,$7E ; to ~ User43 = 528,0,$22 ; Q to " User44 = 529,0,$3C ; W to < User45 = 530,0,$3E ; E to > User46 = 531,0,$50 ; R to P User47 = 532,0,$59 ; T to Y User48 = 533,0,$46 ; Y to F User49 = 534,0,$47 ; U to G User50 = 535,0,$43 ; I to C User51 = 536,0,$52 ; O to R User52 = 537,0,$4C ; P to L User53 = 538,0,$3F ; ` to ? User54 = 539,0,$2B ; { to + User55 = 543,0,$4F ; S to O User56 = 544,0,$45 ; D to E User57 = 545,0,$55 ; F to U User58 = 546,0,$49 ; G to I User59 = 547,0,$44 ; H to D User60 = 548,0,$48 ; J to H User61 = 549,0,$54 ; K to T User62 = 550,0,$4E ; L to N User63 = 551,0,$53 ; + to S User64 = 552,0,$5F ; * to _ User65 = 555,0,$7C ; } to | User66 = 556,0,$3A ; Z to : User67 = 557,0,$51 ; X to Q User68 = 558,0,$4A ; C to J User69 = 559,0,$4B ; V to K User70 = 560,0,$58 ; B to X User71 = 561,0,$42 ; N to B User72 = 563,0,$57 ; < to W User73 = 564,0,$56 ; > to V User74 = 565,0,$5A ; ? to Z User75 = 1043,0,$10 ; C-r to C-p User76 = 1044,0,$19 ; C-t to C-y User77 = 1045,0,$06 ; C-y to C-f User78 = 1046,0,$07 ; C-u to C-g User79 = 1047,0,$03 ; C-i to C-c User80 = 1048,0,$12 ; C-o to C-r User81 = 1049,0,$0C ; C-p to C-l User82 = 1055,0,$0F ; C-s to C-o User83 = 1056,0,$05 ; C-d to C-e User84 = 1057,0,$15 ; c-f to c-u User85 = 1058,0,$09 ; c-g to c-i User86 = 1059,0,$04 ; c-h to c-d User87 = 1060,0,$08 ; c-j to c-h User88 = 1061,0,$14 ; c-k to c-t User89 = 1062,0,$0E ; c-l to c-n User90 = 1063,0,$13 ; c-; to c-s User91 = 1069,0,$11 ; c-x to c-q User92 = 1070,0,$0A ; C-c to C-j User93 = 1071,0,$OB ; c-v to c-k User94 = 1072,0,$18 ; c-b to c-x User95 = 1073,0,$02 ; c-n to c-b User96 = 1075,0,$17 ; c-, to c-w User97 = 1076,0,$16 ; c-. to C-v User98 = 1077,0,$1A ; c-/ to c-z
あとがき
やはり自作キーボードが最適解ですかね。
Thinkpad X1 carbonとXFCEで4Kディスプレイを利用する
4Kディスプレイを買いました。
持っているもの
買ったもの
- https://www.amazon.co.jp/gp/product/B07LC3L6JG
DELLかLGかで迷ったのですが、足がしっかりしているのでDELLにしました。また、ドット欠けの保証があったのも選定理由です。 - https://www.amazon.co.jp/gp/product/B0778D9MZ3
Mini DisplayPort to Thunderbolt3ケーブルです。60Hzで出力するために購入しました。HDMIでの接続では30Hzでの出力になってしまい60Hzで出力できませんでした。30Hzだとyoutubeの動画がカクついて見えるのでかなり厳しかったです。また、本ケーブルで接続することで、XFCEが自動で4Kを検出してくれて大変便利です。HDMIで接続した場合は、WQHDで出力されてしまうため、手動でから4Kへ変更する必要がありました。
Hidpi
XFCEの設定でDPIをポチポチすれば4Kでも快適に利用可能なサイズを設定できます。ちなみに私は160に設定しております。自分の場合はもともとWQHDのthinkpadなので普段使いのために設定していましたが、今回の4K出力にあたってはそのままの設定で問題ありませんでした。
詳しくはArchWikiを参照しましょう。
https://wiki.archlinux.jp/index.php/HiDPI
感想
Chromeでのブラウジング、emacsやPycharmでのコーディング等を行っておりますが、今の所問題なく快適に使えております。thunderboltケーブルをぶっ刺すだけで出力されます。新年度に向けてぜひ!
TensorflowLiteでAndroidでCNN
この記事はAizu Adc 2018 20日目にかかれた4日目の記事です。
前の人は@xatu0202氏, 次の人@ywkw氏です。
こんにちは。@masapontoです。最近は東京でデータ分析太郎として暮らしております。
気がづくと本ブログはアドベントカレンダーでしか書かなくなってしまいました。 今回はTensorflow Lite を使って Android上で画像分類(CNN)をする話をしようと思います。
TonsorFlow Liteを紹介する多くの日本語記事は、サンプルとして用意されている学習済みモデルを動かしてみたっていう話が多い気がします(主観)。
それに対し本記事では、自身で定義して学習を行ったCNNを動かしてみようと思います。
データはCIFAR10っていう画像データセットを使います。
CIFAR10はairplane, automobile, bird, cat, deer, dog, frog, horse, ship, truckの10クラスの画像データセットです。
https://www.cs.toronto.edu/~kriz/cifar.html
※本記事の内容は、単に動かしてみたよって感じの記事なので、詳細な説明を求める方にはおすすめできません。 まぁ何いっても公式ドキュメントを読めばいい話です(完)。 https://www.tensorflow.org/lite/devguide
Tensorflow Liteとは
モバイル端末や組み込み端末で機械学習の推論をするぞいっていうライブラリです。
https://www.tensorflow.org/lite/
基本的な使い方としては、以下の3ステップです。
- PC上のTensorFlowでNNを学習させてモデルMを作る。 (on Python)
- MをAndroid向けに変換し、 M'を作る。 (on Python)
- M'をAndroidアプリのassets/フォルダとかにいれて、呼び出す。 (on Android)
手順 on Python
私の開発環境は、ArchLinux (x64) / Python 3.6.1/ tensorflow 0.12.0 です。
で、下記のようにCNNを学習させるコードを書きます。 いつのまにかTensorFlowにKerasインターフェースが入っていたので、それを使って書いてみました。
# !/usr/bin/env python import tensorflow as tf def convolutional(): model = tf.keras.models.Sequential([ tf.keras.layers.Conv2D(filters=32, kernel_size=[5, 5], padding='same', activation='relu', input_shape=(32, 32, 3), name='input'), tf.keras.layers.MaxPooling2D(pool_size=[2, 2], strides=2), tf.keras.layers.Conv2D(filters=32, kernel_size=[5, 5], padding='same', activation='relu'), tf.keras.layers.MaxPooling2D(pool_size=[2, 2], strides=2), tf.keras.layers.Flatten(), tf.keras.layers.Dense(units=1024, activation='relu'), tf.keras.layers.Dropout(rate=0.4, trainable=True), tf.keras.layers.Dense(units=10, activation='softmax', name='output') ]) return model def main(): (X_train, Y_train), (X_test, Y_test) = tf.keras.datasets.cifar10.load_data() X_train = X_train/255 X_test = X_test/255 print(X_train.shape) Y_train = tf.keras.utils.to_categorical(Y_train, 10) Y_test = tf.keras.utils.to_categorical(Y_test, 10) model = convolutional() model.compile(optimizer=tf.keras.optimizers.Adam(0.0001), loss='categorical_crossentropy', metrics=['accuracy']) model.fit(X_train, Y_train, epochs=100, batch_size=50, verbose=1) # モデルの図示 (任意) tf.keras.utils.plot_model(model, to_file='model.png', show_shapes=True) # モデルをh5で保存 keras_file = "model_keras/cnn_model.h5" model.save(keras_file) # TFLiteでコンバータを用意 converter = tf.contrib.lite.TFLiteConverter.from_keras_model_file(keras_file, input_arrays=['input_input'], output_arrays=['output/Softmax'], input_shapes={'input_input': [None, 32, 32, 3]}) # コンバート tflite_model = converter.convert() open("model_keras/converted_model.tflite", "wb").write(tflite_model) if __name__ == '__main__': main()
ドキュメントにあまり詳しくない部分があって、ググって試行錯誤してなんとか動きました。
converter
を作るときに、input_arrays
とかoutput_arrays
で名前を指定する必要があるっぽいです。
あと入力層のinput_shapesも指定する必要があるみたいです。(このへんよくわかってないので教えてください)
手順 on Android
Kotlinコードを下記においておきます。
動作確認環境はAndroidStudio20172.3/Kotlin 1.2.71/Zenfone 5/Android 8.0.0です。
準備 (TensorFlowLite)
下記を追記 (src: https://codelabs.developers.google.com/codelabs/tensorflow-for-poets-2-tflite/#6)
- app/build.gradle
android { // Add aaptOptions { noCompress "tflite" } } dependencies { // Add implementation 'org.tensorflow:tensorflow-lite:1.12.0' }
また、作成したモデル(.tfliteファイル)は、AppName/app/src/main/assets/
に入れます。
コード
下記のようなコードを書いて、MainActivityから呼びます。 classifyImageFromPath(file) でファイルパスを指定してやって分類する感じです。
package io.github.masaponto.tflitecifarten import android.app.Activity import android.graphics.Bitmap import org.tensorflow.lite.Interpreter import java.io.FileInputStream import java.io.IOException import java.nio.ByteBuffer import java.nio.MappedByteBuffer import java.nio.channels.FileChannel import android.graphics.BitmapFactory import java.io.File import java.nio.ByteOrder class Classifier(activity: Activity) { private val MODEL_NAME = "converted_model.tflite" private val IMAGE_SIZE = 32 private val IMAGE_MEAN = 128 private val IMAGE_STD = 128.0f private var tffile: Interpreter private var labelProbArray: Array<FloatArray> init { tffile = Interpreter(loadModelFile(activity)) // deprecated labelProbArray = Array(1){FloatArray(10)} } @Throws(IOException::class) private fun loadModelFile(activity: Activity): MappedByteBuffer { val fileDescriptor = activity.assets.openFd(MODEL_NAME) val inputStream = FileInputStream(fileDescriptor.fileDescriptor) val fileChannel = inputStream.channel val startOffset = fileDescriptor.startOffset val declaredLength = fileDescriptor.declaredLength return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength) } fun classifyImageFromPath(path: String): Int { val file = File(path) if (!file.exists()) { throw Exception("Fail to load image") } // load image val bitmap = BitmapFactory.decodeFile(file.path) val scaledBitmap = Bitmap.createScaledBitmap(bitmap, IMAGE_SIZE, IMAGE_SIZE,true) // convert bitmap to bytebuffer val byteBuffer = convertBitmapToByteBuffer(scaledBitmap) // classification with TF Lite val pred = classifyImage(byteBuffer) return onehotToLabel(pred[0]) } private fun convertBitmapToByteBuffer(bitmap: Bitmap): ByteBuffer { val byteBuffer = ByteBuffer.allocateDirect( IMAGE_SIZE * IMAGE_SIZE * 3 * 4) byteBuffer.order(ByteOrder.nativeOrder()) val intValues = IntArray(IMAGE_SIZE * IMAGE_SIZE) bitmap.getPixels(intValues, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height) var pixel = 0 for (i in 0 until IMAGE_SIZE) { for (j in 0 until IMAGE_SIZE) { val v = intValues[pixel++] byteBuffer.putFloat((((v.shr(16) and 0xFF) - IMAGE_MEAN) / IMAGE_STD)) byteBuffer.putFloat((((v.shr(8) and 0xFF) - IMAGE_MEAN) / IMAGE_STD)) byteBuffer.putFloat((((v and 0xFF) - IMAGE_MEAN) / IMAGE_STD)) } } return byteBuffer } fun classifyImage(bytebuffer: ByteBuffer): Array<FloatArray> { tffile.run(bytebuffer, labelProbArray) return labelProbArray } private fun onehotToLabel(floatArray: FloatArray): Int { val tmp = floatArray.indices.maxBy { floatArray[it] } ?: -1 return tmp + 1 } }
全体のリポジトリ
convertBitmapToByteBuffer
もよくわかってないです。(つらい..)
動かす
適当に拾った猫ちゃん画像を分類してみましょう。
クラスラベルは1:airplane, 2:automobile, 3:bird, 4:cat, 5:deer, 6:dog, 7:frog, 8:horse, 9:ship, 10:truckの順ぽいのでたぶん動いてますね(雑)。
まとめ。
Kerasインターフェースを使って簡単にCNNの学習コードかいて、携帯端末用に変換する事ができました。 ちなみに、tfliteに変換するときにNoneでなくintegerで指定すればバッチサイズを変更指定できます。 Android端末で機械学習ができるので、わりと作れるアプリの幅が広がった気がします。 こんな調子でお仕事がんばるぞい。