TEX Shinobiが来た!
2019年6月頃に注文したTEX shinobiがコロナ禍を乗り越えて家まできました.
重厚感がほしいなあとおもって黒軸にしたような気がします.トラックポイントがそのまんまThinkpadですね.レトロなキーキャップがとてもかっこいいです.学生時代,Thinkpadのsapce saverを使っていたので,デザインを見た瞬間注文を決めました.
ダンボールで送られてきましたが,本体はとてもおしゃれな箱に入っていました.小さい方の箱がBTキットです.
早速尊師スタイルで遊んでみました.非常に安定感があります.
クリックボタンのコツコツ感が最初きになりましたが,慣れると気持ちよくなってきました.
スペース,シフト,エンターのスタビライザからカチャカチャと音がするので
外からグリスを入れてみましたが劇的には改善しませんでした.様子を見ながら対応していきたいと思います.
何度見てもレトロな雰囲気と重厚感がたまりませんね!仕事ではこれをメインに使っていきたいと思います!
自己証明書とNGINXでhttps通信
nginxでリバースプロキシができたので、次はフロントのサーバまでの通信をHTTPSにしてみたいと思います。簡単のため証明書はオレオレ証明書(自己証明書)を使いたいですが、そのままだとブラウザに危険サイトだと怒られるので、まずそれの設定をします。なおOSXでの設定です。
前準備
わかりやすくするために、/private/etc/hostsを編集してIPアドレスに名前をつけます。
127.0.0.1 localhost 255.255.255.255 broadcasthost ::1 localhost 192.168.3.3 airbell.com # 追記
自己証明書の発行
証明書の中に接続先の方法を埋め込みます。そのためのファイルname.txtを作成し、server.crtを作るときにそれを読み込みます。
$ echo subjectAltName = DNS:airbell.com, IP:192.168.3.3 > name.txt $ openssl genrsa 2048 > server.key $ openssl req -new -key server.key -subj "/C=JP/ST=Some-State/O=Some-Org/CN=airbell.com" > server.csr $ openssl x509 -days 3650 -req -extfile name.txt -signkey server.key < server.csr > server.crt
自己証明書の登録
server.crtをクリックしてKey chainがSystemになっていることを確認してAdd。Keychain Accessの設定画面でつくった自己証明書をダブルクリック、TrustをAlways trustに変更すればOKです。
NGINXの設定
リバースプロキシ用に設定したnginx.confをSSLが使えるように以下のように修正しました。設定変更後、sudo nginxで再起動をします。
http { # 省略 ssl_protocols TLSv1 TLSv1.1 TLSv1.2; server { listen 8111 ssl; server_name 192.168.3.3; ssl_certificate /path/to/server.crt; # サーバー証明書のパス ssl_certificate_key /path/to/server.key; # 秘密鍵のパス # 省略 } }
確認
ブラウザでアクセスできました。
続いて、リバースプロキシのバックエンドのFlaskにもアクセスしてみましょう。HTTPではエラーですが、HTTPSだと結果が帰ってきました。 Flask側には何もSSLの設定はいれていませんが、フロントのサーバが壁となってくれることが期待できます。
$ curl http://airbell.com:8111/API_1 -X GET <html> <head><title>400 The plain HTTP request was sent to HTTPS port</title></head> <body> <center><h1>400 Bad Request</h1></center> <center>The plain HTTP request was sent to HTTPS port</center> <hr><center>nginx/1.17.9</center> </body> </html> $ curl https://airbell.com:8111/API_1 -X GET { "message": "Response from flask server[API_1]" }
Lighttpdとnginxでリバースプロキシ
ゴール
フロントのサーバのIPアドレスが192.168.3.3で、127.0.0.1:8123で待っているflaskのweb APIをリバースプロキシで呼び出したい、という状況です。 Lighttpdとnginxどちらでもいいですが、設定が簡単で開発の盛んなnginxのほうがいいかもですね。 フロントのサーバはhttpsにしないといけませんが、それは後でやります。
index.html
hello world!
Flask
import flask app = flask.Flask(__name__) @app.route("/API_1", methods=["GET"]) def API_1(): response = {} response["message"] = "Response from flask server[API_1]" return flask.jsonify(response) @app.route("/API_2", methods=["GET"]) def API_2(): response = {} response["message"] = "Response from flask server[API_2]" return flask.jsonify(response) if __name__ == "__main__": app.run(debug=True, host="127.0.0.1", port=8123)
Lighttpd
server.modules += ( "mod_proxy") var.server_root = "/usr/local/var/www" server.document-root = server_root server.port = 8111 index-file.names += ("index.html") $SERVER["socket"] == ":8111"{ $HTTP["host"] == "192.168.3.3" { $HTTP["url"] =~ "^/API_1"{ proxy.server = ( "" => (( "host" => "127.0.0.1", "port" => 8123 )) ) } } } $SERVER["socket"] == ":8111"{ $HTTP["host"] == "192.168.3.3" { $HTTP["url"] =~ "^/API_2"{ proxy.server = ( "" => (( "host" => "127.0.0.1", "port" => 8123 )) ) } } }
NGINX
http { server { listen 8111; server_name 192.168.3.3; # reverse proxy location /API_1 { proxy_pass http://127.0.0.1:8123; proxy_set_header Host $host; } location /API_2 { proxy_pass http://127.0.0.1:8123; proxy_set_header Host $host; } location / { root html; index index.html index.htm; } } }
確認
どちらでも、192.168.3.3:8111から127.0.0.1:8123へアクセスできました。
curl http://192.168.3.3:8111/API_1 -X GET > { > "message": "Response from flask server[API_1]" > } curl http://192.168.3.3:8111/API_2 -X GET > { > "message": "Response from flask server[API_2]" > } curl http://192.168.3.3:8111 -X GET > hello world!
メモ
Lighttpdは-Dでフォアグラウンド実行
$ lighttpd -f /usr/local/etc/lighttpd/lighttpd.conf -D
nginxは設定ファイルに以下のように書くとフォアグラウンド実行となります。
deamon off
Karabiner-ElementsでVSCodeのキーバインド変更メモ
背景
VSCodeの素晴らしい拡張Awesome Emacs Keymap
marketplace.visualstudio.com
でVSCode上でもEmacs likeな操作感をエンジョイしています。ありがとうございます。ただ、MacでMetaキーがoptionに割り当てられていて微妙に押しにくいのと、他のOSで開発するときにAltの位置と違っていて混乱するというので、Karabiner-Elementsをつかってそこをなんとかしました。(Metaキーを任意のキーに割り当てるやり方があれば教えていただきたいです)
方法
MacのModifier設定で⌘とoptionを入れ替えるのはあまりにも副作用があるのでやりたくありません。VSCode上で⌘をMetaキーに割り当てれば全て解決なんですが、Awesome Emacs Keymapでそれをどう設定すればいいのかわかりませんでした。ということで、Karabiner-ElementsでVSCodeのときだけoptionと⌘をスワップするようなルールを書きました。
Karabiner-Elementsを使うと最前面になっているアプリ毎にショートカットやキー変更が設定できます。最高です。素晴らしいソフトウェアをありがとうございます。
pqrs.org
手順としては以下のようにしました。
- .config/karabiner/assets/complex_modifications/0.jsonというファイルを作成した*1
- 0.jsonに内容を記入した
- Karabiner-ElementsのComplex modificationsでAdd ruleで該当するものをEnableにした
{ "title": "Visual Studio Code", "rules": [ { "description": "Swap command and option in VSCode to use Emacs Keybinds", "manipulators": [ { "conditions": [ { "bundle_identifiers": [ "com\\.microsoft\\.VSCode", "com\\.microsoft\\.VSCodeInsiders" ], "type": "frontmost_application_if" } ], "from": { "key_code": "left_command", "modifiers": { "optional": [ "any" ] } }, "to": [ { "key_code": "left_option" } ], "type": "basic" }, { "conditions": [ { "bundle_identifiers": [ "com\\.microsoft\\.VSCode", "com\\.microsoft\\.VSCodeInsiders" ], "type": "frontmost_application_if" } ], "from": { "key_code": "left_option", "modifiers": { "optional": [ "any" ] } }, "to": [ { "key_code": "left_command" } ], "type": "basic" } ]
しかしこれだと既存の⌘+tabなど⌘を利用するショートカットもoptionで利用することになり少し不便です。なので、よく使うショートカットについて、⌘とoptionをさらにスワップしてみます。0.json内の"rules"が配列なので、新しい辞書を以下のように追加しました。
{ "description": "Command + Tab --> Option + Tab to use App changer in VSCode", "manipulators": [ { "conditions": [ { "bundle_identifiers": [ "com\\.microsoft\\.VSCode", "com\\.microsoft\\.VSCodeInsiders" ], "type": "frontmost_application_if" } ], "from": { "key_code": "tab", "modifiers": { "mandatory": [ "left_option" ] } }, "to": [ { "key_code": "tab", "modifiers": [ "left_command" ] } ], "type": "basic" } ] }
追記
⌘+Tab+Shiftで逆順に巡るやつの対応ができていなかった。これまでと同じようにやってもうまく機能しなかった、辛い。
*1:名前は数字でないとダメ、という情報を鵜呑みにしています
ポートフォリオ最適化でCVXOPTを学ぶ
リターンを確保しつつリスクを最小にするポートフォリオを構成するにはどの銘柄をどれだけ持てばいいのでしょう?
ポートフォリオに銘柄$i, (i = 1, \dots, N)$をどれだけの割合もつかということを$\boldsymbol{x} = [ x_1, \dots, x_N ]^{T}$、各銘柄のリターンの共分散行列を$C$とすると、ポートフォリオ全体の分散は$\boldsymbol{x}^{T}C\boldsymbol{x}$となります。各銘柄の期待リターンを$\boldsymbol{m} = [ m_1, \dots, m_N ]^{T}$とすると、ポートフォリオ全体のリターンは$\sum_{i=1}^{N}{m_i x_i}$ですね。ポートフォリオの分散を最小化しつつリターン$r$以上を求めるには、以下の条件で最適化を解くことになります。この最適化は非線形最適化のうち二次計画法で解ける形です。
まずは米株のデータをQuandlで取得します。収益率は前日との変化率としました。
from datetime import datetime import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import quandl start = datetime(2010, 1, 1) end = datetime(2018, 12, 31) symbls = [ # DOW30種 "AAPL", "AXP", "BA", "CAT", "CSCO", "CVX", # 中略 "WMT", "XOM" ] # Quadlで株価取得 codes = ['WIKI/' + symbl for symbl in symbls] data = quandl.get(codes, start_date=start, end_date=end) types = [code + " - Adj. Close" for code in codes] df = data[types] df.columns = symbls df_return = df.pct_change().dropna() # 収益率 N = len(df.columns) # 銘柄数
ある銘柄の期待収益率は、ある期間での日々の収益率の平均値に日数を掛けたものとしました。各銘柄の収益率の共分散行列も求めます。こちらは日々の収益率の分散から計算しています。分散を最小化するポートフォリオには少なくとも15%程度の収益率を持たせることにしました。
# 期待(?)収益率 = 全区間の収益率の平均値に任意の期間を掛けたもの duration = 252 # [days] m = df_return.mean().values * duration # 日々の収益率の共分散行列 cov = df_return.cov().values # 最適化するPFの収益率の最小値 r = 0.15
以上でポートフォリオの分散を最小にする銘柄選択のための数字が準備できました。これをCVXOPTで計算し、どの銘柄をどれだけの割合で持てばいいかを計算してみます。目的関数と制約条件をCVXOPTに読み込ませるため、多少の式変形を行います。CVXOPTが想定する2次計画問題は以下の形となっています。
# 最適化ソルバへの入力を準備 g1 = np.eye(N) g2 = -np.eye(N) G = np.vstack((g1, g2)) G = np.vstack((G, -m)) # h = [1,1,...1, 0,0,...,0,-r] h1 = np.ones(N) h2 = np.zeros(N) h = np.hstack((h1, h2)) h = np.hstack((h, -r))
最後にCVXOPTの最適化計算を行います。
import cvxopt from cvxopt import matrix cvxopt.solvers.options['show_progress'] = False P = matrix(cov) q = matrix(np.zeros(N)) A = matrix(np.ones(N).reshape(1,N)) b = matrix(1.0) G = matrix(G) h = matrix(h) sol = cvxopt.solvers.qp(P,q, A=A, b=b,G=G, h=h) print("Optimized Portfolio") for i, e in enumerate(sol["x"]): if e > 10e-3: print(f"{df_return.columns[i]}\t: {e:.4f}[%]") risk_e = 2 * sol["primal objective"] x_e = np.array(list(sol["x"])) r_e = m.dot(x_e) print("-------------------") print(f"PF variance \t: {risk_e:.8f}") print(f"PF std \t\t: {np.sqrt(risk_e):.8f}") print(f"PF return \t: {r_e:.8f}") # ===> Result # Optimized Portfolio # BA : 4.46[%] # CVX : 2.35[%] # DOW : 32.37[%] # KO : 11.50[%] # MCD : 4.10[%] # MMM : 30.72[%] # NKE : 2.94[%] # PG : 2.70[%] # TRV : 3.79[%] # WMT : 3.69[%] # ------------------- # PF variance : 0.00001859 # PF std : 0.00431213 # PF return : 0.15000158
収益率を15%以上に保ちながら分散を最小にするには、以上のように銘柄を選択すればいいようです。この計算を信じる限りは。
。。。
問題は各銘柄の期待収益率、収益率の分散や共分散行列がどう求めるかでしょうね。
やってから検索してQiitaでよく似たことをやっている記事がありました。先に見なくてよかった。。。
pytorchハマったところ備忘録
Cuda assert fails: device-side assert triggered
BCELossにnanを入力していました。BCELossの入力は[0,1]なのでエラーが出ますね。BCEWithLogitsを使えば[0,1]以外も扱えますが、nanをだしている方をなんとかしました。nanが出ていた理由は学習率が高すぎたというものでした。schedulerでburn in期間を設定して、最初は小さなものから徐々に大きくすることにしました。
logをコピーしすぎてGPUメモリが足りない
for batch in dataloader: (中略) running_loss += loss # loss.item()でないと勾配情報をどんどんコピーしていまい、メモリリーク
Accumulated gradients
大きなバッチサイズを確保したいがGPUのメモリが足りないので、勾配を貯めることにしました。 BNはbatch1つ分のままになってしまうようですので注意が必要です。
accumulation_steps = 4 # batch_size * accumulation_stepsだけ蓄積 for itr, batch in enumerate(dataloader): imgs, targets = batch loss = model(imgs, targets) loss = loss / accumulation_steps loss.backward() if (itr + 1) % accumulation_steps ==0: optimizer.step() optimizer.zero_grad() ````
B spline曲線と曲面
B spline曲線について勉強したかったんですけどずっと放置していたので、ついに実装して遊んでみました。 basic functionとknot vectorが曲線にどう関係してくるのか実装するまでわかっていませんでした。
Basic function
ついでにB spline曲面も実装しました。u方向の制御点m個とv方向の制御点n個をつかって、control netなるの行列をつかって以下のように表現できます[1]。実装はgithubのjupyter notebook参照。
参考
[1]https://graphics.stanford.edu/courses/cs348a-09-fall/Handouts/surfaces8.pdf