OmniAICreator/Qiita-1.07M huggingface dataset:
UTMのRISC-V向けUbuntu上でGUI環境を導入してみた

# はじめに

この記事は、Qiita Advent Calendar 18日目の記事です。
以下の記事より、すべての記事をご覧になれます。

https://qiita.com/0_terarin_0/items/2b60d47a2d0e64a273c3

# 本編

みなさん、僕が以前に以下の記事を挙げたのはご存知でしょうか。

https://qiita.com/0_terarin_0/items/9c47ab3637c301a20ba7

この時に用意したRISC-VのUbuntu、これの処理にずっと悩んでいます。OpenWrtで遊ぶのにUTMを開いたついでに、このRISC-VのUbuntuで遊んでいきたいと思います。本当はCosmicを入れたいのですが対応していませんのでGnomeを入れていきたいと思います。

## インストール

まず、この記事は前回の記事で用意したほぼまっさらなdebianであると仮定します。まず最初にいろいろ必要なものをインストールします。

```zsh
su root # Rootでログイン

apt update # ここでエラーが出たら対処してください

apt upgrade # ここでもエラーが出るかもしれないでお気をつけあれ〜

exec $SHELL -l

usermod -aG debian sudo

exit
```

これでとりあえずの準備ができたので、あとはGnomeをインストールするだけ！

```zsh
sudo apt update && sudo apt upgrade # sudoが使えるかどうか試してみてください

sudo apt install gnome-core
```

実はインストールの過程自体はめっちゃ少ないです。ここで一旦シャットダウンをしましょう。

続いて、ディスプレイを追加します。下のようにディスプレイを追加してください。

![Screenshot 2024-12-21 at 15.17.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583428/de7da33a-11e1-41ce-f63d-cd40c37fa74f.png)

ちなみに、GPU Acceleration付きのものは起動しませんでした。

それでは、起動しましょう！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583428/4337399f-1f97-16f0-6e91-085356eaa86c.png)

無事起動できましたね！

## 使い勝手

はっきり言うて使い物にならないです:(　設定のアプリは起動したらそのまま固まりますし、だからと言って他に使えるものがあるかと言われればLibre Officeぐらい。アプリを自分でビルドする人ぐらいじゃないと必要ないんじゃないでしょうか。

# 最後に

なんか仮想化って素敵ですよね。
【AtCoder】ADT EASY 2024/12/19 復習【Golang】

問題リンク：https://atcoder.jp/contests/adt_easy_20241219_3/tasks/abc256_b

YouTube解説を見て、スッゲーと思ったので、解説をもとに復習してみました。

# 最終状態から考えよう！
「全員の人数 - 最終的に塁に残っている人 = ホームに到達した人の数」となるので、最終状態を作ってあげて、引き算すれば良さそうだということです。

## 回答コード
```go:C.go
package main

import "fmt"

func main() {
	var n int
	fmt.Scan(&n)

	A := make([]int, n)
	for i := 0; i < n; i++ {
		fmt.Scan(&A[i])
	}

	// 最終状態から考える
	// A[1 1 3 2]の場合、最終状態は[0 0 1 0]となる。
	// このことから、4人中1人がゴールできていないことがわかる
	// よって、p = 4人-1人 = 3人
	// 最終状態を作る処理
	var b int
	for i := 0; i < n; i++ {
		b |= 8     // マス0に駒を1個置く
		b >>= A[i] // 全ての駒を A[i] 分だけ右にシフトして移動
	}

	// 全体人数から残り人数を引く処理
	p := n
	for i := 0; i < 4; i++ {
		p -= b & 1 // 3塁にいる人を1減らす
		b >>= 1    // 次のマスに移動(まだ1塁、2塁に人がいるかもしれないので次の処理に移る)
	}

	fmt.Println(p)
}
```
説明のため、問題にある入力例1とは入力値を少し変えています。（[1 1 3 2]→[1 1 3 1]）

なんというシンプルさでしょうか。
解説を見ていて感動しました。

簡単なお絵描きをしてみたので、載せておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771904/1cb99ac6-d930-304d-11af-81a80cc859bb.png)
※お絵描きでは、AND演算は2進数で、引き算は10進数で書いています。

1とAND演算することで、3塁に人がいた場合、結果が1になるはずです。
それを全体人数から引いていく処理を、塁に残っている人分、処理します。

## 最後に
この発想をできるようになりたいと思いました。（コードが簡潔でオシャレ）
確か、鉄則本にも処理後の状態を考えると見通しが良くなると、テックニックとして紹介されていた気がします。
これを機に、問題の見方も学んでいきたい思います。
データベースのレプリケーション(物理レプリケーション/論理レプリケーション)

『達人に学ぶDB設計徹底指南書: 初級者で終わりたくないあなたへ』第2章
p.54 COLUMN「物理レプリケーションと論理レプリケーション」が面白かったので、メモ。

https://www.shoeisha.co.jp/book/detail/9784798186627

### データベースのレプリケーションとは
- **現用系・待機系２つのDBを用意し、現用系から待機系へデータ送信をすることで、DBのレベルでデータが同じになるようにする技術**
    - レプリケーションによってデータが反映される待機系DBを「レプリカ」と呼ぶこともある
    - 方法としては「同期レプリケーション」と「非同期レプリケーション」の2種類
        - **同期レプリケーション**：現用系に渡されたデータを現用系にコミット後、そのままリアルタイムでデータを待機系に渡し、待機系コミットが確認できてからシステムに完了通知を戻す
            - 非同期レプリケーションと比較して、コミット時間のずれが少ない
        - **非同期レプリケーション**：現用系コミット→システムに完了通知を戻した後に、同データを待機系にコミットを行う
            - 同期レプリケーションと比較してコミット時間のずれが生じる
- レプリケーションには **物理レプリケーション** と **論理レプリケーション** がある
    - 詳細は以降

このあたりは実業務で触れているので、概略はあれのことねとわかります。

### 物理レプリケーション
- データベース全体の完全な複製
- トランザクションログそのもの（REDOログ、WALログ）を転送することでスタンバイ側でもバイナリレベルで同一のデータベースを複製
    - したがって、異なるバージョン間での複製はできない
- 主な使用シーン
    - 災害対策
    - 参照負荷分散
        - 先日「[SQL発行回数を増やすかLINQで絞るか](https://qiita.com/hayami04/items/6b47305378c9109c1844)」という記事を書いたのですが、この場合SQL発行回数の増加に耐えられるためのDBの分散には、論理レプリケーションよりも物理レプリケーションのほうが適しているということか（というか、自分の中で漠然と物理のイメージであった）
- その他
    - 「ストリーミングレプリケーション」ともいうらしい
        - 🔗[第3回「ロジカルレプリケーション」 -NTTデータ先端技術株式会社](https://www.intellilink.co.jp/column/oss/2018/071700.aspx)
    - AWSの場合、大規模なデータベースには物理レプリケーションを利用できるが、同期にはかなりの時間がかかる場合がある
        - 🔗[AWS -物理レプリケーション](https://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/migration-databases-postgresql-ec2/ha-physical-replication-considerations.html)
    - AWSでの物理レプリケーションの一例
        - １. EC2 インスタンスのデータベースをレプリケートし、アーカイブファイルをコピー
        - ２. 新しいレプリカをデータベースライターエンドポイントとして昇格
        - ３. アプリケーションを新しいターゲットデータベースに向ける

<br>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2632896/c98d1131-d22a-b7a2-1b25-bcdff779c44a.png)

<br>

### 論理レプリケーション
- 論理的な変更情報（特定のテーブルのレコードに対する変更情報、イメージとしては**更新SQLそのもの**）を転送することで、スタンバイ側で変更操作をリプレイすることで複製を行う
    - したがって、基本的にテーブルに対する変更処理を対象として用いられるため、異なるバージョン間であっても複製が可能
- 主な使用シーン
    - 特定テーブルの複製
    - バージョンアップ時のデータ移行
    - 異OS間のレプリケーション
- その他
    - 「ロジカルレプリケーション」ともいうらしい
        - 🔗[第3回「ロジカルレプリケーション」 -NTTデータ先端技術株式会社](https://www.intellilink.co.jp/column/oss/2018/071700.aspx)
    - PostgreSQLの場合
        - TRANCATEコマンドやDDLはレプリケーションされない
        - シーケンス、通常のテーブル以外（インデックス・ビュー・マテビューなど）もレプリケーション外
        - 双方向レプリケーションはできない
        - コミットされた変更情報のみ反映、ロールバックされた変更はスタンバイ側に送信されない
        - レプリケーション衝突（一意制約の衝突など）が発生した場合、変更情報を適用するプロセスはエラー終了する
            - レプリケーション衝突を検知する機能は搭載していない


### 余談
- レプリケーションが個人的に面白いと思った点
    - 突発的に発生する可能性がある自体を想定していかに対策を組むか、というところが面白い
    - アプリケーションのアーキテクチャもそうで、制限がある中で最大限目的が達成できる水準を見極めて狙っていくみたいなことを考えるのがたのしい

### 他参考

https://ryuichi1208.hateblo.jp/entry/2024/05/21/082837

https://learn.microsoft.com/ja-jp/azure/site-recovery/physical-server-enable-replication

<br>
『応用基礎としてのデータサイエンス AI×データ活用の実践』第2章章末問題解答

[応用基礎としてのデータサイエンス AI×データ活用の実践 (データサイエンス入門シリーズ)](https://amzn.to/4gc8hfd)
<a href="https://amzn.to/4gc8hfd" target="_blank"><img src="https://m.media-amazon.com/images/I/61Ydv2hZuaL._SY522_.jpg" width=150 /></a>

解答が公開されてますが

https://www.kspub.co.jp/download/9784065307892_1.pdf

解説がないのと誤っている箇所もあるようなので解説付きで解きました

# 2 データエンジニアリング基礎
## 2.1 ビッグデータとデータエンジニアリング
- 2.1.1 ③
    - ①Volume　  大容量
    - ②Variety  種類が多様
    - 落ち運びは関係ない
    - ④Velocity 発生や更新が高速
- 2.1.2 ①
    - ②、③、④も一定のルールの下という制約はあるが原則正しい
- 2.1.3 ①
    - ①は構造化データ
- 2.1.4 ②
    - エッジコンピューティングを行うことで必ずしも高速な通信が必要とは限らない
- 2.1.5 ④
    - ……もうちょっとマシな外れ選択肢にできないかな

## 2.2 データ表現、プログラミング基礎、アルゴリズム基礎

- 2.2.1 ③
    - $2^8$
- 2.2.2 ①
    - 2進法では0.1は下記のような循環小数となりこれを3倍しても0.3とはならないため
    
    |2進法|10進法|
    |--:|--:|
    |0.1|$1/2=0.5$|
    |0.01|$1/2^2=0.25$|
    |0.001|$1/2^3=0.125$|
    |...|...|
    |0.000110011...|0.1|
    
    ```math
    \begin{align}
    
    \end{align}
    ```
- 2.2.3 ⑤
    ||a[0]|a[1]|a[2]|
    |---|--:|--:|--:|
    |初期状態|901|992|718|
    |b=aだが同じ実体||||
    |a[1]=997|901|992|718|
    |b[0]=911だがaと同じ実体なのでa[0]に代入される|911|992|718|
- 2.2.4 ②
- 2.2.5 ③
    - ①紀元前のユークリッドの『原論』に記載あり
    - ②$\mathrm{O}(n^2)$: バブルソート、$\mathrm{O}(n\operatorname{log}n): 2分木ソート、ヒープソート、マージソート$
    - ④フローチャートなど
    - ⑤Yes
## 2.3 データの収集と加工、データベース
- 2.3.1 ①
    - ②検索
    - ③クレンジング
    - ④フィルタリング
- 2.3.2 ④
    - ①友人の繋がりに偏ったデータとなる
    - ②インターネット利用が多い人に偏ったデータとなる
    - ③最寄りの駅に偏ったデータとなる
    - ④通学に来ない人もいるので通学している人に偏ったデータとなる。大学の名簿からランダムサンプリングした方が望ましいと思うが、この選択肢の中ならばこれか
- 2.3.3 ③
    - ①特徴の一つ
    - ②体調の変化を疑った方が良い
- 2.3.4 ②
    - ①テーブルのキーの連携でリレーションとなる
    - ③検索条件を指定るする
    - ④joinなどでできる
- 2.3.5 ②
    - 履修者名簿、試験点数表は実体なので四角①X③X
    - 試験は関係なのでひし形①X③X④X
    - 名前は属性なのでだ円③X④X

## 2.4 ITセキュリティ
- 2.4.1 ③
    - 1 xor 1 = 1, 0 xor 1 = 1 なので11
- 2.4.2 ④
    - $3\cdot n=1 (\operatorname{mod} 7)$よりn=5
        - 3*1=3
        - 3*2=6
        - 3*3=(9だが7で割ったあまりだから)2
        - 3*4=(12だが7で割ったあまりだから)5
        - 3*5=(15だが7で割ったあまりだから)1
- 2.4.3 ④
    ```math
    \begin{align}
    (p, g, y)&=(23, 2, 8)\\
    m&=3, r=2\\
    u&=2^2(\operatorname{mod 23})\\
    &=4\\
    c&=8^2\cdot3(\operatorname{mod 23})\\
    &=8\\
    &\therefore (4, 8)
    \end{align}
    ```
- 2.4.4 ②
    ```math
    \begin{align}
    (p, g, x, l)&=(23, 2, 3, 11)\\
    m&=2, r=2\\
    u_1&=2^2 (\operatorname{mod}23)\\
    &=4\\
    u&=4(\operatorname{mod}11)\\
    v&=2^{-1}(2+3\cdot 4) (\operatorname{mod}11)\\
    ここで&2^{-1}=6(\operatorname{mod}11)\\
    v&=18(\operatorname{mod}11)\\
    &=7(\operatorname{mod}11)\\
    &\therefore (4, 7)
    \end{align}
    ```
    
- 2.4.5 ②
    ```math
    \begin{align}
    \frac{60\times9+x}{10}&=63\\
    x&=630-540\\
    &=90
    \end{align}
    ```
CLコマンドでDLLを作り、利用する方法

# Windows Visual Studio 2022

cl.exe ファイル名 /LD

でDLLファイルを作成することができます。

Windowsアプリケーションではなく、C 標準のアプリケーションから利用するための方法を書いておきます。

## スタティックライブラリの作成
```
> cl func.c /LD
```
```func.c
__declspec(dllexport) int func(int a);

int func(int a)
{
	return a + 100;
}
```
パラメーターに100を加算し返します。

## スタティックライブラリの利用
```
> cl main.c func.lib
```
```main.c
#include <stdio.h>

__declspec(dllimport) int func(int a);

int main(void)
{
	printf("%d\n", func(1));

	return 0;
}
```
【MT4, MQL4】Access violationについて

# エラー出力
Access violation read to 0x00000002 in ...

# 原因
```c
double iSR(double &arr[]) {
   int size = ArraySize(arr);
   double sd = iStdDevOnArray(arr, 0, size, 0, 0, 0);
   return (sd == 0) ? 0 : iMAOnArray(arr, 0, size, 0, 0, 0) / sd;
}
```
配列のシャープレシオ（平均値/標準偏差）を求める関数。これをOnTester関数内で利用し、動的にリサイズした配列を参照渡しした場合、上記のエラーが発生しました。
よくわからないのですが、ArrayResizeによって動的に確保された配列は参照渡しできなさそうでした。
MIME,SMTPとは

### MIME
>発音区別符号のある言語や、ラテン語以外のアルファベットが使われてる言語、アルファベット以外の言語で書かれているメッセージを送信、受信する場合に問題が起こる。また、テキストデータ以外のを含むメッセージを送信する場合も問題となる。
この問題に対する解決法としてMIME(Multipurpose Internet Mail Extensions:多目的インターネット・メール拡張)が開発された。

>MIMEの基本的な考え方は、RFC822フォーマットをそのまま使い続けるものの、メッセージ本体に新しい構造を付け加え、非ASCⅡコード・メッセージの転送のための符号化規則を規定することである。

### SMTP
>メッセージの送信元から宛先間で中継していくところを見ていく、メール転送はSMTPプロトコルによって処理される。
#### メールを宛先に送る
>SMTPの利用法は二つに分かれていった。第一の利用法はメール投稿(mail submission)であり、
..
これはユーザー・エージェントが配送のためにメッセージをメール・システムに送信するための手段である。

#### 宛先に送るために中継する
>第二の利用法は、メッセージ転送エージェント間のメッセージ転送である。
...
このシーケンスは、送信側のメッセージ転送エージェントから受信側のメッセージ転送エージェントまで、1ホップでメールを配送する。

### ESMTP
>認証を行わないので、この例のFROMコマンドでは任意の送信者アドレスを指定できる。これはスパムの送信には非常に便利である。
第二に、SMTPは2進データではなく、ASCⅡメッセージを転送する。このためbase64 MIMEコンテンツ転送符号化が必要とされる。メール転送においてこの符号化は非常に帯域を使用するため、大きなメッセージを転送する場合に問題となる。
第三に、SMTPはメッセージを平文で送信する。詮索好きな目に対して、プライバシーを確保するための暗号化手段を持たない。

>これらの制限への対応とその他のメッセージ処理問題のため、SMTPは拡張メカニズムを持つように改定された。拡張メカニズムはRFC 5321の必須部分であり、拡張メカニズムを利用するSMTPはESMTP(Extended SMTP:拡張SMTP)と呼ばれる。

https://bookplus.nikkei.com/atcl/catalog/23/03/16/00728/
適当にWebブラウザを作ってみた

# Webブラウザを作ってみた
昔、ブラウザを作ろうとしたんです。
自分で作るって面白そうじゃないですか？
自分用にカスタマイズもできるし。
その時は知識不足過ぎて結局断念したんですが、
そこから何年か経ったので再チャレンジしてみました！

# 基本構造
- 入力されたURLからHTMLを取得
- HTMLをBeautifulsoupで解析
- HTML要素をTkinterのウィジェットに変換

こんな感じです。数十分で作ったのでクオリティは低いですが...
まあ基本的な部分は結構できたと思います！

# 最終結果
https://github.com/Cheesecake2960/my-browser/

GitHubに公開してあるので興味があったら見てみてください！
MIT Licenseです。

# 工夫した点
- aタグを触ったら、ページ移動ができる
- 一応h1~h6タグとa、pタグに対応
- フォントサイズをjsonで設定

# 改善点
- スクロールできるようにする(現時点でははみ出た部分は見られない)
- フォント、CSSを充実させる
- ~~Javascriptも動作？~~ (難しすぎて今は無理)

# おわりに
またいろんなものを自作してみようと思います！
最後まで読んでいただきありがとうございます:cheese::cake:
よければいいね、コメントお願いします！
【Python】並列処理がエラーなしに途中で終了してしまったら

## 【問題】　並列処理が途中で終了する
　Python のモジュール multiprocessing を用いた並列処理が、意図せず途中で終了してしまいました。

### 実行環境
* Python 3.12
* Jupyterlab 4.0.11
* Mac M2 CPU

### 問題発生例
　問題を単純化するため、乱数を出力する関数を定義し、並列処理により高速化する Python スクリプトを以下のように書いてみます。
~~~Python:スクリプト
import random
from multiprocessing import Pool, get_context

def random_output(n):
    hoge = random.random()
    print(hoge)
    return hoge

with get_context("fork").Pool(processes = 3) as pool:
    result = pool.imap(random_output, range(30))
    next(result)
~~~
* x ∈ [0, 1] を満たす乱数を出力する関数 random_output を定義し、並列処理数を3に設定して、random_print 関数を30回実行させます。
* Pool の属性として imap 関数を用いています。

~~~Python:実行結果
0.40398745671651450.89900968116753680.26495311715314007


0.11601183665445658


0.98591264346923340.09981477280742523
~~~

　途中で出力が止まってしまいますが、エラーメッセージは何も出力されません。
* 並列処理数（変数 processes）を変えると、出力される乱数の個数も変化しますが、おおよそ並列処理数の2倍の個数の乱数が出力されて、処理が途中終了するようです。
* 関数の実行回数を 50 回より多く増やしても、状況はほぼ変わりません。


## 【解決策】　出力方法を工夫する
~~~Python:スクリプト
import random
from multiprocessing import Pool, get_context

def random_output(n):
    hoge = random.random()
    return hoge

with get_context("fork").Pool(processes = 3) as pool:
    result = pool.imap(random_output, range(30))
    for value in result:
        print(value)
~~~
:::note warn
**主な変更点**
　関数 random_output 内で print 関数を用いて出力すると混乱しやすいため、imap 関数の戻り値（イテレータ）から for ループで値を取得して出力する形式としました。
:::
~~~Python:実行結果
0.7218835018631663
0.3344170045104009
0.2780252849217204
0.24464348558677929
0.7824587594620069
0.4031033777635977
0.4004705738677147
0.47249736737995274
0.2829334318060327
0.1198023443666798
0.016142659436964912
0.29097633922228905
0.5351089611467076
0.978746281757676
0.33647064561693363
0.703743517087453
0.8197703208763935
0.9998776471460239
0.4161895275766967
0.17547474473294977
0.12662025058123794
0.41937914018030653
0.3755981546742474
0.3983354791382634
0.1799064461511578
0.3390259115731551
0.9256859596614425
0.44345468675582844
0.29497952238706626
0.7332903747559089
~~~
　出力結果もかなり見やすくなりましたね。

## 途中終了の想定原因
　imap 関数は遅延評価関数であり、プロセスごとに開始時刻がずれています。関数 random_output 中で print 文を定義したことによって、関数が実行されるたびに print 関数も実行され、その出力がプロセス間で競合した、と推定されます（print 関数はプログラムの実行速度を低めます）。
　その結果、並列処理は完全に終了していないのに、あたかも並列処理を終了しきったかのような振る舞いを示しています。そこで、イテレータに全ての結果を格納した後に、for ループで結果を出力することで、イテレータを完全に消費する対策を取りました。

## 補足
　上記のプログラムは非常に単純なため、imap 関数を map 関数に変更する等でも並列処理の途中終了を解決できますが、メモリを多用する複雑なプログラムの場合、map 関数よりも imap 関数や imap_unordered 関数を用いた方が、処理が速く終わるケースが多いようです。

### 参考
* [Python3のマルチプロセスPoolのメソッドはimap_unorderedを使うべし](https://qiita.com/engulisyu/items/b255fab5ef2d35938589)
* [データサイエンスのためのPython入門32〜これだけ知っておけばいいmultiprocessingでの並列処理〜](https://datawokagaku.com/multiprocessing/)
整理券アプリを作る（環境構築編）

## いきなりのエラー

```
npx create-react-app react-app --template typescript
```
でフォルダを作成しようとしたところ、以下のようなエラーが出た。
```
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR! 
npm ERR! While resolving: react-app@0.1.0
npm ERR! Found: react@19.0.0
npm ERR! node_modules/react
npm ERR!   react@"^19.0.0" from the root project
npm ERR! 
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^18.0.0" from @testing-library/react@13.4.0
npm ERR! node_modules/@testing-library/react
npm ERR!   @testing-library/react@"^13.0.0" from the root project
npm ERR! 
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR! 
npm ERR! 
npm ERR! For a full report see:
npm ERR! /Users/himegitaichi/.npm/_logs/2024-12-21T05_02_40_858Z-eresolve-report.txt

npm ERR! A complete log of this run can be found in: /Users/himegitaichi/.npm/_logs/2024-12-21T05_02_40_858Z-debug-0.log
`npm install --no-audit --save @testing-library/jest-dom@^5.14.1 @testing-library/react@^13.0.0 @testing-library/user-event@^13.2.1 @types/jest@^27.0.1 @types/node@^16.7.13 @types/react@^18.0.0 @types/react-dom@^18.0.0 typescript@^4.4.2 web-vitals@^2.1.0` failed
```
どうやら `@testing-library/react@13.4.0`と`@testing-library/react@"^13.0.0`がreactのバージョン18を求めているみたい。だけどフォルダを作成するときに自動的にバージョン19をインストールするっぽい。

## 対応策
とりあえず作ったものは仕方がないので
```
npm install react@18 react-dom@18
```
でバージョンを下げた。
がしかし、まだ競合はあったがとりあえず`npm start`を実行
するとlocalhost:3000とともにエラー文がサイト上に出た。
```
Compiled with problems:

ERROR in ./src/index.tsx 7:0-24
Module not found: Error: Can't resolve './App' in '~/react-app/src'
ERROR in ./src/index.tsx 8:0-48
Module not found: Error: Can't resolve './reportWebVitals' in '~/react-app/src'
```
うん、`index.tsx`で`./App`と`./reportWebVitals`が解決できない？
とりあえず`index.tsx`を見てみる。

```
import App from './App';
import reportWebVitals from './reportWebVitals';
```
一旦拡張子入れてみるか...
```
#変更後
import App from './App.tsx';
import reportWebVitals from './reportWebVitals.ts';
```
お！エラーが消えた！
けども次のエラーが出た。
```
ERROR in ./src/reportWebVitals.ts 5:4-24
Module not found: Error: Can't resolve 'web-vitals' in '~/react-app/src'
```
次は`reportWebVitals.ts`を見てみよう。

```
import { ReportHandler } from 'web-vitals';
```
今度は`web-vitals`というモジュールがないみたい。なので
```
npm install web-vitals
```
でインストール...

エラー消えた！！
だけどそれはサイト上での話。VScode上ではまだエラーが...
とりあえず今回はこれでいいだろう。
そもそもなぜ`npx create-react-app`でエラーが出るのだろう？
そこが一発でいけるといいのだが...
個人開発における私なりの手順【備忘録】

フリーランス、個人開発しているとやりたいこと多すぎ迷子になってしまったり、プロジェクト管理のベストプラクティスがなんなのかわからなくなってきてツールをたくさん導入して満足…みたいな結果、経験しますよね？
フリーランスからどこか仕事を請け負おうと思っても、会社でのエンジニア経験ないと未経験枠としてのカウントになるから条件的に厳しくなってしまったりもありえます。
でもそれは自分で選んでいる道なので文句はないのですが、それだったらしっかり地力があるんだよってところを対外的にアウトプットしていた方がいいと思うんです。

自分自身を業界にとっての掘り出し物として捉えられるような努力も必要というか。

そもそも個人で管理している以上、モチベーションの管理も大変にはなってくるわけで、いろんなツールを導入しているとその都度学習コストもかかってくるわけじゃないですか。

だったら、業界としてしっかり使えている必要があって自分自身でトレーニングできることを普段からやればいいじゃんと思い、基本的な手順とかコマンドとかを覚えがきしておこうと思いました。

## 参考
- [GitHub CLI]("https://cli.github.com/")
- [［GitHub］一人開発でもissueベース/セルフプルリクエストを使って開発する]("https://qiita.com/braveryk7/items/5208263cd06a8878f0c2")
- [プルリクエストの一連の流れについて]("https://qiita.com/kuuuuumiiiii/items/42d2d9ed11e3b29c22cf#:~:text=%E3%81%84%E3%81%A8%E6%80%9D%E3%81%84%E3%81%BE%E3%81%99%E3%80%82-,%E3%83%97%E3%83%AB%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%A8%E3%81%AF,%E3%82%8F%E3%81%8B%E3%82%8A%E3%82%84%E3%81%99%E3%81%8F%E8%A1%A8%E7%A4%BA%E3%81%97%E3%81%BE%E3%81%99%E3%80%82")


## 基本的な流れ
上記参考のリンクにあげたところをしっかり取り組んでいくことが答えになりますが、ブラウザ行ったりターミナルにいって、エディタに移動して、別のアプリ開いたりとなると訳もわからなくなってきやすいので、なるべくターミナルとエディタとか、ブラウザのみで完結できるようにしようと思います。

1. GitHubでリポジトリ作る
1. デプロイしていくために必要となる機能、工程を考えてissueに分ける
1. issueごとにブランチをつど作成する
1. 開発する
1. 作業が完了したらpush→プルリクする
1. GitHub上でプルリクを確認
1. マージ
1. ブランチ削除
1. issue閉じる

今までなんとなくGASならスプレッドシートを新規に作っていたり、ローカル環境だと特定のディレクトリ内にプロジェクト作成してエディタ開いて、一定の作業終えたらGitHubのリポジトリ作ってやっていたのですが、まずリポジトリ作ってしまってissueまでたててしまった方が、全体像が見えやすいのではないかと考えました。

### GASによる開発の場合
GASの場合はコンテナバインド型かスタンドアロン型になりますが、僕はスプレッドシートに関するGAS組みするのが多いのでコンテナバインド型で一旦考えますがどちらも一緒になるはずです。
1. ブラウザ上のGitHubでリポジトリを作る
1. issueとブランチを作成する
1. GASエディタを開く
1. 以降上記の流れ

ずっとChromeを開きっぱなしの想定になります。GASエディタ上でブランチ作ろうとするとエラーになりやすいので、先にブランチまで作ってから作業するようにした方が良いです。
そして拡張機能だとpushはできるけどプルリクはできないので、pushしたらGitHubの画面に移動してプルリクを開始する流れになります。

### その他ローカルでの開発
GASだとChromeのブラウザがあればいいので、あとはGithubの拡張機能を導入すれば開発が進められる訳ですが、ローカル環境にディレクトリ作ろうと思うと今まではブラウザからリポジトリ作ってローカルにクローンするか、作業が一定進んだらリポジトリ作成してターミナルから`git remote add`してからpushしてました。
でもなんかあちこちいって面倒に感じていたので、上記の流れがいいように思います。
1. まずターミナル開いて任意のディレクトリを作成する
1. `gh repo create [リポジトリ名]`コマンドでリポジトリを作成する
    1. Flag：`--public`だとパブリックリポジトリになる
    1. Flag：`--private`だとプライベートリポジトリになる
1. `gh issue create`コマンドでissueを作成する
    1. Flag：`-a`をつけて`"@me"`をつけると自分に当てたissueとなる
    1. Flag：`--title`の後にダブルクオーテーションマークの文字列でタイトルを作成
    1. Flag：`--body`の後にダブルクオーテーションマークの文字列でissue本文を作成
    1. Flag：`--label`オプションでbug/enhancement/wontfixのどれかにしておく
1. `git checkout -b ブランチ名`でブランチの作成と移動を行う
1. `git remote add`コマンドで上記作成したリポジトリのURLを紐づける
1. 作業する
1. 以降上記の流れ

あとはどんなissueがあるかターミナルから確認するために`gh issue list`すれば今登録しているものが表示されます。

こうやっていけば、全体像を把握しながら、バージョン管理の勉強もしつつ開発のスキルもアップしていけるので良さそうですね。
これ応用したら別にプログラミングじゃなくてもノーコード開発とかでも結構使えそう。作業内容だけmdファイルに記述してアップしていけば見返しやすそう。
OSCP+ 合格体験記

## 概要
2024年12月にOSCP+試験を受け、無事合格することができました。
本記事では受験の記録とともに主に私が受験前に知りたかった内容を記載しています。同資格を受験する人や受験を考えている人の参考になればと思います。
![2024-12-20_22h33_47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3966879/d29801a7-90f6-2aeb-fa7b-306366bccfae.png)

OSCP自体の概要については本記事では割愛します。

## OSCPとOSCP+の違い
2024年11月からOSCP試験の更新が行われ、OSCP+という新たな認定が登場しました。要点を以下に記します。
* 試験合格するとOSCPとOSCP+が同時に認定される。
* OSCPの有効期限は無し、OSCP+の有効期限は3年間。特定の条件を満たすことでOSCP+の有効期限は更新できる。
* 2024年11月以前の合格者はOSCP認定、OSCP+未認定の状態。

詳細は[公式サイトの情報](https://help.offsec.com/hc/en-us/articles/29840452210580-Changes-to-the-OSCP)をご覧ください。

## OSCP+試験について
OSCP+試験は100点満点の試験で、70点以上で合格となります。
* stand-alone machines (20点×3)：独立した3台のマシンに侵入し、各マシンで管理者権限を取得することが目標。初期侵入10点+権限昇格10点。
* Active Directory （40点）：3台のマシンからなるAD環境に侵入し、各マシンで管理者権限を取得し最終的にドメインコントローラーの制御を取得することが目標。各マシンごとに部分点が入り、合計で10+10+20=40点。

**従来のOSCP試験からの変更点：**
従来のOSCP試験（2024/11以前）では事前に課題をこなすことで10点のボーナスポイントが獲得できましたが、OSCP+ではボーナスポイントが廃止されました。その代わりにAD問題で部分点が付与されるようになりました。

## コース受講前のスキル
PEN-200コース受講前の私のスキルはおおよそ以下の通りでした。Windowsマシンの知識があまり無い状態からのスタートでした。
* HackTheBox
    * Linux：easy問題の約半数がノーヒントで解け、約半数はフォーラム見ながらなら解けるレベル
    * Windows：easy問題に手も足も出ないレベル
* 資格試験
    * 情報安全確保支援士試験 合格

## OSCP vs HackTheBox
OSCPを受験しようか迷っている方は「OSCPはどれくらいの難易度なのか？」という点が気になるかと思います。私の所感にはなりますが、HackTheBoxのeasyマシンとOSCPのラボマシンを比較すると以下のような印象を受けました。
* 発見した脆弱性を突く難易度
    * HackTheBox > OSCP
* 脆弱性を発見する難易度
    * OSCP > HackTheBox

総じて問題の難しさの傾向が違うという印象です。そのためHackTheBoxのeasy問題が解けなかったとしても悲観することはなく、思い切ってOSCPに挑戦してよいかなと思います。

## 受講期間の準備
90日コースで受講を開始しました。

約40日ほどで教科書と付属のExerciseを完了させ、約50日ほどでChallenge Lab 0~6を攻略し試験の準備をしました。これらを進める中で自身が知らなかったことについてはNotionでメモをとり、それをそのまま試験時のCheat Sheetとして活用しました。

ExcerciseやChallenge Lab攻略については公式のフォローも手厚く、公式Discordの情報を参考にすれば手詰まりになるということは無いかなと思います。またChallenge Lab 3 (Skylark) については試験から逸脱した難易度とされていますが、学びになる部分も非常に多いため、Discordの情報を参考にしながらでも攻略することを推奨します。

OSCP対策としてよく挙げられる[TJ Null List](https://docs.google.com/spreadsheets/u/0/d/1dwSMIAPIam0PuRBkCiDI88pU3yzrqqHkDtBngUHNCw8/htmlview?pli=1) や [Proving Grounds](https://www.offsec.com/labs/individual/)については取り組んでいません。

## 試験とレポート
午前10時から試験を開始し、約12時間で合格点の70点に達しました。
その後数時間ほど粘りましたがそれ以上攻略の糸口が見つからなかったため諦めてレポートの準備に取り掛かることにしました。
約6時間ほど睡眠をとった後に再開し、最後にレポート用のスクリーンショットに不足がないかを確認しつつレポートの下準備をしました。翌日9:45に試験を終了しました。

レポートについてはのんびり書き、23:00ごろに書き終えて提出しました。実働としては4~5時間程度でした。

試験中のメモはObsidianで取り、レポートについてはObsidian+pandocで作成しました。

## 合格通知
レポート提出から約3日後に合格通知が届きました。レポートが届くまでの間は非常にそわそわし、RedditでOSCP合格の記事を読み漁っていました。

## 今後の目標
次はOSEPかOSEDを取りたいです。

## 終わりに
本記事では主にOSCPの受験記や難易度感を記載しました。これらの情報が今後受験する方の参考になりましたら幸いです。

OSCPはこれまで受けた資格試験の中でもダントツで面白い試験でした。教材や公式のフォローも充実しており学習が進めやすい点も好印象でした。またラボマシンも充実しており、得たスキルをすぐに実践できるためスキル習得の面でも非常に有用でした。

OSCPを受験しようか迷っている人・事前準備が足りていないのではないかと尻込みしている人も思い切って挑戦してみることをお勧めします。

最後まで読んでいただき、ありがとうございました。
[C言語①] hello worldを記述しよう

C言語を学修するとき、一番最初に取り組むのがHello Worldでしょう.  ここでは、Hello Worldを記述する方法と解説をしていきます.
※初心者向けの記事なので、ある程度Cを使える方は別の記事を参照ください.

プログラム例: Hello World
~~~C:HelloWorld.c
#include <stdio.h>
int main(void)
{
    printf("Hello World\n");
    return 0;
}
~~~
これがHello Worldの例文です.  このように記述することで、Hello Worldを出力することができます.

[ 解説 ]
(1) `#include <stdio.h>`
標準入出力（Standard Input/Output）を扱う関数を使用するためのヘッダーファイルをインクルードします。これにより、`printf` 関数などが使用可能になります。
#includeを使うことで、普段使うファイルを挿入することができ、コードを記述する手間が省けます.
‹stdio.h›はStandard-ioと呼ばれ、#includeによって挿入されるファイルの一つで、最もポピュラーなものです.  今回は‹stdio.h›を使いましょう.

(2) `int`
`main` 関数の戻り値の型を指定しています。`int` は整数型を表し、プログラムの終了ステータスを示すために使用されます。
関数とは、引数を処理する過程のことです.  数学でy=x+2という関数がありますが、これはx(引数)に+2の計算をしてy(出力)に返すという意味になりますよね.  ここにおける計算処理をするために関数を記述します.

(3) `main(void)`
プログラムのエントリーポイントである `main` 関数を定義しています。`void` は引数がないことを示しています。
今回はmainプログラムのみを使います.
また、関数には(2)で解説したように、引数が必要です.  今回は引数を使わないので、(void)と入力しましょう.

(4) 本文の決まり
以上が関数定義です.
ここまで来てようやくプログラムの本文を記述することができます.  本文は{}で囲むことによって周りと区別されます.
また、本文の文末には必ず;を付けましょう.  これにより一つの指令の記述が終わったことを示します.

(5) `printf`
フォーマットされた文字列を標準出力に表示する関数です。`"Hello World\n"` のようにダブルクォーテーションで囲まれた部分が表示されます。`\n` は改行を意味します。
()の中に表示したい内容を記述しましょう.
""に囲まれた内容が文字列データとして扱われます.  ""を使う理由は、()内に文字列データでない変数を使うことがあるためです.  ここは次の記事で改めて解説します.
\nは改行の意味を持ちます.
~~~C:\nあり
#include <stdio.h>
int main(void)
{
    printf("Hello World\n");
    printf("See You");
    return 0;
}
~~~
\nがあるこのプログラムを実行すると
Hello World
See You
と出力されますが、
~~~C:\nなし
#include <stdio.h>
int main(void)
{
    printf("Hello World");
    printf("See You");
    return 0;
}
~~~
\nがないこのプログラムを実行すると
Hello WorldSee You
と出力されます.
今回は改行する必要がありませんが、今後多用することになると思うので覚えておきましょう.

(6) `return 0;`
プログラムが正常に終了したことをオペレーティングシステムに伝えます。`0` は正常終了を示す一般的な値です。
これがないと本文が終了されていない不完全なファイルとしてコンパイラされないので気を付けましょう.

解説は以上です.  長々と書いてしまいましたが、覚えてしまえば内容は簡単なのでこのページだけで理解できると思います.
[C言語]リストはCの初歩的な内容を扱うので、プログラミング初心者の方はぜひ参考になさってください.
Pendo Aggregation APIのVSCode拡張作った

# Pendo Aggregation
PendoのAggregation APIは、Pendoデータにアクセスして処理するためのクエリ言語です。このAPIを使用すると、収集されたイベントデータに対して、MongoDBに似たクエリ言語を使用して構造化されたデータを取得できます。

Aggregation APIは、Pendo UI上で見れるデータをほぼすべて取得できます(一部制限あり）。PendoアプリもバックエンドではAggregation APIを利用しています。

Aggregation API
https://engageapi.pendo.io/#7c8479b8-3843-403c-94a9-04cbdf542db9

私は日々お客様にAggreagation クエリを提供したり、Pendo社内のデータを取得加工するのに利用しています。

Aggregation APIを実行する上で結構重要なポイントは、[イベントソース](https://engageapi.pendo.io/#fba64dda-4e1d-4822-8334-b2e61345a8b3)からほしいフィールドだけに絞ってクエリを実行することです。

フィールドを絞らずにクエリを実行すると処理に時間がかかり応答がなかなか返ってきません。
５分を超える処理実行はタイムアウトしてキャンセルされてしまうこともあります。

(瞬時に数十万のレコード返せるすごい処理能力を要しているのでそんな滅多なことではタイムアウトしませんが）

処理時間が短いに越したことはないので、select句を使ってほしいフィールドだけに絞って実行を心がけています。

![CleanShotIGuDEwwx@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227518/f6419045-ee2b-f83c-b3f3-37363e02fc5a.png)

さぁ、ここで問題発生。

各ソースのフィールドってドキュメント化されていないんです。

あえてドキュメント化されていないようなんですが、これだと毎回selectなしで一回クエリ実行してほしいフィールドを確認してからクエリを書き直すという作業が発生します。

どこかにまとめておけばいいけど、毎回そのファイル見に行くのもめんどくさい。

できればIDE(Vscode)を離れずにドキュメントを参照できるようにしたい。

そこでVscode拡張を作ってしまえということで作りました。

**注意：よく使用されるフィールドだけ抽出しています。完璧なリストはではない点ご留意ください。足りない項目あればGithubまでご連絡ください。**

機能：
1. vscodeコマンドagglookup: showでソースをクイック参照
2. ファイルないにかかれているソース名をマウスホバーでフィールドのクイック参照

https://github.com/Band-Aid/agglookup

スクショ
![CleanShotFLi32uvu.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227518/121a965a-401a-f072-2ec9-ec02eef7d6ee.gif)

ストアに公開していないので、ご自身でビルドして、インストールする必要がありますが、よろしければ使ってみてください！

**追記：**
インストール用のvsixファイルを作りました。
githubのリリースにあげています。install vsixからインストールしてご利用ください
Pythonのlru_cacheを使用した関数処理時間の改善

# はじめに
同じ引数で何度も呼び出される関数がある場合、計算結果をキャッシュすることでパフォーマンスを改善できる可能性があります。
本記事では、Pythonの標準ライブラリfunctoolsモジュールに含まれる `lru_cache` を使用し実装例を紹介します。

# 環境
Python 3.12.4

# lru_cacheの使い方

`@lru_cache (maxsize=None)` というデコレータを関数の直前に付けるだけで、その関数の結果がキャッシュされます。maxsizeパラメータは、キャッシュするアイテムの最大数を指定します。Noneを指定すると、キャッシュサイズに制限がなくなります。

```python
from functools import lru_cache

@lru_cache(maxsize=None)
def hoge_calculation(n):
    # 時間のかかる計算をシミュレート
    result = 0
    for i in range(n):
        result += i * i
    return result
```


# 使用例

重たい処理に対して lru_cache を使用した場合と使用しない場合の違いを見てみます。
関数を10000回呼び出してみて実行時間を比較します。


```python
import time
from functools import lru_cache

# 時間のかかる計算をシミュレート（キャッシュなし）
def sample_calculation(n):
    result = 0
    for i in range(n):
        result += i * i
    return result


# 時間のかかる計算をシミュレート（キャッシュあり）
@lru_cache(maxsize=None)
def cached_calculation(n):
    return sample_calculation(n)


# 処理時間を計測
def measure_time(func, n, iterations):
    start = time.time()
    # 10000回呼び出し
    for _ in range(iterations):
        func(n)
    end = time.time()

    print(f"{func.__name__}: {iterations} 回呼び出し完了")
    print(f"Total execution time: {end - start:.8f} seconds")
    print(f"Average time per call: {(end - start) / iterations:.12f} seconds")


# キャッシュなしで10000回呼び出し
print("\n--- キャッシュなし ---\n")
measure_time(sample_calculation, 1000, 10000)


# キャッシュありで10000回呼び出し
print("\n--- キャッシュあり ---\n")
measure_time(cached_calculation, 1000, 10000)
```

# 実行結果

キャッシュなしとありで違いを見てみます。
合計処理時間と1回あたりの処理時間は次のようになりました。


```
--- キャッシュなし ---
sample_calculation: 10000 回呼び出し完了
Total execution time: 0.32430840 seconds
Average time per call: 0.000032430840 seconds

--- キャッシュあり ---

cached_calculation: 10000 回呼び出し完了
Total execution time: 0.00099969 seconds
Average time per call: 0.000000099969 seconds
```

キャッシュなしの場合は10000回の呼び出しに約0.32秒（1回あたり約0.000032秒）かかっているのに対し、キャッシュありの場合は同じ10000回の呼び出しが約0.001秒（1回あたり約0.0000001秒）で完了しています。lru_cacheを使用することで処理時間が改善されたことを確認できました。
kaggle tutrial bonus part1

https://www.kaggle.com/code/ryanholbrook/create-your-first-submission

は、実際にsubmitしてみようぜ！という部分です。computer vision tutorial に追加で記載されているので、画像認識コンペの１つとなっています。ここまでのtutorialを読めば、モデルの部分を理解できることになります。kerasとgoogle TPUが前提となるので、その部分を理解するtutirialでしょう。筆者はTPUについて詳しくないので、解説のポイントをはずしているかもしれません。とりあえず、日本語訳や私の解説をできるだけ載せておきます。


TPUはGPUが８個ある環境に抽象化できます。すると、一般的なGPU1つのように全てのtaskをGPUに任せるのではなく、あるGPUにはtask1,別のGPUにはtask2というふうに作業を割り振る必要が出てきます。

# Distribution Strategy
人間が仕事を割り振ることはなく、この点についてもkeras(tensotflow)はよしなにしてくれます。我々は、いくつかの宣言をcodeすることが必要です。

```
# Detect TPU, return appropriate distribution strategy
try:
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver() 
    print('Running on TPU ', tpu.master())
except ValueError:
    tpu = None

if tpu:
    tf.config.experimental_connect_to_cluster(tpu)
    tf.tpu.experimental.initialize_tpu_system(tpu)
    strategy = tf.distribute.experimental.TPUStrategy(tpu)
else:
    strategy = tf.distribute.get_strategy() 

print("REPLICAS: ", strategy.num_replicas_in_sync)
```
上のところは意味を理解するのが少し面倒ですが、一般に使いまわせるのであまり気にする必要はありません。

tpu = tf.distribute.cluster_resolver.TPUClusterResolver() 
TPUの場所を確認。TPUが割り当てられていればTPU リソースへの接続情報を表すオブジェクトをtpuという変数に押し込めます。

ここからは正常系のみを確認します。


tf.config.experimental_connect_to_cluster(tpu)
TensorFlow が TPU を使用できるように、ランタイムを TPU クラスタに接続します。

tf.tpu.experimental.initialize_tpu_system(tpu)
TPU を使用する前に、必要な初期化処理を実行します。

strategy = tf.distribute.experimental.TPUStrategy(tpu)
モデルの訓練を複数の TPU コアに分散させることで、高速化を図ります。

何個のGPUに分散されているかを確認するために最後printしています。

個人的に知らなかった部分
tf.distribute.MirroredStrategy
単一マシン上の複数の GPU で同期的に訓練を行うための戦略

tf.distribute.MultiWorkerMirroredStrategy
複数マシン上の複数の GPU で同期的に訓練を行うための戦略

など、他の戦略を調べてみると出てきました。
tf.distribute.MirroredStrategyは１度目にしたことがありましたが他にもいろいろあるのですね。


```
with strategy.scope():
　#モデルを定義
```
とすることで、訓練が勝手にTPUで行われることになります。
そのほか出てくる多くの関数は基本的に過去のtutorial上で学んでいることとなります。
TPUとGPUでは性能の特性や取り扱いに違いが生じたり、面倒になることもありますが、１けた（１０倍くらい）TPUの方が早い印象です。(GPU,TPUのバージョンなどで大きく変わってきます)。もし使えるのであればTPUを利用する方が価格あたりの性能が良いでしょう。
【勉強記録】ポモドーロ勉強法

# はじめに
こんにちは！アメリカで独学でソフトウェアエンジニアを目指しているものです。
本日はとても有名で皆さんも知っているかもしれませんが、私が最近採用しているポモドーロ勉強法がとてもいいということで簡単に紹介していきたいと思います。
個人差もあると思いますが、私はとても効率的な勉強ができるようになったと思ったのでぜひ参考にしてもらえればと思います

## ポモドーロ勉強法とは
ポモドーロ勉強法とは25分間やって5分休憩というサイクルを繰り返す勉強法です。以下がその流れです
1. 25分勉強 + 5分休憩を1セットと考える

2. 4回（または5回）繰り返したら30分の長めの休憩を取る

25分勉強 → 5分休憩を4回（合計2時間分）行った後は、30分ほどの長めの休憩を取ります。
長い休憩で、脳と身体をしっかりリフレッシュしましょう。
3. タイマーを使う

時間を測る際には、キッチンタイマーやスマホアプリなどを活用するのがおすすめです。
タイマーが鳴ったら「必ず」休憩に入り、休憩時間が終わったら再び勉強をスタートする、というルールを守るのがポイント。

私はモニターが3つあるので1つに以下のサイトのやつを使っています

https://www.oh-benri-tools.com/tools/time/pomodoro

時間の通知音を好きな音に設定できますが、私はチャイム音がおすすめ。日本人はチャイム音に慣れているので、鳴ると自然に机に向かうスイッチが入る気がします！

### メリット
1. 集中力の維持・向上
  25分という短い時間に集中することで、タスクへの没頭がしやすくなります。
  休憩をはさむことで疲れが溜まりにくく、長時間でもパフォーマンスを維持しやすいです。
  同じ8時間の勉強でも疲労度が全然違います。
2. 時間の見える化
  「あと○分だけ頑張れば休憩が来る」と思うと、モチベーションが高まりやすいです。
  タスクにかけている時間を把握しやすく、学習進捗を客観的にとらえるのに役立ちます。
  特に独学の場合はこういった小さなステップがあるととても楽しく勉強ができます
3. 達成感が得やすい
  1ポモドーロごとに達成感が生まれ、勉強へのモチベーションが上がります。
  作業を細切れにしてこなすことで、タスクが大きくても「進んでいる」という実感が持てます。

デメリットとしては、25分が合わずもっと長く(45分とか)したい方や短くしたい方(15分)もいると思うので、1サイクルの時間を調整する必要があります


## 私の勉強スケジュール(平日)
こちらは私の勉強スケジュールです。
* 8:00 起床
* 8:00~9:00 朝ごはん& 自由タイム
* 9:00~11:00 新しい内容の勉強(現在はRuby on rails)
* 11:00~12:00 英語の勉強(リスニングとスピーキング)
* 12:00~13:00 お昼ご飯
* 13:00~14:00 新しい内容の勉強(現在はRuby on rails)
* 14:00~16:00 アウトプット(現在はrubyのコーディング)
* 16:00~17:00 筋トレ (リフレッシュのため)
* 17:00~18:30 軽めのインプット(webやインターネットなど)
* 18:30~19:30 料理作る & 食べる
* 19:30~21:00 アウトプット(現在はrubyのコーディング)
* 21:00~ ブログ書いたり、明日の計画練ったり、全体の計画を見直したりなど

このスケジュールで、最低8時間は勉強できます。
ここで私が意識しているのは、2.5時間程度（5セット）続けたら、しっかり休む・科目を変える・英語や筋トレなど別の活動をするといったように、自然に切り替えができるよう時間割を組むことです。

また、これは8時に起きた場合の例ですが、仮に9時や10時に起きたとしても、罪悪感に襲われないようバリエーションを用意しています。たとえば、筋トレや英語の時間を削ってでも、同じくらいの勉強時間を確保できるようにしているんです。

とはいえ、実は今日、5:00に起きる用事があって、それが終わってから13:00まで寝てしまい、起きたときは少し絶望しました（笑）。しかし、そこで自分を責めずに勉強を継続することのほうが大切だと考え、できる範囲でしっかり切り替えて勉強を行いました。

# まとめ
本日はポモドーロ勉強法について紹介しました。
こうして見てみると、決して達成できない量の勉強ではないように感じませんか？
未経験からエンジニアを目指すにあたり、このスケジュールで続ければ、約125日、つまり半年あれば相当な量をこなせると思います。
集中力が続かない方は、ぜひ一度ポモドーロ勉強法を取り入れてみてください！
【Google Cloud】Associate Cloud Engineer試験体験記

# まえがき
おつかれさまです。mochiです。
今回は、Google CloudのAssociate Cloud Engineer(ACE)資格試験に合格したため、それまでの準備期間や本試験時の所感等を皆様に共有できたらと思います。
# Google Cloud ACE試験とは
ACEは、Google Cloudの基本的な実装や各種サービスの総合的な理解度をチェックする認定資格です。範囲はかなり広いものになっており、Compute engineやCloud Storage、Cloud Spannerだけにとどまらず、Pub/Sub、GKE等一通りのサービスを理解しないと、合格はできないと思います。
認定資格の公式サイトから、詳細な試験ガイドを確認することが出来ます。

時間: 2 時間
登録料: $125（税別）
言語: 英語、日本語、スペイン語、ポルトガル語
試験の形式: 50 ～ 60 問の多肢選択（複数選択）式 ※50問でした。

試験の実施方法としては、他のベンダー試験と同様で試験会場に赴くオンサイト試験か自宅から実施できるリモート試験かを選択することが出来ます。

ACE資格の再認定は、認定を得た日から3年間有効です。

https://cloud.google.com/learn/certification/cloud-engineer?hl=ja

# 試験準備に使用した教材
### Google公式の模擬試験
こちらを使用して、自分の中での理解度をチェックすることが出来ました。
問題数は20問と少ないですが、実際の試験に近い形式で問題を何度でも解くことが出来ますので、非常におすすめです。

https://docs.google.com/forms/d/e/1FAIpQLSc7bkUHpDbFShBI5xE4u8OO2vl99DrP0htnswa-la9DQynToA/viewform?hl=ja
### 【Udemy】Google Cloud Associate Cloud Engineer模擬問題集
こちらの問題集を購入し、何周もして間違えた解答の意味まで、しっかりと理解をするようにしました。私はCloud Digital Leaderの資格を取得していることもあり、特に参考書等によるインプットは行いませんでした。

https://www.udemy.com/course/gcp-ace-mogi/?couponCode=KEEPLEARNING

# 本試験の体感
本試験では、かなり問題の難しさを感じました。やはり、コンピューティングやストレージ、DBやKubernetesに関する網羅的な知識と、それらのサービスを使用して会社の複雑な要件に対応するにはどう活用すべきかを問われるような問題が多かったです。

単純にサービス名を問われるような問題は1問も出題されませんでした。
体感、Udemyの問題集からの出題は半分程度だったでしょうか。残りは時間使って何度も見直しして、かろうじて受かったような感じです笑

クラウドの知識だけではなく、IPアドレスの基礎的な知識やブルーグリーンデプロイメント、カナリアデプロイなどのUX向上に関する知識も無いと問題が解けません。また、gcloudやkubectl、gsutilなどのコマンドに関する問題も頻出しました。そのため、要件に応じて適切なコマンドを使用できるように理解しておく必要があります。

合格に近づくには、とにかく問題を解くこととGoogle推奨の各ベストプラクティスについてしっかりと抑えておくことを強くお勧めします。

# あとがき
ここまでお読み頂きありがとうございます。
今回なんとか資格試験に1発合格できましたが、正直危なかったです笑
クラウドの資格試験は毎回危ないですが、合格さえできればオールオッケーです！！
これからACE試験を受けようと考えている方に、この記事が少しでも役立つことができれば、非常に幸いです。
2024年、ありがとうございました。
来年もよろしくお願い致します。
React Profilerコンポーネントでレンダリング時間を計測してみる

# はじめに
本記事は、Profilerを触ってみたものを備忘録としてまとめたものになります。React Profilerコンポーネントを使って対象のコンポーネントのパフォーマンス情報を取得する処理を実装をしていきます。

# Profiler

React の `Profiler` は、コンポーネントのパフォーマンスを測定できる便利なツールです。
`Profiler`を使用した簡単なコンポーネントを作ってみます。

```jsx
import { Profiler } from 'react';

function SampleComponent() {
  const onRenderCallback = (
    id,             // 測定対象のコンポーネントを識別するための一意の名前
    phase,          // "mount" か "update"
    actualDuration  // レンダリングにかかった時間
  ) => {
    console.log(`${id}の${phase}にかかった時間: ${actualDuration}ms`);
  };

  return (
    <Profiler id="SampleComponent" onRender={onRenderCallback}>
      {/* 測定したいコンポーネントをここに */}
    </Profiler>
  );
}
```

上記の場合取得できる情報は次の通りです。

- id:対象のコンポーネントを一意に識別するID
- phase: "mount"（初回レンダリング）か"update"（再レンダリング）
- actualDuration: レンダリングにかかった時間（ミリ秒）


# コンポーネントのパフォーマンスを計測してみる

意図的に重い処理を含むコンポーネントを作成し、Profilerでパフォーマンスを計測してみます。

```jsx
import { Profiler, useState } from 'react';

// サンプルデータ用の配列
const sampleFoods = ['寿司', 'ラーメン', 'カレー', 'ピザ', '天ぷら'];
const sampleSports = ['サッカー', '野球', 'バスケ', 'テニス', '水泳'];

// サンプルデータ生成
const generateItems = (count) => Array.from({ length: count }, (_, i) => ({
  id: Math.random().toString() + `_${i}`,
  firstName: `名前${i}`,
  lastName: `苗字${i}`,
  favoriteFood: sampleFoods[i % sampleFoods.length],
  favoriteSport: sampleSports[i % sampleSports.length],
  email: `email${i}@example.com`
}));

// 重い処理のシミュレート用関数
const heavyProcess = (text) => {
  let sum = 0;
  for (let i = 0; i < 1000000; i++) {
    sum += i;
  }
  const [displayText] = [`${text}`, sum];
  return displayText;
};

function SampleList({ items }) {
  const processedItems = items.map(item => ({
    ...item,
    displayName: heavyProcess(`${item.firstName} ${item.lastName}`),
    interests: heavyProcess(`好きな食べ物: ${item.favoriteFood}、好きなスポーツ: ${item.favoriteSport}`),
  }));

  // レンダリング時の処理時間を表示
  const onRenderCallback = (id, phase, actualDuration) => {
    console.log(`${id}の${phase}フェーズ: ${actualDuration.toFixed(1)}ms`);
  };

  return (
    <Profiler id="SampleList" onRender={onRenderCallback}>
      <div className="list">
        {processedItems.map(item => (
          <div key={item.id} className="item">
            <h3>{item.displayName}</h3>
            <p>{item.interests}</p>
            <p>{item.email}</p>
          </div>
        ))}
      </div>
    </Profiler>
  );
}

export default function App() {
  const [items] = useState(() => generateItems(200));
  return <SampleList items={items} />;
}
```

上記のソースでサーバを立ち上げて、初回レンダリングと再レンダリングを実行してみます。
ブラウザの開発者ツールから確認したログは下記の通りです。

```:出力ログ
SampleListのmountフェーズ: 6.3ms
SampleListのupdateフェーズ: 2.9ms
```

Profilerを使うことで、mountフェーズ（初回レンダリング）とupdateフェーズ（再レンダリング）の処理時間が計測できました。
エンジニア向けFigma入門

# まずはプロトタイプをつくる
自社の引用で恐縮ではありますが、以下のアドベントカレンダーの記事を見て、いい学びだなと思いました。
と同時に、「紙芝居つくる」って意外と難しいよな🤔とも思います。

https://qiita.com/mh-2568/items/b2ace112a6fe645de623

既存の画面があれば、大体developer toolで要素を調整してキャプチャ撮って貼ると思うのですが、その後修正が必要になったときにまたイチからいじるのは面倒なんですよね・・・。
「紙芝居つくる」となって真っ先に選ばれるのはGoogleスライドなのですが、今回はFigmaも使ってみたら便利だったよ、という紹介です。

https://www.figma.com/

デザイナーが使うもの、と思っていたら大間違い！
エンジニアの私が実際に1年くらい使ってみた経験から、「ガッツリ使う派」ではなく「ちょこっと使う派」向けのTipsをまとめます。

※逆に言うと、「デザイナーならそんな使い方はしないわ」というのも絶対ある。

# とりあえず「デザインファイルを新規作成」
これ押すだけです。
![2024-12-13_16h56_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118888/b750053e-364b-1f98-dcbf-a0e1649f023a.png)

# フレームをつくりましょう
スマホやデスクトップのサイズがあるので、使うものを選びましょう。
![2024-12-21_13h38_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118888/52c2e2bc-22ad-48a0-7ee8-403eb8caf68b.png)

# 既存機能のキャプチャを用意しましょう
1. すでに参考にする機能がある場合は、キャプチャをコピペして貼ります。適当にフレーム外に貼っておけばOKです。
![2024-12-21_13h41_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118888/084bcb89-2260-efd6-190c-7c758ba51d7e.png)
　
1. 別パターンのログインフォームを作る（ことはあまりないですが）ことを仮定して、図形を置いていきます。
よく使う色は、ライブラリに登録すると呼び出せて便利です。
色はスポイトでキャプチャから取ってきましょう
![2024-12-21_13h49_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118888/f0cf44b0-a949-cb74-06b0-31f42ebdfd5d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118888/0ae9d075-504e-9d86-d162-a1a194d373c5.png)
横型のログインフォームを作ってみました。

# よく使うキーボードショートカット
これだけ使えれば簡単なものは問題なく作れると思います。
* 図形をコピー：Shift＋Alt＋ドラッグ（パワポだとAlt→Ctrlなのでちょっとややこしい）
* 縦横そろえながら図形を移動：Shift＋ドラッグ
* 図形の選択：Ctrl＋ドラッグ
* 横スクロール：Shift＋スクロール（ブラウザと一緒）
* 拡大縮小：Ctrl＋スクロール（ブラウザと一緒）

# Googleスライドでよくない！？
はい、大丈夫です！！！！
ただ、一回作ってしまえば色の使いまわしや変更、要素をコピーして追加する、というようなところの柔軟性はあるので、変更が生じるプロトタイプにはオススメです。
地味に、縦横をそろえたり拡大縮小したりがGoogleスライドでは操作に限界があるので、めっちゃ拡大できるのはよかったです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118888/f1dfe15e-b80e-67a1-3349-bf0e961d1225.png)
あなたのキーボード、割ってみませんか？

この記事は [株式会社うるる（ULURU）Advent Calendar 2024](https://qiita.com/advent-calendar/2024/uluru) の22日目の記事です。

# はじめに
株式会社うるるのえんフォト事業部でバックエンドエンジニアやってる植木です！
年末ということで今年の振り返りをしようと思ったのですが、今年導入してとても良かったと感じているアレがあるなぁ〜と思い出したので共有します:v:

# 左右分離型キーボードという世界
ずばりこんな感じです↓↓
![スクリーンショット 2024-12-21 10.42.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839327/6756356b-13ce-b8ac-38c0-525402f5eeff.png)

私が使っているものは[Keyball61](https://shop.yushakobo.jp/products/5358?srsltid=AfmBOoq2z0VxGR73syZgcUI-5JcAPYIK4B14F_nEy61EQwm-HZfL85NV)というもので、右側にトラックボールが付いているものです。
「分割キーボード」等で検索するといろんなパターンのキーボードが出てきます。

# 何がそんなに良かったの？
### その１「<font color="HotPink">肩こりに悩むことが減った</font>」
普通のキーボードって手を前に揃える必要があるので、無意識に肩が内に入りがちです。
ずっとその状態をキープするのは辛いですが、分割キーボードは左右に広げて配置することができます。

実際の私の環境はこんな感じです。（配線が汚いとか言わないでください...）
![20241221_095338.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839327/36a1889b-fd02-2393-da49-c402528eee44.jpeg)
かなり肩がリラックスした状態で仕事できます。

### その２「<font color="HotPink">右手の移動がなくなった</font>」
これはトラックボール付きのキーボードの利点です。
ずっと文字を打っているなら特に困らないですが、普通右手がマウスとキーボードで行ったり来たりしますよね。
Keyballに乗り換えてから気づいたのですが、これが意外と無駄動作だったりします。
常にホームポジションに指をおいたまま文字入力とマウス操作ができます。

### その３「<font color="HotPink">プロファイルのカスタマイズができる</font>」
KeyballにはRemapというキー配置をカスタムできるツールに対応したファームウェアを入れることができます。
特定のキーが押されたときの動作をカスタムすることで自分好みのキーマップにしています。

またレイヤー機能もあり、全てのキー配置をレイヤーごとに全く別のものにすることもできます。
例えば、私の使い方だと以下のようなイメージです。
| レイヤー番号 | キーマップの用途 |
|:-----------|:------------|
| 1       | 通常のQwerty配列で文字打ち用        |
| 2     | ショートカットを詰め込んで各キーに配置      |
| 3      | マウス操作用（クリックなどをキーに配置）        |
| 4       | Notionショートカット用          |

特定のキーを長押ししている間、これらレイヤーを切り替えるようにしています。


##### Remap参考
https://suzuki-navi.hatenablog.com/entry/2023/12/17/232540

# 注意点と辛いこと
### 1. <font color="SkyBlue">自作（電子工作）です</font>
はんだごてを使ってパーツを組み立てます。
失敗したら自己責任で、直すのも自分です。
私も無事つまづきましたが頑張って完成させました:thumbsup:
公式ドキュメントが結構しっかりしているので、それだけが救いです。

https://github.com/Yowkees/keyball/blob/main/keyball61/doc/rev1/buildguide_jp.md

### 2. <font color="SkyBlue">慣れるのに時間がかかるかも</font>
最初は違和感だらけでした。

1\. 腕を広げて操作すること
2\. トラックボール初心者
3\. キーが縦に直列なので、最初はTypoが結構多い

慣れれば問題ないんですけどね！

# おわりに
いかがでしょうか？
今の考えているのは、オフィス用にもうちょっと小さいKeyballを作ろうかな？です。
Remapを使わずにファームウェアレベルでカスタムできるらしいので、それも興味あります。

明日のアドカレは@yukou-isshikiさんです！
BtoBマーケティングにおけるカテゴリーの重要性

## 初めに

外資就活ドットコムのBtoBマーケの比嘉と申します。

私自身は中途でハウテレビジョンに入社し、外資就活ドットコムを企業に広めていく施策を行なっております。

前職はとあるコンサルで働いており、新規顧客獲得のための企画等もしておりました。

その際のターゲットは経営者でした。現在は人事の方で全くターゲットも異なります。

そこの違いから、悩みながら走ってきた１年の振り返り、見えてきたBtoBマーケにおけるカテゴリーの重要性と次年度に向けた取り組みを共有したいと思います。

## BtoBにおけるカテゴリーの重要性

ここでいう**カテゴリー＝「〇〇なら△△」**と何を探しているときの第一想起に上がるものです。

例を挙げると、「動画ならYouTube」「ECサイトならAmazon**」**のような形です。

特定のカテゴリーで１番のポジションを取ることがマーケティングでは重要ですが、特にターゲットが法人となるBtoBでは高いように思います。

中途入社して様々なイベントに参加したり、書籍やセミナーでも勉強しましたが、結局はここが一番重要な要素だと感じました。

人材業界でも「理系採用なら〇〇」「体育会採用なら〇〇」「エンジニア採用なら〇〇」のように専門店化している企業が企業からも学生からも選ばれている傾向にあると思います。

弊社ではどうなっているかというと

学生には「外資系企業に就職するなら外資就活ドットコム」というカテゴリーで一定の知名度ができており、チャレンジングな学生に毎年利用いただいております。

結果として登録いただいている学生は難関大や海外大生が多く、TOEICスコアが高い、開発経験がある、長期インターン経験等の自分が就職活動をしていたころや前職でもあまり見たことのない多くの優秀な方に支持いただいており、これを踏まえてもカテゴリーで。

企業にも同様で、比較的外資系には一定の知名度が獲得できております。一方でその他の大手企業の方含めた日系の企業にはまだまだ知名度が低いです。

上記の学生の中には外資系企業以外にも、日系企業に行きたい学生も多くいます。

そのような外資系以外の日本のTOP企業もしくは急成長中の企業をもっと優秀な学生に知らせていいきたいと考えております。

優秀な学生に選ばれているものの、急成長企業や様々な業種の日本のTOP企業にはまだまだ認知されていないというのが現状です。

## 外資就活が狙いたいカテゴリー

多くの企業が課題として「もっと優秀な学生を採用したい」共通で持っているかと思います。

外資系というイメージのみならず、「優秀学生の採用なら外資就活ドットコム」のような「優秀な学生」「TOP学生」といったカテゴリーあるいは新しく使われるようなカテゴリーを創出し、トップを狙うことが必要です。

これが弊社におけるBtoBマーケティングを行う上でのミッションだと感じております。

## 今期の施策

今期は「もっと優秀な学生を採用したい人事の方に外資就活ドットコムを知っていただく」をテーマに、セミナー等のコンテンツ発信や、イベントへの出展や協賛、また自社でのイベント開催を行ってきました。

一貫して優秀学生×採用に限定し、学生の特徴や傾向、採用するためのアプローチ事例、優秀層を採用する上での考え方をお伝えしています。

特に自社でのイベントでは濃いコミュニケーションが弊社と人事の方はもちろん、人事の方同士で生まれ、満足度が高く、なかなかお会いできなかった企業にも会うことができました。

採用ターゲットによって施策が変わるため、一般的にWEBや書籍で見つけられる情報でなく、

優秀層に特化した採用戦略が学べる、情報交換できる場の提供は人事にとって価値があると実感しました。

## 来期に向けて

今年走ってみて、改めて「優秀な人材とは？」と考えることが多く、各企業にとっても考え方が異なるように感じます。

語学力や資格、技術力等の見えやすいスキルを除いて、一貫しているのは「素直さ」「思考力」「ロジカルなコミュニケーション能力（＋エネルギー）のような印象です。

これらのスキル面に加え「業界や職種への志望度」も判断要素になってくるかと思います。

これらを可視化させるような取り組みを行い、人事の方に届けていければと思います。

外資就活ドットコムが優秀層採用に一番詳しいというイメージを残せるように、リアルとWEBの両面で発信していく予定です。

## 最後に

外資就活ドットコムでのBtoBマーケティングは、一般的なBtoBマーケティングと異なり、ABM（Accound Based Marketing）に近く、難しさを感じております。

単にBtoBではなく、学生の部分であるBtoCも絡む人材業界なので余計にそう感じます。

しかしそれが面白さであり、役割にとらわれず、社内でも社外でも色々な部署や人と施策を進めていけるのはハウテレビジョンだからこそだと思います。

来期はより気合いを入れて、個人的にも顧客的にも面白い施策を進めていければと思います。
kaggle tutorial cpmputer vision part 6

https://www.kaggle.com/code/ryanholbrook/data-augmentation

の解説です。
一般に、訓練するデータの数とネットワークを大きくすると性能は上がり続けます。
しかし、訓練するデータは足りず、ネットワークを大きくするには計算資源が足りません。訓練するデータを増やすために、元データを使いまわせたら(data augmentation)、ということを考えていきます。
斜めにする、一部切り抜き、裏返す、色を変えてみる・・・などさまざまな処理をすることでとりあえずデータを増やすことができます。性能が下がるのでは？と思いますが、実際やってみると、汎化性能も上昇するのでとりあえず一度データが足りていてもやってみるのもありかもしれません。


# 訓練データの読み込み
```
Load training and validation sets
ds_train_ = image_dataset_from_directory(
    '../input/car-or-truck/train',
    labels='inferred',
    label_mode='binary',
    image_size=[128, 128],
    interpolation='nearest',
    batch_size=64,
    shuffle=True,
)
```
'../input/car-or-truck/train':
訓練用画像データが格納されているディレクトリのパスを指定

labels='inferred':
ラベルをディレクトリ名から指定。例えば、train ディレクトリ内のサブディレクトリ名（例えば car と truck）が、そのままクラスラベルとして使用されます。

label_mode='binary':
ラベルを二値の形式でエンコードするように指定。

interpolation='nearest':
最近傍補間：最も近いピクセルの値を使って新しいピクセルの値を決定する。

shuffle=True:
データセットを読み込む前にシャッフル。

# データを増やそうとしている部分
```
# Preprocessing
preprocessing.RandomFlip('horizontal'), # flip left-to-right
preprocessing.RandomContrast(0.5), # contrast change by up to 50%

```
preprocessing.RandomFlip('horizontal')
訓練中にランダムな確率で画像を水平方向に反転。

preprocessing.RandomContrast(0.5)
訓練中、コントラストをランダムに ±50% の範囲で変更。つまり、元のコントラストの 0.5 倍から 1.5 倍の間の値にする。


# まとめ
上の２つで、データを色々いじります。訓練データを増やす部分もネットワークに組み込むのが少し違和感があるかもしれませんが、元となるデータをいじるより自由度が増え、データを使いやすいです。
訓練に使われた層は推論時にskipされます。
LightGBMの特徴量重要度とは？初心者向けに徹底解説！

機械学習の中でも高いパフォーマンスを誇るLightGBM。このアルゴリズムを使うとき、「特徴量重要度（Feature Importance）」という言葉をよく耳にします。この記事では、LightGBMの特徴量重要度について、中学生でもわかるように簡単に、さらに具体的な計算方法まで詳しく解説します！

---

## 1. LightGBMとは？

LightGBM（ライトジービーエム）は、データからルールや傾向を学び、問題を解決するための機械学習アルゴリズムです。例えば、テストの点数を予測する場合、「勉強時間」や「過去のテスト結果」などのデータから未来の結果を予想する手助けをします。

---

## 2. 特徴量と特徴量重要度とは？

**特徴量**とは、データの中にある「ヒント」のようなものです。例えば、テストの点数を予測するとき、次のような情報がヒントになります。

- 毎日何時間勉強したか
- 過去のテストの点数
- 睡眠時間
- 塾に通っているかどうか

これらを機械学習では「特徴量」と呼びます。

一方、**特徴量重要度**は、「どのヒントがどれだけ役立ったか」を数値化したものです。これにより、モデルが予測する際にどの特徴量が重要だったかが分かります。

---

## 3. 特徴量重要度の計算方法

LightGBMでは、特徴量重要度を算出する方法がいくつかあります。以下では、具体的な計算方法を解説します。

### 3.1 分割回数による重要度（Split Count Importance）

この方法では、特徴量が「決定木の分割に使用された回数」を重要度とします。

#### 計算式
$\
\text{Feature Importance (Split)}_j = \sum _{t \in T} 1(f_t = j)
\$

- $\ T \$: 決定木のすべてのノード
- $\ f_t \$: ノード $\( t \)$ で使用された特徴量
- $\ 1 \$: 指定した特徴量が使われた場合に1、それ以外は0を返す関数

#### 特徴
単純で分かりやすいですが、同じ特徴量が何度も使われる場合、過大評価される可能性があります。

---

### 3.2 情報利得による重要度（Gain Importance）

情報利得（Gain）は、分割により損失関数がどれだけ改善されたかを示す値です。この改善量を重要度として計算します。

#### 計算式
$\
\text{Feature Importance (Gain)}_j = \sum _{t \in T_j} \Delta \text{Loss}_t 
\$

- \$ T_j \$: 特徴量 $\ j \$ が分割に使われたノードの集合
- \$\Delta \text{Loss}_t \$: ノード \$ t \$ での損失関数の減少量

#### 特徴
モデルの性能向上に寄与した度合いを反映しているため、非常に実用的。ただし、値の大きい特徴量が過大評価されることがあります。

---

### 3.3 カバーによる重要度（Cover Importance）

カバー（Cover）は、分割時にどれだけのデータが関わったかを示す指標です。

#### 計算式
$\
\text{Feature Importance (Cover)}_j = \sum _{t \in T_j} w_t
\$

- \$ w_t \$: ノード \$ t \$ に割り当てられたデータの重み

#### 特徴
各分割でカバーされたデータ量を重視するため、実際のデータ分布を反映した重要度を算出できます。

---

## 4. 実際に特徴量重要度を計算する流れ

LightGBMは、上記の各計算を決定木ごとに行い、それをすべての木で合計します。具体的には、次のような流れです。

1. 各決定木内のノードごとに、使用された特徴量を記録する。
2. 各ノードで得られる「分割回数」「情報利得」「カバー」を計算する。
3. 森全体でこれらを合計して、特徴量ごとの重要度スコアを算出する。

最終的に、モデルにどの特徴量が重要だったかを示す「ランキング」が得られます。

---

## 5. 特徴量重要度の使い方

特徴量重要度は、モデルの解釈や改善に非常に役立ちます。以下はその具体例です。

- **重要な特徴量の把握**：モデルが何を重視しているのかを確認できます。
- **特徴量の選択**：重要度が低い特徴量を削除してモデルをシンプルにできます。
- **業務への応用**：例えば、「勉強時間が重要」と分かれば、「勉強時間を増やす」アクションを提案できます。

---

## 6. まとめ

LightGBMの特徴量重要度は、「どの特徴量がモデルにとって重要だったか」を可視化する便利なツールです。特に以下の3つの計算方法を理解しておくと、LightGBMを使いこなせるようになります。

1. 分割回数による重要度
2. 情報利得による重要度
3. カバーによる重要度

これらを活用して、より効果的な機械学習モデルの構築を目指しましょう！
Raycastでアプリの起動回数を自分に知らせる

先日Raycastを開くと2024年のサマリーが見られるようになっていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642245/a314da45-3d03-f191-b261-f3003ec5ffd8.png)

アプリケーションを開いた回数もカウントされており、僕はSlackを一番開いていることがわかりました。hotkeyに登録しているアプリケーションが少ないためSlackの使用回数が多いこと想像していましたが、改めて見ると流石に多すぎると感じました。

そこで、自分の使用状況を監視するために、RaycastのExtensionを作成してみることにしました。

## やりたいこと
- 1日にSlackを開く回数の傾向を把握する
- 感覚よりも多く開いている場合に、「お前開きすぎちゃう？」と指摘してもらう

:::note
本来はRaycast経由でないSlackを開いた数もカウントしたかったのですが、今回は普段自分が使っているhotkeyで開いた回数のみのカウントになっています。あらかじめご了承ください。
:::

## やったこと
- hotkeyでExtensionを実行し、その中でSlackを開くように設定
- 起動回数をカウントし、一定回数以上になると通知する仕組みを作成

最終的に、以下の2つの機能を作成しました。
① 設定したしきい値以上の回数開いた場合、Macのdisplay notificationで通知
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642245/7f83571a-5432-11f9-8f14-e2ab84b34c24.png)

② 使用するたびにRaycastのshowHUDを使ってディスプレイにその日の使用回数を表示

https://developers.raycast.com/api-reference/feedback/hud

## コード例
以下はサンプルコードです。
普段Slackを開くのに使用していたhotkeyをこのExtensionの実行に割り当てることで実現しました。Slackを開く前に拡張機能を経由することになりますが、操作感は従来と変わりませんでした。

```typescript
import { getFrontmostApplication, LocalStorage, showHUD } from "@raycast/api";
import { exec } from "child_process";

interface DailyTracker {
  date: string;
  count: number;
}

export default async function main() {
  const now = new Date();
  const today = now.toLocaleDateString('ja-JP');

  const storedData = await LocalStorage.getItem<string>("slack-tracker");
  let dailyTracker: DailyTracker;

  if (storedData) {
    const parsed = JSON.parse(storedData) as DailyTracker;
    if (parsed.date === today) {
      dailyTracker = parsed;
    } else {
      dailyTracker = { date: today, count: 0 };
      await LocalStorage.clear()
    }
  } else {
    dailyTracker = { date: today, count: 0 };
  }

  const frontmostApplication = await getFrontmostApplication();
  if (frontmostApplication.name !== "Slack") {
    dailyTracker.count += 1;
    exec("open -a Slack");
    if (dailyTracker.count >= 20) {
      exec(`osascript -e 'display notification "今日は${dailyTracker.count}回もSlackを開いているので辞めときましょう" with title "Slack Tracker"'`)
    } else {
      await showHUD(`Slack opened! (Today: ${dailyTracker.count} times)`);
    }
  }
  await LocalStorage.setItem("slack-tracker", JSON.stringify(dailyTracker));
}
```

## 最後に
RaycastでExtensionを自作するのは初めてでしたが、とても簡単に作成することが出来ました。APIのドキュメントも充実しており、さらに深く活用していきたいと思います。
今回は、拡張機能を経由してSlackを開く方法しか思いつきませんでしたが、将来的には他のアプリケーションも含めて監視できるようにしたいです。

※ 初めは30回Slackを開いたら通知する設定にしていたのですが、意外とすぐに通知が来てしまい、自分の使用頻度の多さを実感しましたw

Happy Raycast Life!