TD4(4bit CPU)を作った
夏休みに、電子工作の界隈ではメジャーであるTD4を作ってみた。
3日くらいで終わるかなと思ったら、5日かかってしまった。 (合間合間にネトフリ見てたせい)
初心者だから配線汚いのは目つぶってね。
回路はこの本の巻末にある回路図をほぼそのまま使用。
1日目
お金ケチって電源アース付きのユニバ基板にしなかったのでめんどい。
2日目
配線きたねえ...
ひたすら配線
3日目
地獄...
4日目
クロックとリセット回路載せるスペースなかったので、急遽別基板で作って、ジャンプワイヤーで接続した。
とりあえず完成...
だがクロックが動かない...疲れたから明日直そう...
5日目(完成)
クロック回路の33kΩと3.3kΩに両方確認用LEDつけていたが、33kΩにつけたLEDを取り除いたら正常動作した。LEDの方に電流がながれてしまい、クロックの回路に電流が流れなくなったのかな?
本当は原因突き止めるべきなんだろうけど、配線作業で気力を使いつくしてしまいやらなかった...よくない。
動いている様子
4bitCPUやっと出来た pic.twitter.com/8htKyedKso
— toson (@westrohifi) September 9, 2019
補足
ROM作る気力なんて残ってなかったので、arduinoを使いました。
先人様ありがたい。
すごく当たり前だけど、参照先のサイトのコードのアセンブリ、レジスタ転送だけなので、レジスタにLED直結してないと動作確認できないから注意。
ICはすべてaitendoで入手できました。(2019/09)
CNNを利用した画像判定器の作成
今流行りのディープラーニングを使って画像判定器を作ってみた。GW丸々潰した...
スクレイピングで画像を集める
bingAPIとFlickrAPIを用いた。
bingAPI事前準備 qiita.com 上記のコードは動かなかったので、 この記事のコードを使ったら動いた。 qiita.com
FlickrAPIはこの記事をコピペ。
(本当は、googleから画像を取得できればいいんだけど、googleAPIの仕様なのか1回走らせると10枚程度しか集められないらしい。)
データセット準備
#ライブラリ from PIL import Image,ImageFilter import os,glob import numpy as np from sklearn import model_selection #リスト作成、数取得、画像ピクセル定義 classes=["miku","rem","chino"] num_classes=len(classes) image_size=50 #検証用データ数定義 num_testdata=15 #画像読み込み X_train=[] X_test=[] Y_train=[] Y_test=[] #リスト取り出し、番号を振ってfor文に渡す for index,classlabel in enumerate(classes): #写真のディレクトリ photos_dir="./"+classlabel #パターン一致でファイル一覧を取得 files=glob.glob(photos_dir + "/*.jpg") #番号を振って順番に画像取り出す for i, file in enumerate(files): #RGB変換リサイズnumpy変換 if i>= 147: break image = Image.open(file) image = image.convert("RGB") image = image.resize((image_size, image_size)) data = np.asarray(image) #検証用データ確保 if i<num_testdata: X_test.append(data) Y_test.append(index) #画像増幅 else: for angle in range(-20,20,5): #回転して追加 img_r =image.rotate(angle) data=np.asarray(img_r) X_train.append(data) Y_train.append(index) #反転して追加 img_trans=img_r.transpose(Image.FLIP_LEFT_RIGHT) data=np.asarray(img_trans) X_train.append(data) Y_train.append(index) #フィルター加工して追加 img_resample=img_trans.rotate(0,expand=True,resample=Image.BICUBIC) data=np.asarray(img_resample) X_train.append(data) Y_train.append(index) #エッジ強化して追加 img_shr=img_trans.filter(ImageFilter.EDGE_ENHANCE) data=np.asarray(img_shr) X_train.append(data) Y_train.append(index) #numpy変換 X_train=np.array(X_train) X_test=np.array(X_test) y_train=np.array(Y_train) y_test=np.array(Y_test) #xyに格納 xy = (X_train, X_test, y_train, y_test) #保存 np.save("./anime_data.npy",xy)
例えば初音ミク、レム、チノちゃん、という青髪キャラ判定器を作りたいなら、
スクレイピングした画像が入っているファイルの名前を、それぞれmiku、rem、chinoと指定。
カレントディレクトリ上にデータセット(anime_data.npy)が出力される。
画像の水増しをしているため、元のデータの 9 (回転) ×2 (反転) ×2 (フィルター加工)×2 (エッジ強化)= 72倍になっているはず。
(水増しをやりすぎると過学習の原因になるため、十分な量の画像を確保できる場合やらなくてもいい。)
CNNによる深層学習
#ライブラリ from keras.models import Sequential from keras.layers import Conv2D,MaxPooling2D from keras.layers import Activation,Dense,Dropout,Flatten from keras.utils import np_utils import keras import numpy as np #リスト作成、数取得、画像を50pxと定義 classes=["miku","rem","chino"] num_classes=len(classes) image_size=50 #メイン関数定義 def main(): #ファイルからテータを配列に読み込む(Xが画像、Yがラベル) X_train,X_test,y_train,y_test=np.load("./anime_data.npy") #正規化(0から1の範囲に収める) X_train=X_train.astype("float")/256 X_test=X_test.astype("float")/256 #正解に1、他0を入れる行列に変換(one-hot-vetcor) y_train =np_utils.to_categorical(y_train,num_classes) y_test=np_utils.to_categorical(y_test,num_classes) #モデル作成関数呼び出し model =model_train(X_train,y_train) #モデル評価関数呼び出し model_eval(model,X_test,y_test) #CNN定義 def model_train(X,y): #連続なモデルであると定義。 model = Sequential() #畳み込み演算。32が出力の次元。3*3のフィルタを用いる。畳み込み結果が同じサイズになるようにする。 model.add(Conv2D(32,(3,3),padding='same',input_shape=X.shape[1:])) #活性化関数(ランプ関数)正の値は通し、負は0 model.add(Activation('relu')) model.add(Conv2D(32,(3,3))) model.add(Activation('relu')) #一番大きい値を取り出す model.add(MaxPooling2D(pool_size=(2,2))) #データ35%捨てる(過学習防止) model.add(Dropout(0.35)) model.add(Conv2D(64,(3,3),padding='same')) model.add(Activation('relu')) model.add(Conv2D(64,(3,3))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Dropout(0.35)) #Flatten処理(データを1列に並べる) model.add(Flatten()) #全結合型ニューラルネットワーク model.add(Dense(512)) model.add(Activation('relu')) model.add(Dropout(0.5)) model.add(Dense(3)) #softmax関数(負の値を正の値に変換して確率に変換) model.add(Activation('softmax')) #最適化アルゴリズム(1回回すごとに学習率を下げていくらしい) opt=keras.optimizers.rmsprop(lr=0.0001,decay=1e-6) #損失関数(正解と推定値の誤差)定義、最適化アルゴリズム定義、評価の値を正答率で定義 model.compile(loss='categorical_crossentropy',optimizer=opt,metrics=['accuracy']) #学習分割数、学習回数定義 model.fit(X,y, batch_size=128,nb_epoch=40) #学習データ保存 model.save('./anime_cnn.h5') return model #評価関数定義 def model_eval(model,X, y): #結果受け取り scores=model.evaluate(X,y,verbose=1) #損失量表示 print('Test Loss:',scores[0]) #精度表示 print('Test Accuracy:', scores[1]) #ほかのプログラムから参照する際、このプログラムが呼ばれたときのみmainを実行 if __name__ =="__main__": main()
Keras公式サイトを参考にして色々パラメーター弄ると精度上がったり下がったりする。
知識ない場合公式サイトに載ってる例の通りでいいかも。
CIFAR-10 CNN - Keras Documentation
画像判定器の作成
#ライブラリ import os from flask import Flask,request,redirect,url_for,render_template from werkzeug.utils import secure_filename from keras.models import Sequential,load_model import keras,sys import numpy as np from PIL import Image import tensorflow as tf #動物の学習データ取り込み model=load_model('./animal_cnn.h5') graph = tf.get_default_graph() classes=["猿","イノシシ","カラス"] num_classes=len(classes) image_size=50 #キャラクター学習データ取り込み model_anime=load_model('./anime_cnn.h5') graph_anime=tf.get_default_graph() classes_anime=["ミク","レム","チノ"] num_classes_anime=len(classes_anime) image_size_anime=50 #犬猫学習データ取り込み model_dogcat=load_model('./animal_cnn_dogcat.h5') graph_dogcat=tf.get_default_graph() classes_dogcat=["犬","猫"] num_classes_dogcat=len(classes_dogcat) image_size_dogcat=50 #アップロードフォルダパス指定 UPLOAD_FOLDER='./static/uploads' ALLOWED_EXTENSIONS=set(['png','jpg','gif']) #flaskのおまじない app=Flask(__name__) app.config['UPLOAD_FOLDER']=UPLOAD_FOLDER #何かしらの文字入れないと動きませんでした。多分ログイン機能追加するときに使う? app.config["SECRET_KEY"]="sample" #.があるかどうかのチェックと、拡張子の確認。 def allowed_file(filename): return '.' in filename and filename.rsplit('.',1)[1].lower() in ALLOWED_EXTENSIONS #ルーティング @app.route('/') def index(): flag="main" #ページ転送 return render_template('index.html',flag=flag) #動物画像投稿時のアクション @app.route('/',methods=['GET','POST']) def post(): #学習データ読み込み global graph with graph.as_default(): if request.method=='POST': #ファイルがなかった時の処理 if 'file' not in request.files: flag="animal_none" return render_template('index.html',flag=flag) #アップロードされたファイル取り出し file =request.files['file'] #ファイル名がなかった時の処理 if file.filename == '': flag="animal_none" return render_template('index.html',flag=flag) #アップロードされたファイルのチェック if file and allowed_file(file.filename): #危険な文字の削除(サニタイズ処理) filename = secure_filename(file.filename) #ファイル保存 file.save(os.path.join(app.config['UPLOAD_FOLDER'],filename)) filepath = os.path.join(app.config['UPLOAD_FOLDER'],filename) #RGB変換、リサイズ、numpy配列変換 image=Image.open(filepath) image=image.convert('RGB') image=image.resize((image_size,image_size)) data=np.asarray(image) #リスト型変数宣言、data付加、numpy配列変換 X=[] X.append(data) X=np.array(X) #結果を格納 result=model.predict([X])[0] #最大値を格納 predicted=result.argmax() #百分率化 percentage=int(result[predicted]*100) return render_template('index.html',classes=classes[predicted],percentages=str(percentage),filepath=filepath) #ルーティング @app.route('/bunken') def bunken(): flag="bunken" return render_template("index.html",flag=flag) #ルーティング @app.route('/anime') def ani(): flag="anime" return render_template('index.html',flag=flag) #キャラクター画像投稿時のアクション(変数が変わるだけで動物画像時と仕組みは同じ) @app.route('/anime',methods=['GET','POST']) def anime(): global graph_anime with graph_anime.as_default(): if request.method=='POST': if 'file' not in request.files: flag="anime_none" return render_template('index.html',flag=flag) file =request.files['file'] if file.filename == '': flag="anime_none" return render_template('index.html',flag=flag) if file and allowed_file(file.filename): filename = secure_filename(file.filename) file.save(os.path.join(app.config['UPLOAD_FOLDER'],filename)) filepath = os.path.join(app.config['UPLOAD_FOLDER'],filename) image=Image.open(filepath) image=image.convert('RGB') image=image.resize((image_size_anime,image_size_anime)) data=np.asarray(image) X=[] X.append(data) X=np.array(X) result=model.predict([X])[0] predicted=result.argmax() percentage_anime=int(result[predicted]*100) return render_template('index.html',classes=classes_anime[predicted],percentages_anime=str(percentage_anime),filepath=filepath) #ルーティング @app.route('/dogcat') def dogcat(): flag="dogcat" return render_template('index.html',flag=flag) #犬猫画像投稿時のアクション(変数が変わるだけで動物画像時と仕組みは同じ) @app.route('/dogcat',methods=['GET','POST']) def dogcats(): global graph_dogcat with graph_dogcat.as_default(): if request.method=='POST': if 'file' not in request.files: flag="dogcat_none" return render_template('index.html',flag=flag) file =request.files['file'] if file.filename == '': flag="dogcat_none" return render_template('index.html',flag=flag) if file and allowed_file(file.filename): filename = secure_filename(file.filename) file.save(os.path.join(app.config['UPLOAD_FOLDER'],filename)) filepath = os.path.join(app.config['UPLOAD_FOLDER'],filename) image=Image.open(filepath) image=image.convert('RGB') image=image.resize((image_size_dogcat,image_size_dogcat)) data=np.asarray(image) X=[] X.append(data) X=np.array(X) result=model.predict([X])[0] predicted=result.argmax() percentage_dogcat=int(result[predicted]*100) return render_template('index.html',classes=classes_dogcat[predicted],percentages_dogcat=str(percentage_dogcat),filepath=filepath) #最初にimportするとなぜか動かないので直前に書きました。 from flask import send_flom_directory #保存したアップロードファイル呼び出し @app.route('/static/uploads/<filename>') def uploaded_file(filename): return send_from_directory(app.config['UPLOAD_FOLDER'],filename)
webフレームワークのFlaskを用いた。
公式サイトとpaizaがおすすめ。
「Flask」入門講座一覧(1講座) | プログラミング学習ならpaizaラーニング
Welcome to Flask — Flask Documentation (1.1.x)
最初にpaizaの入門講座を1周して公式サイトを読んだ。
イノシシ猿カラス判定器、いぬねこ判定器、青髪キャラ判定器
3つの判定器を組み込んだのでちょっとコードが長くなってしまった。
画像をアップロードすると、判定してくれる。
精度73%くらいなので間違える時もある。
青髪キャラは画像をあまり集められなかった(各50枚程度)ことで過学習気味になってしまい精度があまり出なかった。
OpenCVなどを用いて顔の部分だけ特徴量を抽出させてみると改善につながるかもしれない。
pythonも深層学習もド素人であるが、ライブラリをフル活用することでなんとか形になった。
GW全日潰したが良い経験になった。
Githubに環境設定等載せました。
pythonで3dグラフを書く
ベクトル解析の講義で立体図を書かされた。その答え合わせのためにpythonを使って立体図を書いてみた。
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D def f(x, y): return x**2-y**2 Z = f(X, Y) # 描写 fig = plt.figure() ax = Axes3D(fig) ax.plot_surface(X, Y, Z, alpha=0.5, edgecolor='black')
x,y,z描写してみる
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D def f(x, y): return 1/(x**2+y**2)**0.5 Z = f(X, Y) # 描写 fig = plt.figure() ax=Axes3D(fig) ax.set_xlabel('$x$', fontsize=15) ax.set_ylabel('$y$', fontsize=15) ax.set_zlabel('$z$', fontsize=15) ax.plot_surface(X, Y, Z, alpha=0.5, edgecolor='black')
意外と簡単...
windowsで作ったmincraftサーバー(forge導入済)をlubuntuに移行
ubuntuにマイクラサーバー立てる方法は、ネットの海探せばいくらでも見つかるけどlubuntuに立てた人はあまり見たことないので一応書いておく。(ほとんど導入方法同じなんだけどね。)
*新規で建てるのではなくwindowsからの移行です。(軽い環境に移したかった)
*一応verは1.12.2
1.windowsでforgeマイクラサーバーを立てる
ググって
2.フォルダごとusbメモリか何かでlubuntu機に移動
3.鯖が入ってるフォルダーにシェルスクリプトを作成
#!/bin/bashjava -Xms1024M -Xmx1024M -jar <forgeのjar> nogui
例えば
#!/bin/bash
java -Xms1024M -Xmx1024M -jar forge-1.12.2-10.12.2.1121-universal.jar nogui
とか。
サーバーのjarじゃないよ。ファイル名は何でもいいがstart.shにする。
*noguiの前で改行すると起動しなかったので注意
*windowsで作った起動パッチをシェルスクリプトに変える場合、windowsで作成したファイルは改行コードが\r\nとなっている場合があるので\rを取り除く。ターミナルで作業ディレクトリ移動して
$ sed -i 's/\r//' start.sh
パッチ書き換えるより新規でシェルスクリプト作った方がいいね。
4.java導入
ターミナルに
$ sudo apt-get install openjdk-8-jre
*ver8以外だと動かなかった。
5.ファイルの設定
開くアプリケーションでOpenJDKを選択
パーミッション開いて、実行で"すべて"もしくは"所有者のみ"を選択
*jarファイルはすべてこの作業を行ってください(mod含めて)
6.起動
ターミナル起動してcdコマンドで作業ディレクトリを移動。
例)
$cd /home/ユーザー名/サーバーがあるファイル
移動したらさっき作ったシェルスクリプト実行。
$sh start.sh
起動できるはず。
lubuntuのみでサーバー新規導入も同じように行えばできると思う。forgeDL前にjavaのインストールとDLした後のファイルの設定(5に書いたやつ)忘れずに。
追記)virtualboxとかの仮想環境からマイクラサーバー運用できないかなって思ったんだけどクッソだるそう。
Minecraft Server auf Linux Debian 8 (VirtualBox, Java 8) Teil 1| Spigot | Bukkit | Plugins - YouTube
TP-Link Archer C1200 レビュー 簡易NAS速度など
6年くらい使ってる無線lanルーターが流石に調子悪くなってきたので買い換えようと思った。
希望としては
- 有線ポート4つ以上(1gbps対応)
- 5ghz帯対応
- 5000円くらい
amazonでいろいろ探してみるとこれを見つけた。
バッファローでもよかったが物理アンテナついてたほうが電波強そう(小並感)
早速購入。
タイトルにもあるように、このルーター簡易NAS機能ついてるんですね。usb3.0非対応だけど。ちょうどHDD余ってたので試してみようかと思いました。
WDの500gb(5400rpm)をhddケースに入れてルーターに接続。
hddケースはこれ。
crystaldiskmarkで計測。
hdd(5400rpm)-usb2.0-LANだもん。こんなもんだよ。
読み込み-約66mbps 書き込み-約97mbps
itunesの音源全部このNASに入れてみたけど、やっぱりちょっと重い。mp3は問題ないが、wav音源再生するときもたつく。
おまけ
openvpnで外出先から接続。
mineoのためキャリアよりも4g速度は遅めなので、あまり参考にはならないかも。
好きなコンポーザーを挙げていく
こんばんは。tosonです。
音ゲーを嗜む人は音ゲーの楽曲提供者つまり作曲家のことをよくコンポーザーって呼びます。たぶん。コンポーザーを和訳すると作曲家なので、英語圏では広域な意味、一般名詞としての作曲家ですね。
私自身、音ゲーは上手くないのですが、音ゲーの曲が大好物なので、好きなコンポーザーを適当に挙げていきたいと思います。
Kiryu
cytus cytus II crossbeats musica等に楽曲あり。
私が初めて知ったのはcytusのQですね。bpm192で繰り広げられる疾走感あるピアノとドラムンベースのループが特徴的。典型的なartcoreですね。こういうの大好き...
resurrection
Kiryu氏曰くQの続きを考えて作ったらしい。cytus IIに収録。
Destino
シンセ使わないアコースティック系の曲も良い。
arforest
同じくartcore系統の楽曲が多いコンポーザー。
lanotaやdynamix,arcaeaなどのスマホゲーへの楽曲提供が多い印象。
Altros
めっちゃきれい...(語彙力)
journey
イントロはオルゴール、サビまでのつなぎはオーケストラ風。サビはuk hardcoreと、もりだくさんながらも綺麗な楽曲。
sakuzyo
知らない人いないでしょ...
M3で行列できてたらどれかは必ずsakuzyo氏ブース。
映画アマデウスのモーツァルト役の目を若干細くしたような顔に似てるとか似てないとか。
axion
これ作った当時16やで...やばない...
何回このセリフ聞いたかな。年齢抜きにしても神曲。
altale
初めて聴いたとき鳥肌立ったんですよ...歌詞がない曲でもここまで心に訴えかけることができるんだなと。個人的に一番好きな曲です。
ujico*(別名義snail's house)
Kawaii Future Bassという新たなジャンルをつくった若手作曲家。
太鼓の達人に曲収録されていた気がする(ごめんなさい...太鼓やったことないです...)
MVのコメントがほぼ英語だったりと、日本よりも海外で人気がある気がする。
ラ・ム・ネ
夏休みに家でゴロゴロしてラムネ飲んでるような情景が思い浮かぶ曲。何故かこの曲を聴くと甘酸っぱい気持ちになるんだよなあ。あー私恋愛経験0です。はい。
dream city
ujicoさんって曲の拍というか、音と音の間の時間をすごい大事にしているイメージがあるんだよな。聴いてて安心する曲。
もりもりあつし
BPM遅めの曲から速めの曲までダンスミュージック系統なら何でも作れる印象。
ザ futurebass メロディーの緩急が癖になる。
pupa
あー好き... voezで100回以上やった気がする。c♭キーならではの響きと高速メロディラインが気持ちいい。
もっと紹介したかったのですが英語の課題終わってないのでまたあとで。
ibasso DX80のバッテリー交換
こんにちは tosonです。
Ibasso DX80というdapを愛用しているのですが
2年前に中古で購入して駆使してきたため、最近リチウムポリマーバッテリーが膨らんできてしまいました。よくある経年劣化ですね。
バッテリーの交換しようとヒビノインターサウンド(正規代理店)のサポートセンターに連絡したところ送料別で4800円。
バッテリー単体販売はしていないので本体を送ってくれとの事でした。
技術料を取られるのはもったいないと思い、ibasso公式のサポートセンターにバッテリー単体販売出来るか問い合わせてみるとできると返信が来ました。
バッテリー8ドル送料5ドルとの事でした。
送金はpaypalで行いました。
購入から発送までのやり取りは英語で、eメールで行いました。
このような個人輸入は初めてだったのですがibassoサポート担当者が丁寧に受け答えしてくれたためスムーズに取引できました。
少しトラブルになったのはpaypalに登録してあった住所が日本語のままだったことですね。
発送できないから英語で書いてくれと言われました。
発送から到着まで2週間くらいかかりました。
何故か知らないがオランダから届く。
開封!
え?D14?
D14の筐体の中にバッテリーありました...
ぴったりはまってます。輸送時の保護には最適解ですね。
3700mAh。 元々のバッテリーより100mAh容量アップしてました。バッテリーのケーブルも若干太くなっていて好感が持てます。
バッテリー交換して公称時間かそれ以上バッテリーが持つようになりました。
DX80の太い音が好きなのであと3年くらいは使っていきたいですね。
レートにもよりますが送料込みで1400円くらいでした。
英語でのメールのやり取りに抵抗がなく自分でバッテリー交換できる人は是非チャレンジしてみてください。
分解方法はこの記事がわかりやすいと思います。