技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

キャプチャボード導入と、録画を試す

こんなものを購入したので、色々試したメモです。

Elgato Game Capture HD60 Pro [並行輸入品]

Elgato Game Capture HD60 Pro [並行輸入品]

  • メディア: Personal Computers

これは内蔵型キャプチャボードで、USB 型も存在しています。
面倒とか、中触るの怖い人はこっち Elgato Game Capture HD60 S [ソフトウェアエンコード式キャプチャボード(日本国内正規品)] 1GC109901004 を使うと良いかも知れません。

インターフェースは PCIE なので、スロットが開いてるかどうかも確認しましょう。
因みに、留めネジは入ってないので、事前に用意しておく事を推奨します。

この内臓キャプチャボードには、IN/OUT のHDMIポートがあり、IN が録画用ソースで、OUT はパススルー出力ポートである。
パススルーというのは、録画用の処理を一切せず、IN の内容を出力するもので、こっちは完全に遅延なし。
これを利用して、OUT のHDMI をディスプレイやTVに繋げば、遅延を気にせず遊べます。(USB版もパススルーはできるはず)

インストール

まずはデバイスドライバインストールと、キャプチャソフトインストールを行います。
ダウンロードサイトはこちら

www.elgato.com

自分のキャプチャボードと、OS を選ぶと

f:id:white-azalea:20210419190223p:plain

二つのアプリが出てきます。
ダウンロードするのは右側の GAME CAPTURE の方。 (4K CAPTURE UTILITY はおそらくTVとか動画とかをキャプチャするためのツールじゃないかな…)

f:id:white-azalea:20210419190249p:plain

因みに、気づかないと凹むのはこっそり下の方に View game capture drivers here. とか書いてあるやつ。
なんでドライバがこっそりしてるんだよとは思うけど、これも入れておく。

f:id:white-azalea:20210419190457p:plain

インストールする順番は気にしなくても良いらしい。

続きを読む

Salesforce開発の基礎編1

教科書はコレ。

trailhead.salesforce.com

問題となるのは、この勉強用プラットフォームの翻訳を信用できないという所(汗
日本語だと正解選択肢が出ないとかいうバグもちらほらある。

加えて単語の訳が微妙過ぎて、同じページで同じ単語の訳が一貫してないとかいうクソ仕様まであるので、改めて先頭から見ようかと。

プラットフォーム開発の基礎 | Salesforce Trailhead

超ざっくり要約:

  1. プラットフォーム開発の開始
    Trailhead Playground という環境の作成チュートリアル
    忘れてはいけないのは、環境作成直後に「英語」に変更しておくこと。
    多分それ以外に注意点はない。
    Salesforce では、環境一つ一つを「組織」と呼んでる。「Trailhead Playground」で作成された環境も「組織」と呼ぶことがあるので注意。
  2. コーディング不要の開発
    OSS 開発でブイブイ言わせてた人のためには基本的に読み替えが出来れば理解しやすいと思う。
    • メタデータ = テーブルに関連した表示設定などの周辺設定情報
    • オブジェクト = テーブル、またはテーブルスキーマ
    • 項目 = カラム定義
    • レコード = レコード 注意点「オブジェクト」と紹介しているくせに、後述でオブジェクト操作のUIを「スキーマビルダー」とか言い出してるところ。 オブジェクトの定義内には、データの形状のほかに見せ方の定義(レイアウト、検索条件などのメタデータ)が含まれてるのが重要な点かと。
  3. Salesforce 言語によるコーディング
    開発する際によく使うフレームワーク/言語の紹介。
    • Lightning コンポーネント Salesforce は過去のアップデートで Lightning というインターフェースに移行してて、その際出てきたフレームワーク
      Lightning インターフェースに沿った画面が作れたり、Lightning 特有のコンポーネントを組み合わせることで、リッチな画面を作成しようというもの。 XML + JavaScript で書くことになるが、独自仕様と制限が多いので嫌われ気味。
    • Apex
      Salesforce で開発するとなったときの大体の場合の第一言語
      Java ライクを目指したといいつつ、Generics は実質利用不可能で、リフレクション関連も利用できない。
      Java 1.4 にかろうじて List に型が宣言できる程度だと思っておくと良いかもしれない。
      コード中に SOQL というオブジェクトにのみ適用できるクエリが書ける。
    • Visualforce
      画面作成や、外部公開ページ(非Salesforce組織ユーザ向け画面)を作る際に良く使われる候補。
      ASPJSP の流れを持った奴だと思うと分かりやすい。 尚、Visualforce のバックエンドは Apex 一択で、static 変数は JSP と違ってセッション単位にインスタンスができる。 つまり、他のユーザと static 変数の共有はしない所は勝手が違う。
  4. Salesforce Platform の拡張
    Salesforce は外部からアクセスする手段をそこそこ沢山持ってる。
    また、Heroku が Salesforce 傘下なので、Heroku 上の Postgres ←→Salesforce object をリンクするなんてこともできる。

Apex と .NET の基本 | Salesforce Trailhead

因みに .NET と聞くと Microsoft .NET を連想しそうだが、正直忘れないと地獄を見る。
これはやればやるほど分かるが「どこが .NET じゃ」と暴れるレベル。

  1. .NET の概念の Lightning プラットフォームへの対応付け
    ざっくり概要:
    • Apex はオブジェクト指向で、C# ライクな構文形態してますよ
    • データ型は大体似てますよ
    • リスト/セット/マップ 位のデータ構造は似た感じで使えますよ
    • ASP.NET と Visualforce は似てますよ(←個人的に絶対にNOと言いたい。良いところ ASP 止まりでしょう…)
    • Apex はデータと密接に連携してるので、LINQ っぽいクエリ書くけど、これはレコード専用だよ。
    • 設計パターンが互換しない(フレームワーク構造と使い方は1から慣れてね)
    • 単体テストコードで 75% 以上カバーしない場合、本番環境にリリース禁止ね♪ (← 個人的には良い仕様)
    • ソリューションファイル、プロジェクトファイル、設定ファイルがない
      (組織アップロード時にコンパイルだから)ローカルコンパイルしないし、何処に何を置くかの構造も決まってるので、こうした設定の類はありません。
      …ということにしておきましょう。厳密には sfdx というのが最近の主流で、これには設定が結構含まれる。
    • クラスライブラリがはるかに小さい…というか実質無い。
    • セキュリティの処理...サーバ上で、しかも特定組織でしか起動しなかったり、ユーザ単位でのアクセス権などが全部 Salesforce 上で完結するので、データベースの接続文字列とか不要です
    • インテグレーションについて 外部からの接続アプリが作れます。
  2. 実行コンテキストの理解
    コンテキストは「文脈」とか「状況」みたいに考えると理解しやすいです。
    Apex コードの呼び出し方(呼び出される状況)は複数パターンありますという話。
    ここでは演習として、データベーストリガを書きます。
    レコードの Insert 直前、Insert 後、更新直前…といったレコード処理の前後でコードを実行し、関連データ更新だったり保存値の変更だったり、入力チェックだったりできます。
  3. 非同期 Apex の使用
    非同期というとあれですが、別スレッドで処理を実行することを意味します。
    ケースの説明で
    • 処理するレコード件数が非常に多い
      バッチを使いましょう。
      Salesforce には ガバナ制限 という悪名高い制限があり、Apex 処理中でアクセス/更新するなどの回数/量に制限があります。
      バッチでなら一部回避できます。
    • 外部 Web サービスへのコールアウトを行う
      外部の REST API を呼んだりすることを「コールアウト」と呼んでます。
      この操作は、データベースの更新処理(update/delete/insert)後に実行できないという制限があるので、このような状況だけ非同期にするという手段を取ります。
    • Queueable Apex
      future より制限薄い実装

多分 Queable とか非同期周りは以下を見た方が良いかもしれない

keneloper.com

マジで駄文。ボウリングのスコア計算

ボウリングのスコア計算ってどういうルールなんだろう?
と思って調べてみた。

スコアの付け方

なるほどそういうルールだったのか…興味ないから今まで知らんかった(汗

  • ストライク = 10 点+次の 2 投分
  • スペア = 10 点 + 次の 1 投分

ストライクは次の 2 投分 + 10 するということは、「ストライク → 1, 3」となったとき、10+1+3, 1, 3 という計算になるのだろう。
仮に9 フレーム目まで All Strikeで、10フレーム目で「1, 0」だったと仮定すると

9 フレーム目にフィードバックで 11, 8 フレーム目= 10 + 10(9フレーム目) + 1(10フレーム目) みたいな計算になるはず。
てことは、実質最後から計算した方が計算しやすいのかもしれない。

全フレームストライクと仮定すると、最初の 2 投まで1投目のスコアはつかず、3投目決まった時点で 30 点になる。
で、その後もストライクが続くと 1 フレームあたりマックススコア 30 が 10 フレーム続くので、 300 点マックスと。

やっぱりこれは後ろから計算した方が楽そうだ。

python にゃ配列の処理が豊富なので、色々楽にできる。

# 各フレームのスコアを列挙してみた
score = [
    [9, 1],
    [8, 2],
    [10],
    [5, 0],
    [3, 6],
    [4, 2],
    [7, 3],
    [6, 3],
    [10],
    [9, 1, 9]
]
score.reverse()
score

[[9, 1, 9], [10], [6, 3], [7, 3], [4, 2], [3, 6], [5, 0], [10], [8, 2], [9, 1]]

逆順ソートできるのでイイネ
そしたら 10 フレーム目だけ単純 sum して残りをスライスでループしたらいい

total=0
next1, next2 = 0, 0

# 最終フレームは特別扱い
total += sum(score[0])
if len(score[0]) == 3:
    next1, next2, _ = score[0]
else:
    next1, next2 = score[0]
print(f'Total: {total}')

# 他のフレームを計算
for frame in score[1:]:
    print(f'frame {frame}')
    frame_sum = sum(frame)
    if len(frame) == 1:
        print(f'strike! 10 + {next1} + {next2}')
        total += 10 + next1 + next2
        next1, next2 = 10, next1
    elif frame_sum == 10:
        print(f'spere! 10 + {next1}')
        total += 10 + next1
        next1, next2 = frame
    else:
        print(f'append {frame_sum}')
        total += frame_sum
        next1, next2 = frame
    print(f'Total: {total}')

total

結果: イインジャネ?

Total: 19
frame [10]
strike! 10 + 9 + 1
Total: 39
frame [6, 3]
append 9
Total: 48
frame [7, 3]
spere! 10 + 6
Total: 64
frame [4, 2]
append 6
Total: 70
frame [3, 6]
append 9
Total: 79
frame [5, 0]
append 5
Total: 84
frame [10]
strike! 10 + 5 + 0
Total: 99
frame [8, 2]
spere! 10 + 10
Total: 119
frame [9, 1]
spere! 10 + 8
Total: 137
137

WSL に Salesforce 開発環境を作る

「汚さず」というのはWindowsのPATHとか常駐とか増やしたくないのです。
で、どういう事かというと WSL2 に Ubuntu 突っ込んで、そこに sfdx をセットアップするという方向。

なぜセットアップかって?メインマシンに SFDX 入れてなかったからさ!

WSL2 インスコ

まずは、Windows subsystem for linux をインストールしよう。

docs.microsoft.com

やるならWSL2からだね。
当たり前だけど窓 10 限定。

  1. Powershell を管理者で起動して
    f:id:white-azalea:20210407201754p:plain
  2. Powershell脳死dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart と突っ込む。
    f:id:white-azalea:20210407201912p:plain
  3. 次のコマンドで dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart を叩く。
    f:id:white-azalea:20210407202148p:plain
  4. カーネルパッチを当てよう
    Windows Subsystem for Linux (WSL) を Windows 10 にインストールする | Microsoft Docs
  5. 最後にPowerShellwsl --set-default-version 2 を叩けばおk

因みに、最後のコマンド実行時に BIOS の仮想化が Off になってる場合は指摘されます。
BIOS の設定はマシンによるので、環境ごとにやって下さいな。

尚、ASUSIntel マザボの場合は、「詳細」「CPU」の中に 「Intel VT」があるのでこいつを有効にしよう。

Ubuntu のインストール…っても Windows ストアで「Ubuntu」って突っ込めば手に入ります。

f:id:white-azalea:20210407203444p:plain

初回起動時にアカウントとパスワードを登録する。
因みに、初回は以下をお忘れなく

$ sudo apt update
$ sudo apt upgrade -y

nodejs と sfdx インストール

なぜ nodejs からだって?sfdx単体でなんて入れたくないからだ

  1. sudo apt install nodejs npm -y でとりあえず二つをインストール。
  2. sudo npm install n -gn というコマンドをインストールする。こいつはパッケージ管理ツールみたいなもんだ。
  3. sudo n stable 安定版 nodejs いれませう
$ node --version
v14.16.1
  1. で、インストール後に apt で入れた node は消しとく。 sudo apt purge -y nodejs npm
  2. npm コマンドをアップデートしよう npm update npm
  3. sfdx をインストールして完了。 sudo npm install sfdx-cli --global
続きを読む

畳み込み層を実装してみる

white-azalea.hatenablog.jp

この辺の続き。
畳み込み層とプーリング層、ひいては CNN をしてみる。

前回の im2col 連中を、バッチサイズ/チャンネルとか踏まえて再実装。
超長いので、今回はここから続きを読むリンク…。

続きを読む

画像を行列で処理する前準備

CNN で特徴的な動作に畳み込みっちゅう処理がある。

画像には局所性(隣接するピクセルの影響を受ける事)があるので、それを利用して画像の特徴を強調したりできる。
やってることはフィルタを用意して、画像に畳み込み計算を行う事。

以下の例みたいに、左上からフィルタを適用して 1 セル生成。したら、右に 1 セルずらして…と繰り返す。


    \left(
        \begin{array}{cc}
            1 & 0 \\
            0 & 1 \\
        \end{array}
    \right)
    \times
    \left(
        \begin{array}{cccc}
            2 & 2 & 1 & 2 \\
            1 & 1 & 2 & 1 \\
            1 & 2 & 1 & 0 \\
            1 & 0 & 0 & 1 \\
        \end{array}
    \right)
    \longrightarrow
    \left(
        \begin{array}{ccc}
            3 & 4 & 2 \\
            3 & 2 & 2 \\
            1 & 2 & 2 \\
        \end{array}
    \right)

見ての通り画像自体は小さくなる。

因みにこのずらす間隔をストライドと呼ぶ。
ストライド幅が大きいほど画像サイズは小さくなり、特徴が見逃されやすくなる。

で、この計算するとしたときに普通の画像に対して処理するのがしんどいなんで整形するのが一般的なのだそうだ。

im2col

画像に対して畳み込みを行うには形状がめんどくさいので以下みたいに配置しなおす。
これを im2col と呼ぶっぽい。


\left(
    \begin{array}{cc}
        2 & 2 \\
        1 & 1 \\
    \end{array}
\right)
\longrightarrow
\left(
    \begin{array}{c}
        2 \\
        2 \\
        1 \\
        1 \\
    \end{array}
\right)

例えば 2x2 のフィルタで 3x2 のデータに適用するとき、まずは im2col でこんな風にしてしまう


\left(
    \begin{array}{ccc}
        2 & 2 & 3 \\
        1 & 1 & 2 \\
    \end{array}
\right)
\longrightarrow
\left(
    \begin{array}{cc}
        2 & 2 \\
        2 & 3 \\
        1 & 1 \\
        1 & 2 \\
    \end{array}
\right)

こう変換すれば、フィルタをドット積で一括計算できる。

で、実際に変換と逆変換をやってみた。

続きを読む

過学習対策あれこれ

white-azalea.hatenablog.jp

前回わざと過学習させてみたわけだが、そもそも学習の打ち切りはやたらと難しいハズだ。
あの時はデータセットが 200 位しかないし、ニューロンの数も限られていたといえる。
しかし、現実には大量のデータセットがあるだろうし、学習時間はそこそこかかるだろうと思われる。

例えば1回の学習だけで数時間かかるとする。
それを見て、じゃぁどの位で打ち切るか?2週目開始までにどれだけ待つ必要があるだろう?
要するに学習の打ち切りを判断するのはちょとどころでは難しいと予測できる。

ということで、今回はやり方を変えてみる。
まずは前回の誤差を見てみよう。

Epoch: 0 / 1000, Err_train: 1.1043634751935245, Err_test: 1.0623824378086812
Epoch: 100 / 1000, Err_train: 0.04227735559583767, Err_test: 0.13396243782658682
Epoch: 200 / 1000, Err_train: 0.018747407955545834, Err_test: 0.12865441586002588
Epoch: 300 / 1000, Err_train: 0.004991569690202153, Err_test: 0.218183645593179
Epoch: 400 / 1000, Err_train: 0.002959841289188, Err_test: 0.25887483170314346
Epoch: 500 / 1000, Err_train: 0.001493562533847086, Err_test: 0.3049230574592406
Epoch: 600 / 1000, Err_train: 0.0010474962034239849, Err_test: 0.3333645685971381
Epoch: 700 / 1000, Err_train: 0.0007757803305818819, Err_test: 0.3506614397003805
Epoch: 800 / 1000, Err_train: 0.0006128411251375161, Err_test: 0.36719589756963056
Epoch: 900 / 1000, Err_train: 0.0004995183637277335, Err_test: 0.37831813699595335

f:id:white-azalea:20210318205457p:plain

最終的に過学習のせいで 0.4 目指してエラーが広がっている。

モノは試しに RMSProp を導入してみた。
式は過去記事のものを利用。

white-azalea.hatenablog.jp

roh = 0.95

class RMSNeuron(Neuron):
    def __init__(self, n_upper, n, activation_function, differential_function):
        super().__init__(n_upper, n, activation_function, differential_function)
        self.h_w = np.zeros((n_upper, n)) + 1e-8
        self.h_b = np.zeros((n)) + 1e-8

    def update(self):
        # ここだけ更新
        self.h_w = (self.h_w * roh) + (1 - roh) * (self.grad_w * self.grad_w)
        self.h_b = (self.h_b * roh) + (1 - roh) * (self.grad_b * self.grad_b)
        self.w -= eta / np.sqrt(self.h_w) * self.grad_w
        self.b -= eta / np.sqrt(self.h_b) * self.grad_b


class Output(RMSNeuron):
    pass


class Middle(RMSNeuron):
    def backword(self, grad_y):
        delta = self.differential_function(grad_y, self.y)
        self.grad_w = self.x.T.dot(delta)
        self.grad_b = delta.sum(axis = 0)
        self.grad_x = delta.dot(self.w.T)
        return self.grad_x


# ニューロン初期化
mid_layer1 = Middle(n_in, n_mid, relu_func, relu_func_dash)
mid_layer2 = Middle(n_mid, n_mid, relu_func, relu_func_dash)
outputs = Output(n_mid, n_out, soft_max, soft_max_dash)

exec()

結果が

Epoch: 0 / 1000, Err_train: 1.1000068284857787, Err_test: 1.105102282860116
Epoch: 100 / 1000, Err_train: 0.0004723302009342129, Err_test: 0.25285731779944576
Epoch: 200 / 1000, Err_train: 2.435419747198503e-05, Err_test: 0.41570733582516095
Epoch: 300 / 1000, Err_train: 1.6498331127020632e-07, Err_test: 0.42415464268234687
Epoch: 400 / 1000, Err_train: 3.2775216891847647e-06, Err_test: 0.424167001320326
Epoch: 500 / 1000, Err_train: 1.7252434605417651e-06, Err_test: 0.42416032411453786
Epoch: 600 / 1000, Err_train: -9.588821783186093e-08, Err_test: 0.42416031798981263
Epoch: 700 / 1000, Err_train: 1.9298299962666904e-07, Err_test: 0.424160335489329
Epoch: 800 / 1000, Err_train: -2.7639660886741467e-08, Err_test: 0.42416031479869326
Epoch: 900 / 1000, Err_train: -9.780188673424984e-08, Err_test: 0.4241603145452869

f:id:white-azalea:20210318205756p:plain

ちょwwwww
過学習広がったしwwww

アカンw これ学習係数は一方通行で減らさないとダメだコレw

初期段階で一気に学習進めると、一時的に学習係数に圧がかかって、緩やかになるのだけど、それ以降で物忘れによって学習係数が跳ね上がる。 そこに過学習が入ってヒャッハーされたことが見て取れる。

続きを読む