若き研究者の日常

技術寄りの事かポエムを書く。

個人事業主として開業する際のtips

筆者は某国立大学の博士課程であり,SPRINGという博士課程の経済支援プログラムに採用されています.この制度のおかげで月18万円の生活費を得ているのですが,確定申告を自分でしないといけないらしいです. その際に,雑所得ではなく事業所得にした方が税の優遇措置を受けられるとのことで個人事業主として開業し,月18万円の生活費を事業収入として受領することにしました.

以下では,雑所得と事業所得の違い,確定申告に関する大まかなサービス,自分が行ったフローチャートを記します.

雑所得と事業所得の違い

どっちも収入としてみなされることには違いはないです.が,事業所得を青色申告していれば、青色申告特別控除が受けられます.ざっくり理解で言うと,「この収入は自分が事業で頑張って手に入れた収入で,この収入を得るためにこんなビジネスに関する支出が必要だったんです.」みたいな申告ができて,税務署が「うむ,,,なら必要な支出分は多めに見てやるか.それ差し引いた分を収入として考えていいよ.」って言ってくるイメージです.max65万円の支出を実際の収入から差し引けます. 書類上で自分をより貧困層ですとアピールしていくイメージです.そうすると所得税,住民税,保険料の支払いの額も減っていくっぽいです.

確定申告に関する大まかなサービス

何らかの所得を自分の事業で得た収入だと言い張るためには,確定申告が必要となります. 大まかに,Moneyforwardクラウドと,freee開業というサービスが個人事業主の開業届を出すのや確定申告に使えるサービスとなります.それぞれ年額大体1万円強かかりますが,レシートをアナログ保存したりするのめんどくさすぎるのと,大体10万20万円くらい支払いせず済むらしいので導入する方が得です.

フローチャート

1. 開業届を出す

自分はMoneyforwardクラウド開業届を使って開業しました.他に,freeeで開業届もクラウド上から出せるみたいです.

2. 領収書を貯める,or クラウド会計管理アプリの導入?

一応今年度は紙媒体も保存してます.電子で保存したいが,クラウド会計管理アプリのサブスク代金をケチっている... 僕はfreeeを使うつもりです.クレカとか株の資産管理をMoneyforward MEで行なっているので,Moneyforwardクラウドを使おうか悩んだんですが,freeeの方がUIが初心者に優しいらしいのとMoneyforward MEからデータ取り込んだりもできるらしいのでfreeeにしました.とはいえまだ使ってはいない.

5. 確定申告?

今年度末なのでまだできていない.

所感

自分はどっちかというと収入を増やす努力をした方が支出を減らす努力よりもいいと考えるタチなのですが,財務の知識はある程度あるべきな気はしてるので博士の間数年は少しこういうのにフォーカスしてもいいのかな.とはいえレシート管理をちまちまするのは面倒くさいので早い事外注したい.

参考サイト

フェローシップや次世代研究者挑戦的研究プログラムに採択された博士課程の学生は開業届を出して個人事業主になろう|たぐれおん

「SPRING次世代」確定申告~研究奨励費を事業収入とするには~|山本山雅

電子帳簿保存法に対応してレシートを保存するには?ポイントを解説 - 電子帳簿保存法お役立ち情報 - 弥生株式会社【公式】

某財団の奨学金に落ちた

某アート系の財団の奨学金に落ちました. 特段いう事でもないんだけれど,結構悔しかったので成仏.というか,悔しさを雑多にここに書いとけば後々奮起する際の着火剤になりうると思って記す.(特にどこに落ちたかは隠すつもりはないけど,SEOとかで上に来すぎたら嫌なので言い換え表現適宜してます.)

落ちたのはどんな奨学金だったかというと,元々は芸術作品制作者に配られる奨学金で,とはいえ最近は何か,もっと幅広く,AIに注力している人に奨学金を払うようになっています.

僕は今年初挑戦で,自分の一番の売りと思って研究内容をESに書いてたらESは通りました.しかしここが失敗だったかも.ESで引っかかったのが研究者の人達(面接時には二人から質問されるが,どちらも研究者バックグラウンドの方だった)に対してっぽかった.面接の様子を友達(芸術系)に聞いたら「パッションをぶつけるんや」とのことだったので,言語やコミュニケーションの分野が好きっていう熱意を面接ではベラベラ話してたんですが,ガチ研究面接みたいな感じの質問が飛んできてたので「あ,これ学会発表と同じ対策するべきだった」って思いました.

僕はどちらかというと,この奨学金の一番の売りは奨学金ではなく秋口にある作品制作展にあると思ってます.秋の作品展にアートっぽいもの出したいモチベでこの奨学金出してた(これまでは大学内の範囲でしか作品制作をしたことはない)ので,一貫性とか無茶苦茶に通じちゃったんだろなと思っています.あとは即興で話をまとめるのも得意というわけではないし.

僕は今年25なのでセカンドチャンスはないので残念なのは正直な感想です,,,が,芸術を通じて自分の考えを外に出すことは好きなので続けていこうかな.威を借りる必要がないくらいに自信つけたいなって逆に奮起してます今は.

御殿下記念館の講習会予約サイトをハッキングする

東京大学には御殿下記念館と呼ばれる場所があり,トレーニングルーム,ボルダリングウォール,クライミングウォールなど様々な運動のための施設が内部に設置されている.

ただし,それらの設備を使うためには,トレーニング室利用登録講習会/ボルダリング講習会/クライミングウォール講習会を必ず受講しなければならず,それには予約フォームにおける予約が必要となる. とはいえ,東京大学マンモス校であり,通常は以下のように常に満員となっている.ライブチケットの予約のごとくサイトに張り付き,1ヶ月以上先の予約を抑えねばトレーニングルームを使うことができない.

筆者はこのサイトがPHPで書かれた古典的なサイトであることを踏まえ,ホワイトハッキングの初めてのステップとしてちょうど良いだろうと思い,ハッキングし,予約をインジェクションできうるか調べることにした.結果としてはインジェクション攻撃が可能であることが示された.

この図の通り,受付上限人数を超えた予約済み人数となっている(上限人数でバリデーションを行っていないことが原因と思われる)

この件は御殿下に報告中である. 以下はメモを記す.

URLについて

御殿下予約サイトのURLの例は以下のようになっている.先述した通りPHPで書かれており,予約申し込みページから予約確定ページに遷移する過程でGETで色々パラメタを送っているっぽい.遷移順は「講習会予約日程選択ページ」から日程を選ぶと,「予約申込ページ」に飛び,そこで氏名などの情報を入力させ,「予約確定ページ」へと遷移する.予約確定ページに遷移した時にDBに入力された情報がメールで送信されてくる.

講習会予約日程選択ページ
https://www.undoukai-reserve.com/lectureclass/system/prog/select_program.php

予約申込ページ
https://www.undoukai-reserve.com/lectureclass/system/prog/reservation_input.php

予約確定ページ
https://www.undoukai-reserve.com/lectureclass/system/prog/reservation_finish.php?submode=update&categories_id=1&courses_id=2&date=2024-04-30&starttime=13:30:00&endtime=14:30:00

hiddenタグについて

講習会予約日程選択ページの予約ボタンごとにhiddenタグのvalueが異なっていてForm Actionで同じページに飛ばす仕組みなので,valueを書き換えれば思ったところで予約できる.

  • catergories_idは1がトレーニングルーム,2がボルダリング予約,3がクライミングウォール.

  • course_idは分からんが,時間帯ごとに分けられて管理されているわけではなさそう.トレーニングルームとボルダリング講習会は2,クライミングウォールは5になっていた.

  • programs_idはページの上から順にユニークな数字が振られている. 現在の予約人数はwhere(program_id=hoge)をcountした値が貼られている.

  • program_idと開催日時の紐付けが多分DBのテーブルで行われていて,多分格納している値はprogram_idとユーザの情報だけ. 5月17 13:30-のが3519で5月2413:30-が3520(講習日時の時系列順ではないため注意!).(他のメモ.3522ダメ.3527は5月20日17:30〜.3525が5月18日17:30~.) date, starttime, endtimeの値が予約完了メールに使われて送信されるけど,dbにはprogram_idや名前などが格納されてるだけでこれらの値は格納されてない(なのでdateとprogram_idに不整合があるリクエスト送ったらprogram_idの方の日時が優先される).

  • submodeがnewの場合とupdateの場合の動作の違いはメール文が変わるだけっぽそう?(予約してる状態でupdateのリクエスト送ったら一旦予約解除しろというページに遷移したので,既存のDBの情報を更新してくれるわけではなかった.)

  • order_limitはなんだろう?満員か否かのフラグかと思ったけど,いじらなくても定員オーバーで予約できた.

  • hiddenでvalueを渡す形式ってどうなんだろうと思って最近のサイト見てみたら,hot pepper beautyの予約サイトとかGatsby公式サイトはhiddenタグのvalueが空だった.このあたりがどう動作してるかあんまり分からない.セッション情報をうまく使って分岐させている?

  • 予約完了ページのこれらのタグについてはまだ調査できていない.

  • developer toolってページの表層上の見た目を書き換えるだけかと思ってたけど,ちゃんとvalueを書き換えれば,リクエストも変更後のが送られるので便利だと思った.

  • developer tool使えばwebフォントも出てくるの知らなかった.便利

Create MLを試してみる

犬の犬種判別器を作ってみました.ガチで10分20分でできてしまったので,とても驚いている...

データセットはここから引っ張ってきた: Stanford Dogs Dataset | Kaggle

Create MLにディレクトリを放り投げるだけ.データ拡張とかも可能っぽい.今回はしなかった.

tensorboard的な学習具合も確認できる

訓練データ,評価データのスコアも確認可能

モデルのプレビューもすぐにできる.精度としては7割なので早速間違ってはいる.

ライブプレビューも可能.机にある青い鳥くんはパグと認識されている.

入力や出力も確認できる.

モデルの保存やXcodeへの輸出もすぐにできる.

次のステップはPyTorchからのモデルの輸入だが,それなりに引っかかるところはありそうだねぇ. 【Coremltools】PyTorchのモデルをCoreMLに変換する際にハマりまくった話 #iOS - Qiita

他にもAudio Analysisを試してみた. 以下のサイトから声優統計コーパスを拾ってくる.3人の女性声優様たちの声データである

日本声優統計学会

ところが学習させたところあんまり識別率が良くない.まあ確かに,生データを聞いたけど自分でも正直3人の声の違いがあまり分からない.

この記事では非常にうまく性能が出ている.作者にお聞きしたところ各声は10分程度のデータだったとのこと.サザエさんなどのアニメではこの辺うまく声質の切り分けなどされているのかもしれない. SoundAnalysis + Create MLで話者認識 #Swift - Qiita

参考

犬の写真から犬種を判別するアプリを作成してみた

Creating an Image Classifier Model | Apple Developer Documentation

自作キーボードを作った(Neo65,組み立てからVIAによるリマップまで)

最近自作キーボードを作りました.キーボードの中の構造とか,キーマップの変更について知識が深まったので良かった.Neo65というPCBを使ったキーボードで作りました.

キーボード組み立て

スタビライザーのズレを直す

スタビライザーはShiftやスペースなどの長いキーの水平性を保つための部品である.画像で言う鉄棒っぽいやつ. 直すときはこのような中のインクを抜いたボールペンの殻を利用する.

プレート,スタンドオフ,スタビライザー,PCBの組み合わせ

プレートとはキースイッチをはめる穴の空いた板の事で,スタンドオフはPCBとプレートの間を開けるために使われるつっかえ棒的なやつ.

組み合わせるとこんな感じ.ハンバーガーで例えると,プレートが上のバンズ,PCBが下のバンズ,スタンドオフとスタビライザーがピクルスとかハンバーガー的なノリ.

キースイッチをはめる

キースイッチをはめるとそれっぽくなってくる.今回は基本の部分にTecsee Honey Peach Metal Pole Switch,特殊キー周りにDurock Black Lotus Linear Lubedを使った. どっちもリニア軸で,ピンクの方は45g, ストロークは3.5mm, 接点までの距離は2.0mm.紫の方は55g,ストロークは4.0mm, 接点までの距離は2.0mmだった.

キートップを被せるとこんな感じ.

キーマップ変更

キーマップを変更するときはこれらのサイトを参考にした.

Review: Neo65 Custom Mechanical Keyboard – Tech Jio

VIA– SUPER KOPEK

Neo65の場合はVIAというキーマップに関するブラウザアプリを使うっぽい.PCB用のキーマップの設定ファイルを公式サイトから拾ってきて読み込ませてキーマップの変更をしたりできる.

デフォルトの設定はこんな感じ.

シミュレータもついている.押したところのキーが紫で表示されるので,どこを押したらなにが動作したら気持ち良いのか調べられる.

自分の場合,右下の2つのAltとMO(0)キーが使わなそうだったので,バッククォートとM(1), つまりFnキーに変更しておいた.

MO(1)について何かというと,キーボードにはレイヤーというものがあり,通常0レイヤー目のキーマップに基づいて入力が行われる.しかし,MO(n)を押すとそのレイヤーにキーマップが移動し,さらにキーの数分の入力語彙が増えるという仕組みである.レイヤー1の標準設定は上の画像の通りだったので,いわゆるMacのFnキーと同じ働きをMO(1)はしている.

MOの他にも色々種類がある. MO: momentary turn on layer hogeの略で,他には TG:toggle, TT...など

ChatGPTのiOSアプリの車輪の再発明をした

写真の通り.

今は普通にiOSのUI設計をして,裏でchatGPT APIとナイーブなHTTP通信をしているだけ.

今後はOpenAIKitを使ってリファクタリングしたりとか,Vision APIに対応させたりしたいわね. SwiftUIに慣れる良い機会だった.

ボードゲーム強化学習をする際に思ったこと/ データセット保存する際にハマった点

最近ボードゲーム強化学習手法を適用しようと試行錯誤しています.

修論発表や他の論文発表準備やら新年度からの金策準備でてんてこ舞いなんですが,なんとか時間捻出して実装してみたいので,1週間弱くらい部屋にこもって風呂入らずにカタカタしています.汚ねえ.

今やってることは論文出したいので大局的なところは書きませんが,実装することでなんとなくこれまではTD学習,Q学習,SARSA,Actor-Criticとか机上で覚えてきたことばっかだっただったのが一部だけでも身に染み付くような感覚になるので,実際の実装の中身をのぞいていじるのはとても楽しいです.

例えば, Online学習とOffline学習の2つの実装を対比して比べることにより, より2つの実装の必要とされている場面を想像できるような気がします.Offline学習手法はミスが許されないような環境にデプロイするというのは授業で習ったことですが,実際に取得したデータからどうstateやrewardを付加していくか考える際にOnline学習が有効になりそう,つまりソリッドなデータセットもない条件で作るプロトタイプにはOnline学習環境を整えるべきとか.

あとは題材にするゲームについて,ボードゲームは駒のルールといった制約付き,行動空間や状態が非常に多いしかし空間は離散的に処理できる,その一方でHalfcheetahとかmujocoっぽいアレらは空間が連続的だけど次元数は少ないとかそういう実装上の常識についても学びました.素人的に強化学習始める前はボードゲームの方がmujocoとかより簡単やない?と思ってましたが,こっちの方が変な制約を考える方に頭が削がれる(行動空間が状態によって可変だし)のでむずくね?って思ってます.分かんないけど.

あとはMuZeroがなんでアルゴリズム無しに勝手にそれぞれのボードゲームのルールを学ぶんだと思ってましたが,あ,Offline強化学習でデータセットから学ばせるのか,とか(そもそも最初はOnline強化学習しか頭になかったので強化学習でデータセットを使うという発想がなかった...はずかし).

今は古典的なDQNでオンライン学習させて,それで得た棋譜とそれに応じた軌跡のデータを収集しようとしている段階です(オフライン学習させてみたいので)

今日引っかかったところですが,observationの保存をミスってTensorで保存してたのですが,1軌跡だけで3.5GBになるくらいデータ量が爆発しちゃいました*.listでやり直したら11MB** (それでも1軌跡としてはデカイ...).(余談,あとでnumpyでやり直したら17.6MB)

tensorで保存したら30分くらいかかりました.一方でlistでobservation保存したら47秒.ちなみにnumpyは30秒.

*中身を覗くと

'observations': array([list([tensor([0, 0, 6]), tensor([0, 1, 6]), tensor([0, 2, 6]), tensor([0, 3, 6]), tensor([0, 4, 6]), tensor([0, 5, 6]), tensor([0, 6, 6]), tensor([0, 7, 6]), tensor([0, 8, 6]), tensor([1, 0, 8]), tensor([1, 8, 8]), ....

**中身を覗くと

'observations': array([list([[0, 0, 6], [0, 1, 6], [0, 2, 6], [0, 3, 6], [0, 4, 6], [0, 5, 6], [0, 6, 6], [0, 7, 6], [0, 8, 6], [1, 0, 8], [1, 8, 8], [2, 1, 8], [2, 7, 8], [3, 2, 8], [3, 6, 8], [4, 7, 7], [5, 1, 7], [6, 3, 8], [6, 5, 8], [7, 4, 8], [14, 0, 2], [14, 1, 2], [14, 2, 2], [14, 3, 2], [14, 4, 2], [14, 5, 2], [14, 6, 2], [14, 7, 2], [14, 8, 2], [15, 0, 0], [15, 8, 0], [16, 1, 0], [16, 7, 0], [17, 2, 0], [17, 6, 0], ....

***中身を覗くと

'observations': array([array([[ 0,  0,  6],
              [ 0,  1,  6],
              [ 0,  2,  6],
              [ 0,  3,  6],
              [ 0,  4,  6],
              [ 0,  5,  6],
              [ 0,  6,  6],
              [ 0,  7,  6],
              [ 0,  8,  6],
              [ 1,  0,  8],...