OmniAICreator/Qiita-1.07M huggingface dataset:
LLM実装におけるポイントまとめ

# はじめに
こんにちは。今回はLLM実装について記事を書いてみました。
今年の秋からLLMを実装する機会があったのですが、その際に初め分からなかった箇所などを、いくつか備忘録の意も込めてまとめています。
# コード実装
## TrainingArgumentsにおける引数設定
TrainingArgumentsではoutput_dirなどトレーニングにおける引数を指定することができます。ここで特に引数設定をしなければ、デフォルト値が適用されます。
例えば、バッチサイズを1にして5エポックの学習を行わせ、1エポックごとにモデルを保存したい場合(設定変更)は以下のような設定になります。
```
training_args = TrainingArguments(
    save_steps=198,
    num_train_epochs=5,  # エポック数
    per_device_train_batch_size=1,  # GPUごとのバッチサイズ
```
ここで、上記[save_steps]の値は198となっていますが、この値は学習の際に使用するデータやバッチサイズによって変動します。今回は5エポックで990ステップを要する処理であったので、この値を198(990÷5=198)としています。

## DeepSpeedにおけるCPUオフロード
DeepSpeedは、分散トレーニングや推論を効率的かつ効果的に行うための深層学習最適化ライブラリです。今回はDeepSpeedを使用して全パラメータ学習を行ってみました。ここでは、DeepSpeedにおけるCPUオフロードについて記載します。
CPUオフロードでは、オプティマイザのメモリや計算を GPU からホスト CPU にオフロードすることで、メモリの削減や高速化を目指します。これにより、単一のGPUでの処理など、限られたGPU環境の中でも処理を実行することができます。
今回は以下のような設定にしてみました（一部抜粋）。
```
{
    "zero_optimization": {
        "stage": 3,
        "offload_optimizer": {
            "device": "cpu",
            "pin_memory": true
        }
        "contiguous_gradients": true,
        "overlap_comm": true
    }
}
```
なお、ここで指定している[stage]では、オプティマイザーの状態や勾配、パラメーターの分割に対応する最適化ステージを指定します。
以下の図は標準的なデータ並列ベースラインと比較した3 ステージのメモリ節約量と通信量を表しています。
![スクリーンショット 2023-12-18 175151.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632319/4b59761e-655b-778a-7517-63a4cf6b1439.png)
(引用：https://www.microsoft.com/en-us/research/blog/zero-deepspeed-new-system-optimizations-enable-training-models-with-over-100-billion-parameters/)
## LoRAConfigにおけるtarget_modulesの設定
LoRAを使用する場合はLoRAConfigにおいて引数を設定することができます。上記で記載したTraining Arguments同様、特に指定しなければデフォルト値が適用されます。
LoRAConfigでは、[r]や[lora_alpha]などの引数が指定できますが、ここでは[target_modules]の設定について記載します。
target_modulesでは、LoRAを適用させたい層(モジュール)を指定することができます。既存のモデルを使用する場合は、そのモデルごとにこの引数を変更する必要があります。
以下ElyzaとOpenCalmを使用した際のコードを記載しています。なお、Elyzaはllama2、OpenCalmはGPT-NeoXがベースとなっています。
```
#Elyzaの場合
peft_config = LoraConfig(
            r=8,
            lora_alpha=16,
            lora_dropout=0.1,
            bias="none",
            task_type="CAUSAL_LM",
            target_modules=[
            　"q_proj",
            　"o_proj",
        　　　"gate_proj",
            　"up_proj",
            　"down_proj",
            　"k_proj",
            　"v_proj",
            ]
        )

#OpenCalmの場合
peft_config = LoraConfig(
            r=8, 
            lora_alpha=16, 
            lora_dropout=0.1,
            bias="none",
            task_type="CAUSAL_LM",
            target_modules=["query_key_value"])
```
# さいごに
LLM実装をやり始めてからまだ少しの期間ですが、論文や公式ドキュメントなど見つつ行ってはいるもののまだまだ分からない事だらけです。場合にもよりますが、分からない点に対しては、基本的には公式ドキュメント(HuggingFaceやGitなど）を見に行ってみるのが、バージョン変更などの観点からも確実ではないかと考えています。
今回は3つのポイントを紹介しましたが、今後もこのようなナレッジはためていこうと思います！
【TIPS】案外知られていないEnum.into

この記事は、[Elixir Advent Calendar 2023 シリーズ11](https://qiita.com/advent-calendar/2023/elixir) の19日目です

---

【本コラムは、5分で読め、2分で試せます】

[piacere](https://twitter.com/piacere_ex) です、ご覧いただいてありがとございます :bow:

`Enum.into` って、けっこう便利に使えるのですが、案外、知られていない関数の1つなんじゃ無いかなって思います

それをTIPSとしてまとめておきました

# 使い方

キーワードリストをマップに1発変換できます

```elixir
[a: 123, b: 456]
|> Enum.into(%{})
```

```elixir:結果
%{a: 123, b: 456}
```

逆も然りです

```elixir
%{a: 123, b: 456}
|> Enum.into([])
```

```elixir:結果
[a: 123, b: 456]
```

つまり、第二引数に指定した型で、第一引数（パイプの前）のデータを変換するということです

正確に言うと、`Enumerable` のデータを `Collectable` に変換するのが、`Enum.into` です

そのため、タプルや文字列、バイナリのような `Collectable` に属さないデータには変換不可です

```elixir
[123, 456]
|> Enum.into({})
```

```elixir:結果
** (Protocol.UndefinedError) protocol Collectable not implemented for {} of type Tuple. This protocol is implemented for the following type(s): BitString, File.Stream, HashDict, HashSet, IO.Stream, List, Map, MapSet, Mix.Shell
    (elixir 1.15.7) lib/collectable.ex:1: Collectable.impl_for!/1
    (elixir 1.15.7) lib/collectable.ex:92: Collectable.into/1
    (elixir 1.15.7) lib/enum.ex:1534: Enum.into_protocol/2
    #cell:2ugmh3yq3flnvles:2: (file)
```

ひとまず、キーワードリストとマップのようなKeyValueに特化した関数だと思っていればOKです
自然言語処理のための動的計画法

本記事は、[京都大学人工知能研究会KaiRAのAdvent Calender](https://qiita.com/advent-calendar/2023/kyoto-kaira) 19日目の記事です。

今回は自然言語処理の手法について、動的計画法(Dynamic Programming)という切り口から簡単に解説してみたいと思います。

自然言語処理の手法である __構文解析__ には動的計画法が用いられていますが、なぜ動的計画法であることが必要なのか、その性質に焦点を当てて動的計画法を用いる意義の理解の一助となれば幸いです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631758/54c72222-e884-fded-f9ad-634a9bd84640.png)


# 目次
[1.動的計画法](#1-動的計画法)
[2.自然原言語処理への応用](#2-自然言語処理への応用)

# 1. 動的計画法

## 1.1 動的計画法の概要

動的計画法については下記のようにわかりやすくまとめられています。
「ある大きな問題を、同じ形をしたより小さな部分問題に帰着させ、部分問題の計算結果を記録して使い回しながら解いていく」
出典: [中学受験の算数問題で入門する動的計画法](https://tars0x9752.com/posts/dp-nyuumon)

## 1.2 注目したい動的計画法の性質

この、 __小さな部分問題の解を記録し、再利用することで時間計算量を効率化できる__ という点が自然言語処理に応用できます。

# 2. 自然言語処理への応用

## 2.1 自然言語の構文解析

動的計画法の応用に行く前に、自然言語処理における構文解析に触れておきます。

構文解析とは、自然言語の文を入力とし、その内部構造である構文構造を計算する自然言語処理技術のことです。

我々人間は、下記の2文のように同じ単語の組み合わせによって作られた文でも、その並びによって異なる意味を表すと認識できます。

さらに、見た目は全く同じ文であってもどこで区切るかによって考えられる文意を複数想定し、文脈に合うよう1つに絞ることもできます。

構文解析の目的は、このように複数ある選択肢の中から __人間の解釈と同じ文構造を正解として__ 出力することです。

## 2.2 CKY法

入力された文が短いものであれば考えうる構文を難なく列挙できますが、長い文になれば計算量は爆発的に増えるため、いかに効率よく計算するかがポイントになります。

そこでCKY法というアルゴリズムが用いられます。

CKY法とは、動的計画法を用いてすべての構文パターンから最も確率の高いものを計算するアルゴリズムです。

動的計画法の性質については1.1や1.2で触れましたが、つながりをもつデータを効率的に処理するために動的計画法は効果的です。

# まとめ

動的計画法を応用したCKY法により、部分的な構文の解析結果を逐一保存しながら構文解析を進めることができます。

# 参考資料
[自然言語処理の基礎](https://www.amazon.co.jp/Text-%E8%87%AA%E7%84%B6%E8%A8%80%E8%AA%9E%E5%87%A6%E7%90%86%E3%81%AE%E5%9F%BA%E7%A4%8E-%E5%B2%A1%EF%A8%91%E7%9B%B4%E8%A6%B3-ebook/dp/B0BBT6KXZN/ref=tmm_kin_swatch_0?_encoding=UTF8&qid=1702911224&sr=8-1)
ポインタのキャンセルに関するアクセシビリティ

## これはなに？

アクセシビリティの「操作可能」の中で入力モダリティのポインタのキャンセルに関するの項目についてまとめました。
このアクセシビリティはレベルAです。

:::note info
**入力モダリティとは**
利用者がキーボード以外の様々な入力を通じて機能を操作しやすくすること。
モダリティとは、「様式」「様相」といった意味です。
マウス、タッチスクリーンの指、Apple Pencilのようなポインター入力デバイスなどがあります。
:::

## 概要

クリックやタップで実行される機能の実行、完了のトリガーには、ダウンイベントを使わず、アップイベントやクリックイベントを使い、誤った操作を中断できるようにする。

:::note info
**ダウンイベントとは**
コンテンツを押下したタイミングで実行されるようなイベント。
「タッチスタート」や「マウスダウン」と呼ばれることもある。
:::

:::note info
**アップイベントとは**
コンテンツから手を離したタイミングで実行されるようなイベント。
「タッチエンド」や「マウスアップ」と呼ばれることもある。
:::


例えば「間違えてタップしたので、そのまま指をずらしてから離せばキャンセルされる」という経験はありませんか？
このアクセシビリティはそういった行動を定めています。

## なぜこのアクセシビリティが必要なのか 

誤タップや誤クリックなど、意図しない動作で操作されないようにするために必要とされています。

## 対応

- ダウンイベントがない
    - コンテンツを押下したタイミングで機能が実行されない
- 中止または元に戻すことができる
    - コンテンツから手を離したタイミング（アップイベント）で、ダウンイベントの中止か元に戻すことができる
- アップイベントで反転

### ダウンイベントがない

コンテンツを押下したタイミングで機能が実行されないように、アップイベントで実行されるようにします。

例えば `a` タグのテキストリンクは、アップイベントでページが遷移する状態になっています。

### 中止または元に戻すことができる

先に例で出した「間違えてタップしたので、そのまま指をずらしてから離せばキャンセルされる」が該当します。
間違ったアイテムを選択していることがわかった場合、ポインタまたは指を離す前にターゲットから動かすことで操作をキャンセルすることができます。

### アップイベントで反転

例えば、ボタンを押下している間（ダウンイベント中）だけポップアップの表示や動画の再生がされる場合、ボタンから離したタイミング（アップイベント）でポップアップが消えたり、再生が停止される状態などが該当します。

## 例外

ダウンイベントが必要不可欠な場合は例外として認められます。
この場合元に戻す方法の提供は **ダウンイベントが必要不可欠な例外において必須要件ではない**です。
なんだか難解な言い回しです。
ただ、UXの観点では提供したほうが良いと考えます。 

- ダウンイベントが必要不可欠な例
    - ピアノツールの場合、鍵盤を押したら音がなる
    - Deleteボタンで文字が消える

## 参考

- [達成基準 2.5.2: ポインタのキャンセルを理解する](https://waic.jp/translations/WCAG21/Understanding/pointer-cancellation.html)
- [ダウン・イベントをトリガーにしない|入力ディバイス — freeeアクセシビリティー・ガイドライン Ver. 202107.0 ドキュメント](https://a11y-guidelines.freee.co.jp/categories/input_device.html#gl-input-device-use-up-event)
- [2.5.2 ポインタ操作のキャンセルができる - Ameba Accessibility Guidelines](https://a11y-guidelines.ameba.design/2/5/2/)
【UEFN】Verseでプレイヤーを回復させてみる

## 背景
最近メタであるボックスPVPを作ろうとしたときに一定の間隔で回復する役職を作りたかったので調査してきました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692976/bd47adae-8640-1390-7cb1-fc74cb97fcb5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692976/76bb7bc4-dbdb-878d-d6f8-3984e8a5bb14.png)

## やること
セッションにいるプレイヤーそれぞれ一秒ごとに10体力を回復させる機能をつけます。

### 動画
<iframe width="560" height="315" src="https://www.youtube.com/embed/HBFECXY89xA?si=MX48v2VjZQStJk1u" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

## 実装
### 全体コード
```
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Fortnite.com/Characters }

player_heal_device := class(creative_device):

    OnBegin<override>()<suspends>:void=
        Print("Hello, world!")
        Print("2 + 2 = {2 + 2}")
        AllPlayers := GetPlayspace().GetPlayers()
        for (Player : AllPlayers):
            if(FortCharacter := Player.GetFortCharacter[]):
                Heal(FortCharacter)

    Heal(FortCharacter : fort_character)<suspends>:void=
        Print("Healing player !")
        # 体力が回復することを確認するために、一時的に体力を10に設定します。
        FortCharacter.SetHealth(10.0)
        loop:
            Sleep(1.0)
                FortCharacter.Heal(10.0)
```
いつもの``GetPlayspace``でそのセッションにいるプレイヤーを取得してそれぞれの``fort_character``を取得している感じになります。

``fort_character``はhealableインターフェースを実装しているので以下の関数がプレイヤーに対して有効でした。
```
    # Implemented by Fortnite objects that can be healed.
    healable<native><public> := interface<epic_internal>:
        # Heal the `healable` object anonymously by `Amount`. Setting `Amount` to less than 0 will cause no healing.
        # Use `Heal(:healing_args):void` when healing is being applied from a known instigator and source.
        Heal<public>(Amount:float):void

        # Cause `Args.Amount` damage to the `damageable` object. Setting `Amount` to less than 0 will cause no damage.
        Heal<public>(Args:healing_args):void

        # Signaled when healing is applied to the `healable` object.
        HealedEvent<public>():listenable(healing_result)
```
今回はただ回復させたいだけだったので``Heal<public>(Amount:float):void``を使いました。
``Heal<public>(Args:healing_args):void``こちらの関数は回復してくれたプレイヤーなどのオプションを付けて回復させることができるようです。

#### ``fort_character``でキャラ関連の操作は何でも行けそう？
```
    fort_character<native><public> := interface<unique><epic_internal>(positional, healable, healthful, damageable, shieldable, game_action_instigator, game_action_causer):
```
``fort_character``に実装されているインターフェースを見た感じだと体力やシールド、このプレイヤーに影響を与えた・与えられたプレイヤーなどさまざあなことが取れそう。

## まとめ
今回もシンプルに実装できました。

``game_action_instigator``,``game_action_causer``インターフェースも利用できるようになれば相手に与えたダメージ分だけ回復するとかが実装できそうでした。

## 余談
この度UEFN/Verseに関するオープンコミュニティサーバーを建ち上げました。ちょっとでも興味があれば奮ってご参加くださいませ。

https://discord.gg/MehcNhyxdq
図書館で技術書を探すときのTips①　検索編

# はじめに
　技術書を無尽蔵に買うほどの資金と収納場所があればいいのに、と願うことはないでしょうか。急に宝くじが当たるといったことがない限り、実現は難しいと思います。

　その点、公共図書館は無料で借りられますし、返却してしまえば収納に困ることもありません。本記事では、私が図書館で技術書を探すときに心がけていることを書きました。
 （長くなってしまったので①検索編と②貸出編に分割しています。）

 :::note warn
技術の進歩が早く出版スピードも早いものは、図書館の所蔵している版が古い可能性もあるので、必ず出版年を確認することをオススメします。
:::

# 1. まずは王道の検索から

## 近くの自治体図書館のOPAC（図書検索）を利用する

　一番手っ取り早いのは、近くの図書館のHPを探すことです。「○○県立図書館」や「○○市立図書館」などで探すと見つかります。面倒な時は、「近く　図書館」などで探してもOKです。
 
 　大まかな傾向として、県立図書館は割と学術的な固めな本、市立図書館は実生活により近い本を収集している（市民により親しみのあるテーマ）ことが多いので、使い分けてみるのも◎
  ※もちろん例外もあります。

  各自治体でHPの特色がありますが、基本的には「蔵書（図書）検索」や「本を探す」などが書かれた検索ボックスからキーワードで探せます。

例）　My推しの「石川県立図書館」HP

* [図書館HP本体](https://www.library.pref.ishikawa.lg.jp/)
* [SHOSHO](https://www.library.pref.ishikawa.lg.jp/shosho/)

## 近くの大学図書館のOPAC（図書検索）を利用する

　コロナ禍で一時期停止している学校が多かったですが、大学図書館は一般利用者も受け入れていることが多いです。収集は学術書メインですが、その分、より専門的な図書を探すのに適しています。（もちろん、入門書も多く所蔵していますが）

　一点、注意が必要なのは、蔵書の置き場所に〇〇研などが書いてある場合です。研究室が所有している本で、一般利用者への貸出は行なっていない場合が多いです。

## カーリル（図書館横断検索エンジン）を利用する

　カーリルとは、全国の図書館の蔵書を横断検索できる検索エンジンです。少し遠いけれど行けなくもない図書館に蔵書があったり、取り寄せを検討する時に効果を発揮します。
 
 　ちなみに、私は蔵書リクエストをするときに検索して、他の図書館でも購入実績があるか調べることもあります。

https://calil.jp/

### カーリルのオススメ機能

**1. お気に入り図書館機能**
　お気に入り図書館を設定して、その中で蔵書があるか、検索範囲を絞ることができます。所蔵なし・貸出可・貸出中…など、その本のステータスが分かるので、すぐに読めるか、少し時間がかかるのかの判断材料になります。

**2. 本のレシピ**
　カーリルユーザーがテーマごとに作成したブックリストを閲覧できるサービスです。
大学図書館や公共図書館のアカウントなどもレシピを作成しています。
技術書というよりは人文学系が人気レシピに上がってきている印象ですが、キーワード検索でレシピを探すこともできます。

例）　プログラミングに関する本のレシピ

https://calil.jp/recipe/5880583964590080

# まとめ
　書店と電子書籍に加えて、図書館は読書好きには強い味方です。　使いこなして楽しい読書ライフを！
スライスやってる？

## はじめに
リストやタプルを扱う際のスライスについての備忘録．

## 動作環境
- Python 3.12.0

## コマンド紹介
### スライスの基本
```python
list[sIndex:eIndex] # sIndex(最初のインデックス)，eIndex(最後のインデックス)
```
```sIndex <= x < eIndex```の範囲が選択されます．
なので，Indexの範囲としては```list[sIndex]```~<ins>```list[eIndex-1]```</ins>が選択されます．ちょっとややこしいですね．
イメージとしては，スライスで指定するインデックスは要素と要素の間を指すと考えると理解しやすいかもしれません．
>スライスの使い方をおぼえる良い方法は，インデックスが文字と文字のあいだ(between)を指しており，最初の文字の左端が0になっていると考えることです．
<ins>[3.12.1 Documentation » Python チュートリアル » 3. 形式ばらない Python の紹介](https://docs.python.org/ja/3/tutorial/introduction.html#text)</ins>

```
 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
 0   1   2   3   4   5   6
-6  -5  -4  -3  -2  -1
```

```python
sample = ['C', 'D', 'E', 'F', 'G', 'A', 'B']

print(sample[2:5]) # Indexが2番目から4番目まで
print(sample[:4]) # Indexが0番目から3番目まで
print(sample[3:]) # Indexが3番目から最後まで
print(sample[:-2]) # 負の数を指定するとシーケンスの末尾から数える
print(sample[-2:])

# 実行結果
['E', 'F', 'G']
['C', 'D', 'E', 'F']
['F', 'G', 'A', 'B']
['C', 'D', 'E', 'F', 'G']
['A', 'B']
```
---
### ステップの指定
最初と最後のインデックスの他に，ステップの数値も指定することができます．
```python
list[sIndex:eIndex:step] # sIndex(最初のインデックス)，eIndex(最後のインデックス), step(ステップ数)
```

```python
sample = ['C', 'D', 'E', 'F', 'G', 'A', 'B']

print(sample[::2]) # 最初から最後までを2つおきに出力
print(sample[1:4:2]) # Indexが1番目から3番目までを2つおきに出力

# 実行結果
['C', 'E', 'G', 'B']
['D', 'F']
```

ステップ数をマイナス値にすると逆順（リバース）して要素を取り出せます．
```python
sample = ['C', 'D', 'E', 'F', 'G', 'A', 'B']

print(sample[::-1]) # 最初から最後まで逆順に要素を取り出す
print(sample[5:1:-2]) # 5番目から2番目まで逆順に2ステップずつ要素を取り出す

# 実行結果
['B', 'A', 'G', 'F', 'E', 'D', 'C']
['A', 'F']
```
逆順で範囲を指定して要素を取り出す際は，```sIndex > eIndex```である必要があります．

---
### 多次元配列のスライス
```python
import numpy as np
X = np.array([
    [1,2,3],
    [4,5,6],
    [7,8,9]
    ])
 
print(X[:,1]) # 全ての配列の1番目の要素にアクセス
print(X[2,:]) # 2番目の配列のすべての要素にアクセス == X[2]
print(X[:2,1:]) # 1番目までの配列の1番目以降の要素にアクセス

# 実行結果
[2 5 8]
[7 8 9]
[[2 3]
 [5 6]]
```
開発向けオンボーディングにUI/UX課題「デザインクリティーク」を取り入れたら意外と盛り上がった話

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982136/cc683900-1f4f-9662-77fa-069601646f28.png)

## 概要
初めまして！ 人事パッケージ製品のUI/UXデザインチーム の Design Ops / Manager / UI設計を担当しているデザイナーのアンナです。

Works Human Inteligence(以下WHI)では2022年から毎月/毎年、開発部署に配属された新卒・中途向けにオンボーディングクエストを実施しています。クエストにUI・UX課題として "__デザインクリティーク__" を導入させてもらったので、その背景・目的・やり方・についてご紹介したいと思います！


##### WHIオンボーディングについてはこちらをチェック
- [2022年、3大がっかりだった開発オンボーディングを皆で楽しくした話](https://qiita.com/e99h2121/items/888165fafcb03e249f0e)
- [WHIの開発オンボーディングに迫る！Vol.1 オンボーディングのこだわりポイントとは？](https://note.com/works_hi/n/ncef79cf102ef)

## 誰に読んでもらいたいか？
こんな方にぜひ読んでもらいたいです！
- デザインクリティーク初耳の人
- オンボーディングに、デザインコンテンツを取り入れてみたい人

## デザインクリティークとは
デザインクリティークとはアウトプットについてのフィードバックを集めるための会議のことです。
![image.png プレゼンターがアウトプットを共有している様子](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982136/365e2819-4fe6-3064-dff9-d9af54f34a42.png)
出典：https://osamaabdelnaser.medium.com/learn-more-about-design-critique-sessions-e88cf4300244

## 背景
一見デザインが関係なさそうな開発向けのオンボーディングにデザインクリティークを取り入れた背景は２つあります。

### 1. 開発部門に “UI/UX” を共通言語として取り入れるため
UIとUXの知識を全員が共通で持つことで、ユーザー中心設計を意識したより直感的で使いやすい製品の開発が促されます。また、デザイナーと開発者の共通理解によりコミュニケーションが円滑化し効率的な開発を実現できるため、UI/UXコンテンツをオンボーディングに導入しました。

### 2. デザインはセンスではなく誰でも取り入れられる思考であるということを体験してもらうため
[2022年のWoman Developer Summit](https://speakerdeck.com/whisaiyo/women-developers-summit-2022)でもお話しした内容になりますが、WWHIのデザイナーの数は開発者の人数に対して極端に少ないため、全ての案件のUI・UX設計にデザイナーが関わることは難しいのが現状です。一方で、UI/UXデザインはデザイナーの感覚的なセンスが必要だと感じている人も多く、自分にはできない、と考えている人もいます。その考えを払拭し、デザイナーでなくても設計時にユーザーを意識すれば読みやすく・直感的な製品を設計できると実感してもらうために実践課題を導入しました。

## デザインクリティークの目的
デザインクリティークは以下の目的を達成するために開催しています。
- アウトプットに至った経緯をロジカルに伝える練習のため
- 他開発者のアウトプットに対して、ロジカルなフィードバックをする練習のため
- 様々なフィードバックから新たな発見を得るという経験を得るため

## デザインクリティークのやり方
デザインクリティークの事前準備と当日の進め方についてです。

### 事前準備
事前準備としてキャッチアップして欲しいコンテンツと課題を共有します。WHIではデザイナーお手製の「デザイン4原則」と「UXライティング」のコンテンツを共有しています
- 「デザイン4原則」に関する学習コンテンツの共有 
- 「UXライティング」に関する学習コンテンツの共有 
- 事前課題（今回は①名刺の改善②ポスターの改善③ダイアログの改善の3つの課題を用意しました）

![image.png　名刺の改善・ポスターの改善・ダイアログの3つの課題](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982136/adc47b42-ca0f-b217-7b77-1419e038b6ac.png)

### デザインクリティーク当日
1. プレゼンター(1名)・ファシリテーター(1名)・レビュアー(それ以外)を決める
2. プレゼンターから改善案とそのデザインに至った経緯（問題と解決策）を説明する
3. レビュアーがフィードバックをする
※全員にプレゼンターが回るまで#1~3を繰り返す。

```
Tips
★ タイムキーパーもいると計画的に進めることができます!
★ Figjamなどのツールを利用して収集したフィードバックのメモを取ると後で忘れずに振り返ることができます!
★ レビュワーはさらに改善するためのステップを教えてあげたり、
　　　　気になったデザインの意図を聞いてみるとより興味深い会話が展開されることがあります!
```

## まとめ
以上、開発のオンボーディングに導入した「デザインクリティーク」というフィードバックを集める会議についてのご紹介でした。デザイナーだけでなく誰もがUI・UXの知識を習得し、デザインを意識した製品設計をするための取り組みです。

人生初Qiita投稿を果たしたので、次回はもう少し肩の力を抜いて発信していこうと思います。

やり方がわからない/他にもっと良いイベントあるよなどなどあればお気軽にコメントください！
日本語プログラミング言語をモデリング言語としてシステム開発上中流工程に導入のメリット・デメリット

# はじめに

日本語プログラミング言語をモデリング言語としてシステム開発上中流工程に導入した場合、そのメリット・デメリットについて考察する記事の8回目です。

本記事の内容はいくつかに分割されて記載されます。本記事中の「本記事」とは分割された内容の総体を指す場合があります。

https://qiita.com/advent-calendar/2023/remind

この記事は日本語構造化仕様記述言語 Re:Mind（リマインド）アドベントカレンダー2023の18日向けの記事です。


## 対象読者
とりあえずこの記事の想定読者はシステムエンジニアさんです。とくに日本語で要求仕様や内部設計資料を書いている方向けのお話です。

また、参考にプログラマさん。ぐだぐだの内部設計書から実装してひどいめにあったことのあるひと（力量のあるデベロッパはそれを乗り越えて設計者になる？）

システム開発工程をトータルに見ている責任者さん、システム開発工程の改善ソリューションを検討している企画責任者さんとか。

# 想定しているシステム開発フロー
オーソドックスなリレーショナルデータベースを使用している業務システムであることを[1回目](https://qiita.com/mylifewithviolin/items/b7cc85911507cf1a2a55)[2回目](https://qiita.com/mylifewithviolin/items/4ce62e0d5473626347e1)の記事で説明しております。

## 想定しているレイヤードアーキテクチャ・業務
一般的なWebアプリケーションシステムであり、簡単な受発注業務をインターネットで支援するシステムであることを[3回目](https://qiita.com/mylifewithviolin/items/d10d59e98c4d2d7dca3d)[4回目](https://qiita.com/mylifewithviolin/items/68dbf00cebb1bc8f6209)の記事で説明しております。

## 想定しているユビキタス言語
[5回目](https://qiita.com/mylifewithviolin/items/e1a7915efbf369117c97)の記事ではドメイン駆動設計（DDD）の文脈で用いられる意味でのユビキタス言語を例示しました。

## ユビキタス言語化された日本語プログラミング言語
[6回目](https://qiita.com/mylifewithviolin/items/f49c48241d8f72d6839a)[7回目](https://qiita.com/mylifewithviolin/items/8823d08c79bf70464bc0)の記事ではドメインエキスパートからプログラマレベルまで共有可能な言語のことをユビキタス言語化された日本語プログラミング言語とし、その各工程のソースコードの差異を例示・解説しました。

# 日本語プログラミング言語をモデリング言語としてシステム開発の上中流工程に導入のメリット・デメリット

これまでの記事でようやくひととおりの検討材料を例示できましたので、まだまだざっくりしたシンプルな例すぎて説得力にはかけると思いますが、さらに詳細に立ち入る前に、本記事のテーマのメリット・デメリットについて考えてみます。

## メリット
**自然言語の母語が構造化された制約があるだけで、言語としての可読性が高い**
この点でシステムエンジニアリングに疎いドメインエキスパートでも十分に意図を共有可能（特に上流のモデリング記述）

**ロジックの意図の表現・精度が自然言語記述より格段に増す**
数学的形式言語ほどではないにしろ、最上流から静的に型付けされた構造化言語による記述とすることでシステムに出現するデータの型の引き、戻りの一貫性は検証可能

**各工程層の設計者の意図を確実に次の工程に引き渡せる**
前の工程の成果物・ソースコードを継承する
次工程担当者は前工程のソースコードを直接編集して書き足すイメージ

**各工程層の中間成果物に「完成」の客観的な目安を導入できる**
つまり各工程層のユビキタス言語のコンパイラが通過するか

## デメリット
**数学的形式言語よりは各段にハードルは低いものの自然言語記述より制約があるため最上流では能力的に対応できない実務担当者も出現**
ただし自然言語との併記は可とすることで逃げれる。（次も似た感じ）

**各工程層の中間成果物にコンパイラ検証による「完成」の客観的な状態が導入されるため自然言語記述のあいまいな逃げができないことによる工程遅延**
これの回避策としては、コンパイラ検証はオミットして、構造化疑似言語として運用する（多少のあいまいな表現が許容、未定義のデータ名、処理名などが混在）

**後工程の変更の前工程へのフィードバック工数**
後工程の変更内容をどこまで前工程のソースに反映するか。手作業ではやってられない。ただし、帰納的なトランスコンパイルは抽象的な状態を詳細化するよりは一意性がありコンピュータが得意なので、逆トランスコンパイラなどで自動化はできるかもしれない。

# この回のまとめ
本記事の中間的な締めとして、ざっくりメリット・デメリットについて検討してみました。。

# 次回
各工程の詳細について引き続き検討していきます。数学的形式言語との関係について少し触れます。
SpringBoot３.0にバージョンアップした話

この記事はZOZOアドベントカレンダー　Series1 19日目の記事です。

Spring Boot３にバージョンアップしました！

とはいえ、もう２系はサポートしていないので、この記事も不毛なものになるかもしれませんが、まだやっていない方向けに記録しておきます。

基本はSpring Boot３マイグレーションガイドにある通りでOKです。

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide

他にもこの件については多くの記事が既に出ています。

この記事ではそれらの記事を漁ってもあまり情報が出てこなかった点に絞ってお伝えします。

# sentryへの通知がなんか変？

微妙におかしくなってたのですが、dev環境のエラーがproduction環境と表示されてしまっていました。対応方法としてはjakarata版のライブラリがあるのでそれに切り替えましょう

     - implementation 'io.sentry:sentry-spring-boot-starter:6.33.0’
     + implementation 'io.sentry:sentry-spring-boot-starter-jakarta:6.33.0’

# redisキャッシュのapplication.yamlの設定方法が変わっていた。

表記方法が代わってキャッシュがされていませんでした。
変更前
    
    redis:
    cluster:
    nodes: 127.0.0.1:7000
    
変更後
    
    data:
    redis:
    cluster:
    nodes: 127.0.0.1:7000
    
# bootRunでFlyway自動マイグレーションが動かなくなった。
こちらは諦めて、bootRun前に手動でマイグレーションするようにしました。

# OpenAPIからgeneraterを使って作られたクラスのうち、内部クラスのクラス名が変わった。

語尾にImplと付くようになりました。対応としては、最新のopenapi generator7.0.1で起こっていたので、6.1.0 にダウングレードして8割ぐらい解決。それでもクラス名が変わるケースがあったので、そこは諦め使う方を修正しました。
    
# DatadogAPMのパスパラメータの表記が変わった

datadogのAPMでresource_nameに使うパスパラメータの表記がパラメータ名が元々入っていたのに、？表記になってしまいました。こちらは頑張ってdatadogのMonitorの設定などを変更して対応しましたが、dd-java-agentのバージョンアップで治ることがわかりました。

ご参考まで
設計者必見！PolarDBのパフォーマンス ホワイトペーパー

# 結論
絶対値ベースの具体的なパフォーマンス テスト結果が載っている、貴重で太っ腹な資料なので、設計者は要チェックです！

# はじめに
プリセールス段階や要件定義段階で、ハードウェア構成(台数、スペック)、それに伴う課金の概算見積もりを求められることが多々あります。

特にクラウド時代になると、簡単にスケールアップ・スケールアウトができるので、逆に見積もりの振れ幅が大きくなり、予算管理の観点で、その振れ幅を含む概算を求められる事が増えてきています。

ただ、業務要件とシステム要件が固まっていない事が多い初期フェーズで、その概算見積もりをするのは至難の業で、実機テストをするにも工数やコストが合わず、頭を抱える事が多いです。

そんな課題に、このオフィシャル・ドキュメントのパフォーマンス ホワイトペーパーは、かなり役立つと考えます。

# パフォーマンス ホワイトペーパー とは？

PolarDBのドキュメントページには、Performance White Paperがあり、その中では具体的なハードウェア構成および負荷テストの結果、さらには、QPS(クエリ／秒) ・TPS(トランザクション／秒)の絶対値が公開されており、概算を出すのに、具体的な数値を参考にして計算できます。

基本的に、製品・サービスベンダーがオフィシャルに、このようなデータを出すことは稀で、出したとしても絶対値ではなく相対値 (何%アップとか) だったりするので、痒いところに手が届かない感じが多いのですが、こちらの資料は前提条件やテスト手法やデータ、構成の違いによる絶対値の推移がきちんと記載されているので、かなり太っ腹な資料公開だと思います。

# 公開されているデータ

[PolarDB for MySQL に関するパフォーマンス ホワイトペーパー(英語)](https://www.alibabacloud.com/help/en/polardb/polardb-for-mysql/performance-white-paper-4/)および、[PolarDB for PostgreSQL に関するパフォーマンス ホワイトペーパー(英語)](https://www.alibabacloud.com/help/en/polardb/polardb-for-postgresql/performance-white-paper-3/)が公開されており、利用データベースエンジンに合わせて、利用しましょう。


:::note info 
2023/12時点では、日本語版マニュアルだと情報が古かったので、英語版マニュアルのホワイトペーパーを見るのが良いと思います。
:::

# 特に参考になった資料 3選

#### 1\. Performance test results of PolarDB for MySQL 8.0.2 (Cluster Edition)
Dedicated instance familyの章では、コア数/メモリを、段階的に増やした処理 (2コア/8GB, 4コア/16GB, 8コア/32GB, 16コア/128GB) がスケールすることが証明され、かつ面白いのはメモリを増やしただけのテスト(8コア/32GBと、8コア/64GBの比較)も入っていることです。

またスケールアウトのテストで、read-only nodesを1台から8台にして、かつスレッド数を変動させた場合のテストも入っているのも興味深いですね。

https://www.alibabacloud.com/help/en/polardb/polardb-for-mysql/performance-test-results-of-polardb-for-mysql-8-0-2-cluster-edition?spm=a2c63.p38356.0.0.536c4aeaer8bgB


<BR>

#### 2\. Performance comparison with similar PostgreSQL cloud-native databases
類似の PostgreSQL 14 クラウドネイティブデータベース(たぶん、アレ)と、PolarDB for PostgreSQLとを比較している資料です。
企画自体がなかなか攻めていますね！

https://www.alibabacloud.com/help/en/polardb/polardb-for-postgresql/performance-comparison-with-similar-postgresql-cloud-native-databases?spm=a2c63.p38356.0.0.46997bf56kOM8N


<BR>

#### 3\. Performance comparison with open-source PostgreSQL
オープンソースのPostgreSQLと実行環境をほぼ合わせた状態でテストをしています。
ストレージアーキテクチャの違いと、トランザクション管理・キャッシュ管理が、PolarDB for PostgreSQLのアドバンテージになっているようです。

https://www.alibabacloud.com/help/en/polardb/polardb-for-postgresql/performance-comparison-with-open-source-postgresql?spm=a2c63.p38356.0.0.25594c487X0p9X



# 参考文献

PolarDB for MySQL に関するパフォーマンス ホワイトペーパー(英語)

https://www.alibabacloud.com/help/en/polardb/polardb-for-mysql/performance-white-paper-4/

PolarDB for PostgreSQL に関するパフォーマンス ホワイトペーパー(英語)

https://www.alibabacloud.com/help/en/polardb/polardb-for-postgresql/performance-white-paper-3/
Power Automate Desktopを触ってみた2023～なかなか触れないとこうなる～

## はじめに
1.本記事は、RPA（ロボティック・プロセス・オートメーション） Advent Calendar 2023の18日目の記事になります。

https://qiita.com/advent-calendar/2023/robotic_process_automation

2.本記事で登場するPower Automate DesktopのVersionは2.38です。
　また、UiPathのVersionは2023.10.2です。
3.筆者は現状、実務でPower Automate Desktop並びにPower Automate関連を使用していません。

<b>※そのため、この記事では技術的なことは一切出ません。ただ、他ツールを使うときに気を付けたいことを今回はまとめてみました。</b>

## 久しぶりすぎて...
自分は普段の業務ではUiPathを使用しています。一方Power Automate関連に興味があるものの触れる機会がめっきり減ったような気が...します。
（過去にはブログも書いたような…気がする）
今後を考えてPower Automate Desktopだけでも触れておかねば...という使命感で今、ブログを書こうとしています。

とりあえず、簡単なものを作ってみましょう。

## 何か実装しましょう
とりあえず、あるExcelのB2セルに「ここに書くよ」とありますが、上書きして「今日は登校日ですよ」と書込してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/fcd0017c-cfed-90ea-9941-7201292bbbc9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/ec42fafe-9ff2-61d3-2aed-cfa14dfac6ea.png)

こんな感じで作ったので実行。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/3dbefd94-b71e-9b6d-f2be-e22efe51ba8b.png)

できた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/bab2f255-d86e-6327-6a1b-ca75ca26821b.png)

※ちなみに最初に実行したところ、書き込みされてない？と思ったらExcelが「読み取り専用」になっていることを見落としていた。。。お恥ずかしい。

## 久しぶりに触ってみたところ...

### ①(1年ぶり？で)結構忘れていた。
普段、業務で使用することがない場合は、自分で機会を作って何かしら作ることが重要だと思います。
今回Excelの書き込みだけを行う操作を実装してみましたが、どのアクションを使うんだっけ？という感じで思い出しにくいところがありました。
こういったアドベントカレンダーで思い出せるのは、とても大切なことです。


### ②似ている動作はあるはず。だったら思い出せるはず。
UiPathでは、Power Automate Desktopのアクションに相当するのが<b>アクティビティ</b>です。
なので、自分が使っているツールをヒントにアクションを導き出すことも一つではないかと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/7316fe7d-7c13-50ad-7d8a-fb3e1a42816e.png)
探すと「この動作と近いかも？」となって、芋づる式に思い出せるかも？

### ③LT登壇など、何かしらの機会を自ら作る。
ここ最近はUiPath以外のイベントに顔を出すことが難しくなっていますが、RPAコミュニティでのLT大会、ハッカソン等のイベントで自ら使用する&何か成果物を作るという課題を自らに課す...というように自分を追い込むこともポイントです。
ハッカソンの場合は、その道を究めたものも多く匙を投げそうになるかもしれませんが...。それでも、自らその機会を作るor挑戦することは、大事なのかもしれません。

## まとめ
エクセルや操作は割と操作を覚えていた感じではあったのですが、いざまっさらな状態で作るのに時間を要してしまいました。
なかなか業務で使う機会がない場合、どうしてもアクション等の操作や実装手順を忘れがちになってしまいます。
こういったブログ投稿を機に実装方法を忘れないようにするもの技術を衰えさせないコツ？なのかもしれません...。
<b>2024年は、Power Automate系も無理なくスキルアップしたいです。</b>
最後までお読みいただきありがとうございました。
OAuth2.0モックサーバーの紹介

# 1. はじめに
GoogleログインのようなOAuth2.0サービスを利用すると、ログインやユーザー登録が簡単になります。その一方で、外部サービスに依存してしまうために、統合テストやE2Eテストの自動化が難しくなってしまいます。

そこで、モックサーバーを作って、テストを簡略化することを試みました。今回は作成したモックサーバーの紹介をしたいと思います。

### モックサーバーのコード
[ここ](https://github.com/SyunGyo/oauth2-mock)に置いてあります。
言語: Rust
フレームワーク: Axum

Googleログインはモックできました。その他のサービスは検証していません。

# 2. OAuth2.0の仕組み
はじめに、OAuth2.0の仕組みについてまとめます。OAuth2.0とは、あるサービスが保有するユーザー情報を外部サービスに提供するための方法です。以下では、ユーザー情報を保有するサービスを「リソースサービス」、外部サービスを「クライアントサービス」と呼ぶことにします。リソースサービスから提供されたユーザー情報を使って、クライアントサービスはログインなどの処理を行います。

全体の流れを図示すると、以下の図のようになります。

![スクリーンショット 2023-12-18 230836.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2331812/fee98ba1-214f-3361-2dad-172149b78684.png)


登場人物の具体例を挙げると、

- ユーザー=あなた
- リソースサービス = Google
- クライアントサービス = Qiita

となります。

<br>


次に、図の各ステップで何をしているかを説明します。

① ユーザーはOAuth2.0を使ったログインをしたいと、クライアントサービスに要求します

② クライアントサービスは、ユーザーに情報の提供を承認してもらう必要があります。そこで、リソースサービスの承認用URLを送ってリダイレクトしてもらいます。この時、後々クライアントサービスに戻ってくるために、コールバックURLも用意しておきます。

③ ユーザーはリソースサービスにログインして、承認をします。

④ リソースサービスは承認を受け付けると、認可コードをユーザーに送り返します。

⑤ さらに、ユーザーは認可コードをクライアントサービスに送ります。

⑥ クライアントサービスは、認可コードとあらかじめ保有していた認証情報をリソースサービスに送って、ユーザー情報取得APIを利用するためのアクセストークンを要求します。

⑦ リソースサービスはアクセストークンを返却します。

⑧ クライアントサービスはアクセストークンを使ってユーザー情報取得APIを叩きます。

⑨ リソースサービスはユーザー情報を返却します。


# 3. モックサーバーの概要
以下の図のようなログインページを用意して、入力された名前とメールアドレスをユーザー情報としてそのまま返すモックサーバーを作成しました。
![login-page.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2331812/4c0384d8-8a31-a885-85ad-58a9ec00d4dd.png)



作成したエンドポイントは次の4つです。
- [ ]  GET ```/login```
  ログインページを返します。クエリパラメータとしてリダイレクトURLも受け取って、セッションに保存しておきます。(③ ・④ に対応)
- [ ]  POST ```/login```
  ログインボタンを押すと、このエンドポイントにリクエストを飛ばします。リクエストを受け取ると、ランダムな認可コードを発行し、認可コードをKEYとしてユーザー名とメールをハッシュに挿入します。(③ ・④ に対応)
- [ ]  POST ```/token```
  認可コードを受け取って、アクセストークンを返します。このモックでは、認可コードをアクセストークンとしてそのまま返します。(⑥・⑦ に対応)
- [ ]  GET ```/info```
  アクセストークンを受け取って、ハッシュから対応するユーザー名とメールを検索して返します。(⑧・⑨ に対応)


# 4. 最後に
自動テストツールでGoogleログインを実行しようとすると、ブロックされてしまいます。この問題に対処するために、今回のモックサーバーを作成しました。同じような問題に苦しんでいる人の参考になれば幸いです。
[JavaScript] Canvas 間で画像を転送する

# 1. 直接 `drawImage()` メソッド等を呼ぶ方法

`drawImage()` メソッド等は `HTMLCanvasElement` および `OffscreenCanvas` を直接扱うことができます。

```js
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');

const offscreenCanvas = new OffscreenCanvas(300, 150);

// ...

context.drawImage(offscreenCanvas, 0, 0);
```

参考「[CanvasRenderingContext2D: drawImage() メソッド - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/CanvasRenderingContext2D/drawImage)」
参考「[WebGLRenderingContext: texImage2D() method - Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texImage2D)」

# 2. `ImageBitmap` にする方法

他の Canvas の画像を転送することのみを目的とする場合や、同じ画像を頻繁に描画する場合は、`ImageBitmap` にすることで高速に描画できます。

参考「[[JavaScript] ImageBitmap について - Qiita](https://qiita.com/kerupani129/items/79b988d2ecd23213b392)」

```js
const canvas = document.createElement('canvas');
const context = canvas.getContext('bitmaprenderer');

const offscreenCanvas = new OffscreenCanvas(300, 150);

// ...

const imageBitmap = await createImageBitmap(offscreenCanvas);

context.transferFromImageBitmap(imageBitmap);
```

```js
const canvas = document.createElement('canvas');
const context = canvas.getContext('bitmaprenderer');

const offscreenCanvas = new OffscreenCanvas(300, 150);

// ...

const imageBitmap = offscreenCanvas.transferToImageBitmap();

context.transferFromImageBitmap(imageBitmap);
```

```js
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');

const offscreenCanvas = new OffscreenCanvas(300, 150);

// ...

const imageBitmap = await createImageBitmap(offscreenCanvas);

context.drawImage(imageBitmap, 0, 0);
imageBitmap.close();
```

```js
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');

const offscreenCanvas = new OffscreenCanvas(300, 150);

// ...

const imageBitmap = offscreenCanvas.transferToImageBitmap();

context.drawImage(imageBitmap, 0, 0);
imageBitmap.close();
```

参考「[ImageBitmap - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/ImageBitmap)」
参考「[createImageBitmap() - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/createImageBitmap)」
参考「[OffscreenCanvas: transferToImageBitmap() method - Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas/transferToImageBitmap)」
参考「[ImageBitmapRenderingContext: transferFromImageBitmap() method - Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmapRenderingContext/transferFromImageBitmap)」
参考「[ImageBitmap.close() - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/ImageBitmap/close)」
Babylon.js で作成したメッシュの頂点毎に着色する

これは[Babylon.js Advent Calendar 2023](https://qiita.com/advent-calendar/2023/babylonjs) の18日目の記事です。

## この記事について
今回はメッシュの頂点を編集する方法について記載します。

### 立方体の頂点色を編集をする
CreateMeshをしたオブジェクトに対して、[前回](https://qiita.com/Ykoba791/items/00aee40ef1b4e9e53797)と同様にgetVerticesDataで色情報を取得します。
前回は、getVerticesDataの第一引数に、「BABYLON.VertexBuffer.PositionKind」を指定しましたが、色をコントロールする際は、「BABYLON.VertexBuffer.ColorKind」を指定します。

```javascript:四角形の色情報を取得する
var box = BABYLON.MeshBuilder.CreateBox("box1",  scene);
var boxCol = box.getVerticesData(BABYLON.VertexBuffer.ColorKind);
alert(boxCol);
```

取得した変数を表示してみたところ、結果はnullでした。
頂点の色の初期値は設定されていないようです。


それでは、試しに立方体の1点の色を変更してみます。
CreateBoxで立方体を作成し、配列にRGBカラーを1つ用意。
最期に頂点編集の時と同じように、setVerticesDataで、色情報を渡します。

```javascript:四角形の1点に色情報を指定する
    //立方体作成
    var box = BABYLON.MeshBuilder.CreateBox("box1",  scene);

    var colors = [];
    colors.push(1.0, 0.5, 0.0);
    box.setVerticesData(BABYLON.VertexBuffer.ColorKind, colors);
```

実行結果は下図のようになりました。
![baby20231218_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594551/4d085dfb-4cb2-6375-eced-6d448fcbcfcf.png)


1つの頂点に橙色が着色され、他の頂点に向かってグラデーションで表示されていますが、指定した頂点以外の部分が全て黒になってしまいました。未指定の頂点は0（黒）になるようですね。(初期値もnullでしたし)

残りの各頂点に白色も指定します。
頂点データ（x,y,zの配列）を取得して、3で割って頂点数を収集して指定します。

```javascript:四角形の1点を橙、他は白色を指定

    var boxPos = box.getVerticesData(BABYLON.VertexBuffer.PositionKind);

    var colors = [];
    colors.push(1.0, 0.5, 0.0);
    for(var p = 0; p < boxPos.length / 3; p++) {
        colors.push(1, 1, 1);
    }
    box.setVerticesData(BABYLON.VertexBuffer.ColorKind, colors);
```
実行結果は下図です。

![baby20231218_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594551/bfc63353-68ab-6e89-ae6e-0932cf7e3a34.png)

Playgroundはこちら。
https://playground.babylonjs.com/#UY72D0#15

頂点間の色は、自動でグラデーションされますね。


もうすこし色の指定を増やしてみます。
```javascript:四角形の9点に色を指定
    var boxPos = box.getVerticesData(BABYLON.VertexBuffer.PositionKind);

    var colors = [];
    colors.push(1.0, 0.5, 0.0,1);
    colors.push(1.0, 0.5, 0.0,1);
    colors.push(1.0, 0.5, 0.5,1);
    colors.push(0.0, 0.5, 0.5,1);

    colors.push(5.0, 0.5, 1.0,1);
    colors.push(5.0, 0.5, 1.0,1);
    colors.push(0.0, 0.5, 0.0,1);
    colors.push(0.0, 0.5, 0.0,1);

    colors.push(0.0, 0.0, 1.0,1);

    for(var p = 3; p < boxPos.length / 3; p++) {
         colors.push(1.0, 1.0, 1.0,1);
    }
    box.setVerticesData(BABYLON.VertexBuffer.ColorKind, colors);
```

![baby20231218_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594551/e76c3fc4-2dd2-42de-ae79-28a3e787897a.png)

面が変わると、別頂点として着色されました。
（右図の中央の頂点から右は緑色から橙へグラデーションが始まるが、左は白色から青へとグラデーションしている。）

## 最期に
今回は、立方体の頂点の色を指定してみました。

頂点の位置と色を指定できましたので、次回は少し冬らしいものを作成してみます。
やることリストが無限に長くなるあなたへ

# この記事のあらすじ
RPA（ロボティック・プロセス・オートメーション）Advent Calendar 2023の記事です。カレンダーを作ってくれた@inaho3517さんに感謝いたします。
この記事では、チケット駆動開発のチケットを業務進行管理に使う方法について触れています。本格的な方法やRPAらしいチケット処理の自動化やアラート処理などについてはここは[Qiita](http://qiita.com)なので山ほど情報があると思います。なので超入門編です。
# やることリスト
手帳、メールソフトに付属するToDoやスケジュール、付箋（物理orソフト）、自分へのチャット、などなど、「あ、あれやらないと」と未来の自分にリマインドを飛ばすことが良くありますし、その方法も様々な方法があります。
これをカード型のチケットにしてみてください。1枚で1件の「やること」にするのです。本や巻物の状態から離れましょう。スケジュール帳にスケジュール以外の情報を書くと、書いた場所を見失ったり、うんざりするほど過去の日付に戻る羽目になるのです。
カード型のチケットにすることで
* 重ねて管理でき、必要であれば机一面に広げることもできる
* カードサイズで記入量が物理的に制限されるので、必要以上に細かく書いて時間を消費しなくなる
* （慣れてきて軌道に乗ると）枚数でなんとなくヤバさが把握できる（多過ぎても少なすぎてもヤバイ）
* 分類することで、頭の中の交通整理ができる

など、さまざまなメリットがあるのです。今日は「チケット作成」と「分類」について紹介します。
# チケット作成
![IMG_0870.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/851752/398861e8-5caa-f005-430c-f8fc265cacb1.jpeg)
私は、A7サイズの紙切れを使っています。A4のコピー用紙を半分の半分の半分にしたサイズがA7サイズです。名刺よりちょっと大きいサイズ。私は何か書く時は必ず右上に日付を書くことにしています。
「やること」をA7サイズに書くコツとしては
* やり終えた状態を書く（未来の自分へのリマインダなので）
* あれこれ細かい条件を書かない（未来の自分が最低限理解できるレベルに留めておく）

です。私も初期に悩んだのが「イベントの企画」とか大きなことを書きすぎて、いつまでたってもやり終えた状態（企画完了）にならないので次第にうんざりして自己嫌悪に陥るのは本末転倒です。こういう時は「イベントの場所を時間を仮押さえする」「イベント2ヶ月前にやっておいた方が良いことを10個考えておく」「イベントに必要になりそうな機材を10個考えておく」など、大きなことを紙に書く前に「どうやったら細切れのザク切りのみじん切りにできるか」を考えてください。これは日頃から訓練できます。例えば買い物って習慣でやっていますが、買うモノを選ぶ→売ってそうな店を選ぶ→行く→買う→買ったものを所定の場所に置く、などとザク切りできるのです。
無限に長くなる「やることリスト」をA7サイズに揃えて、うんざりしない粒の大きさにザク切りするところまで成功です。やったね。
# チケット分類のオススメは「あしか（はてなの進行管理）」
* すぐやる
* そのうちやる
* ペンディング
* 終わった

です。あしかについては2005年と古いですが記事が残っています。
[「はてな」という変な会社](https://www.itmedia.co.jp/news/articles/0507/04/news036.html)
これを丸パクリして、箱ではなくて板にクリップ止めしています。
![IMG_0939.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/851752/d62b6d7a-351f-136a-7518-2140f7b2f1b2.jpeg)
クリップはPLUSさんのWクリップに「豆」「極豆」という可愛らしいサイズがあるのでこちらをオススメします。台紙になる厚紙＋15枚ぐらいはイケるので必要十分です。
わたしはこんな感じでこの進行管理板を使っています。
* 新しいチケットを書いたらとりあえず「そのうちやる」に入れる
* 朝イチはかならずこの板を見て、「すぐやる」を確認したり、「そのうちやる」から「すぐやる」に移動するものを決める
* 会議の合間など、ぼーっとしたいときはチケットを全部眺めて、書き直し（チケットの分割）ができそうなものを探す（2分割できそうなら2枚新しく書いて、もとの大きいのは「終わった」に放り込む（分割したよと書き残すとなお良い）
* 「ペンディング」は返事待ちや見積もり紹介中など、自分以外の都合で「終わった」に入れられないチケットを全部入れます。たまに見返して、催促したり諦めて他の方法を考えたりします。

# 作業時間は「すぐやる」チケットだけを見る
これを徹底することで、頭の中身から余計なものを一時的に追い出すことができます。電話などで割り込まれたら、さ新しいチケット1枚に書いて「そのうちやる」で後回しにします。
# 作業以外の時間に「すぐやる」以外のチケットの交通整理をする
作業中にこれを始めて現実逃避すると大体カオス化します。チケットの交通整理は頭の中のデフラグにもなるので、できれば大きな机に全部広げるのがオススメです。なので広げられない状況の時は交通整理は諦めて、「そのうちやる」から手頃に1枚拾う、ぐらいで済ますのが良いでしょう。
# 「終わった」にチケットが溜まるのは割と快感
長々と書きましたが、一番言いたいのはこれです。僕は1か月分まとめています。「今月これだけ終わったんだ」と常に確認できる状況を作って、一人でこっそりニヤニヤしたり、もっと良い方法はなかったのか振り返ったり、もっとわかりやすいチケットの書き方を研究するのは超オススメです。「終わった」はあなたの実績であり、経験値であり、誰も奪えないあなただけの足跡なのです。
そもそもWebAPIってなーに？

# なんでこれかいたの？
普段開発時にWebAPIを使用するがこれについてしっかり説明しろと言われると出来ないため

例）
Q WebAPIってなーに？
A なんか外部のアプリケーションに通信してデータ貰うやつ？

# APIとWebAPIってなーに？
### APIってなーに？
` Application Programming Interfaces`の略称で異なるソフトウェア、アプリケーション間で機能を共有する仕組み。アプリケーション同士が情報を要求、交換するためのメソッドやデータフォーマットを定義するもの。

### じゃあWevAPIってなーに？
Web上で通信するためにHTTP・HTTPSプロトコルを使用しているAPI
RESTAPIとかGraphQLがよく使われてるイメージ

# どうやってWebAPIが動いてるの？
- APIのエンドポイント（特定のURIやURL）をHTTPメソッド（GET、POST、PUT、DELETEなど）を用いてリクエストを送信する
- クライアント(お使いのPC,スマホ)がリクエストヘッダーに必要な情報（例: 認証トークン）、リクエストボディには必要なデータ（例: 新しいユーザーの情報）を含め、HTTPメソッドに従ってリクエストを作成して送信する
- APIサーバーは受信したリクエストを処理し、適切なHTTPステータスコードとレスポンスボディを生成してレスポンスをHTTPレスポンスとしてクライアントに送信する
- クライアントは受信したレスポンスを処理をする。例えば、成功時にはデータを表示したり、エラー時にはエラーメッセージを表示したりなど。
## 長い三行
エンドポイントで指定してHTTPメソッド使ってリクエスト送信
APIサーバーで処理してHTTPレスポンスとして送信
受け取ったらレスポンスを処理
# 最後に
記事書くために色々調べてみてふんわりWebAPIについて知ってる知識がちゃんと知ってる知識に落とし込めたかなと思いました
### Q.そもそもWebAPIってなーに？
A.外部のアプリケーションに通信してデータ貰うやつ
PowerQuery: 表記揺れの名寄せに使える AddFuzzyClusterColumn

# 背景

名寄せをするのって面倒だったけど、専用の関数があったので備忘録

# 概要

- AddFuzzyClusterColumn にお任せで名寄せ
- 言語指定をすることで日本語も利用可能
- 閾値で、調整可能
- 変換テーブルを用意しておくことで、調整も可能

ドキュメントは以下

https://learn.microsoft.com/ja-jp/powerquery-m/table-addfuzzyclustercolumn

# 利用例

## 閾値だけ

> = Table.AddFuzzyClusterColumn(変更された型, "ジャンル", "名寄せ 閾値", [SimilarityColumnName="similarity", Culture="ja-JP", Threshold=0.1])

日本語指定しても、全角半角、小文字大文字は単純に名寄せしてくれる。
カタカナひらがな程度なら、閾値次第

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/caab1acd-f9d7-41dc-4008-b920550dfff4.png)


## 変換テーブル利用

> = Table.AddFuzzyClusterColumn(result, "ジャンル", "名寄せ with table", [SimilarityColumnName="table similarity", IgnoreCase = false, Culture="ja-JP", Threshold=0.27, TransformationTable=Transform])

以下のようなテーブルを用意しておくことで、追加で名寄せを実施出来る。
とはいえ・・面倒ではある・・よね。 :sweat: 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/d7ec8762-192e-3721-08f8-d004d96d2709.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/fc895f1c-bb82-f9b2-12fb-ccea8356a2a8.png)


## 変換コード例全部

```perl: Transform Table
let
    ソース = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45Wety473HT5MeNPUo6Ss/2rH4+ZbdSrE600tMNE5/u3PJiFZrw4+Z5j5s3Y6h+3LTocXP34+aFQGE4+3HznsdN2x83LwfqgKra/Lh5/uPm5sdN65H0xwIA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [From = _t, To = _t]),
    変更された型 = Table.TransformColumnTypes(ソース,{{"From", type text}, {"To", type text}})
in
    変更された型
```

```perl: Fuzzy Sample
let
    ソース = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WerZn9fMpu5VidaKVHjfPe9y8+XFjD4TXuO9x02Q4r2nz4+b5j5ubHzeth0oD5fY/blz8uLEfLPB0Qs+TXbterOpBNqtpDVT3osfN3Y+bF6LyHjfvedy0/XHzcqBSsIyzv6+nM5iVnJ+bmQxmvd+z+P2e9e/3rH2/ZyWQDRHb2/x+b//7vb3v93YC2UqxsQA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [ジャンル = _t]),
    変更された型 = Table.TransformColumnTypes(ソース,{{"ジャンル", type text}}),
    result = Table.AddFuzzyClusterColumn(変更された型, "ジャンル", "名寄せ 閾値", [SimilarityColumnName="similarity", Culture="ja-JP", Threshold=0.1]),
    result2 = Table.AddFuzzyClusterColumn(result, "ジャンル", "名寄せ with table", [SimilarityColumnName="table similarity", IgnoreCase = false, Culture="ja-JP", Threshold=0.27, TransformationTable=Transform])
in
    result2
```

# あとがき

700 を超える関数があるので、なにかやりたいことがあったら調べてみるってのが大切ではあるけれど、
たまにしか使わないとついつい手抜きしてしまう。

ってことで、こうやって備忘録をしていくことは記憶に残すためにも大切なはず・・
p5.js で弾む系のイージングを試したり複数のイージングを変な混ぜ方で使ったりなど【完走賞ゲット-20】

:::note info
※ [Qiita の完走賞をゲットするための条件は「単一／複数のカレンダーに投稿した記事が合計25」です](https://twitter.com/Qiita/status/1593441648796524545)
:::

この記事は、「[完走賞ゲットのため小ネタ 25記事を投稿しようとチャレンジ v2 Advent Calendar 2023](https://qiita.com/advent-calendar/2023/youtoy)」の 20日目の記事です。

## 今回の内容
今回の内容は、以下の記事の続きとなるような内容です。
「イージング関数チートシートの関数」「p5.js の lerp()、frameCount」を組み合わせるという点では、同じです。

●「イージング関数チートシートの関数」「p5.js の lerp()、frameCount」を組み合わせたイージングの繰り返しの実装【完走賞ゲット-18】 #JavaScript - Qiita
　https://qiita.com/youtoy/items/06d4ef113175463ed4d7

上記の記事との違いは、弾む系のイージングを試したことと、今回試したイージングと上記の記事で使ったイージングの合計4つを、変な混ぜ方をして使ってみた点です。

### 動作時の様子
描画処理を動かした時の様子は、以下のとおりです。

<iframe width="560" height="315" src="https://www.youtube.com/embed/v0YpVgPIVEE?si=JlDjMG9iXoU865zh" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

### 実装した内容
まずは、実装した内容を掲載してみます。

```javascript
function setup() {
  createCanvas(600, 400);

  fill(100, 150, 200);
}

function draw() {
  background(20);

  const t = (frameCount % 120) / 120;

  const x1 = lerp(20, width - 20, easing(t, 3)),
    x2 = lerp(50, width - 50, easing(t, 4)),
    x3 = lerp(50, width - 50, easing(t, random([1, 2, 3, 4])));

  circle(x1, height * 0.25, 60);
  circle(x2, height * 0.5, 60);
  circle(x3, height * 0.75, 60);
}

function easing(t, num) {
  // https://easings.net/ja#easeOutQuart
  if (num === 1) return 1 - pow(1 - t, 4);
  // https://easings.net/ja#easeInOutQuint
  if (num === 2)
    return t < 0.5 ? 16 * t * t * t * t * t : 1 - pow(-2 * t + 2, 5) / 2;
  // https://easings.net/ja#easeInBounce
  if (num === 3) return 1 - easeOutBounce(1 - t);
  // https://easings.net/ja#easeOutBounce
  if (num === 4) return easeOutBounce(t);
}

function easeOutBounce(t) {
  const n1 = 7.5625;
  const d1 = 2.75;

  if (t < 1 / d1) {
    return n1 * t * t;
  } else if (t < 2 / d1) {
    return n1 * (t -= 1.5 / d1) * t + 0.75;
  } else if (t < 2.5 / d1) {
    return n1 * (t -= 2.25 / d1) * t + 0.9375;
  } else {
    return n1 * (t -= 2.625 / d1) * t + 0.984375;
  }
}
```

イージングは、以下の 4つを用いており、関数はイージング関数チートシートに掲載されたものを使いました。

1. easeOutQuart
1. easeInOutQuint
1. easeInBounce
1. easeOutBounce

動画では、円が 3つ動いていたと思います。
その 3つに適用した動きは、以下のとおりです。

1. easeInBounce
1. easeOutBounce
1. easing() が呼び出されるたびに、4つのイージングをランダムに選択

3つ目は、とびとびになる座標をランダムに選ぶような形になるので、残像が残りつつ動くような見た目になります。

## 今回の内容を試した背景
今回の内容を試そうと思ったきっかけは、1週間くらい前に記事に書いた、以下のイージングのブレンドが関係しています。
以下の記事のブレンドは、異なるイージングを順につないだようなブレンドをしているようでした。

●p5.js と Tween24.js を組み合わせたお試し：イージングのブレンド【完走賞ゲット-13】 #JavaScript - Qiita
　https://qiita.com/youtoy/items/24dae2f6c946b41d9c82

複数のイージングがブレンドされたものを使う、というのはこの時に初めて試しました。
それで、この異なるイージングのブレンド、という方向で、何か違った動きが作れないかと思って試したのが今回の内容でした。

## おわりに
今回、弾む系のイージングを 2つ試したり、その2つと別の 2つのイージングを変な混ぜ方をした処理を試してみました。

これまでは、たくさんあるイージングの中のいくつかを個別に適用するという形が主でしたが、複数のものを混ぜるという方向も試していければと思います。混ぜ方については、動きを制御するのに複数を混ぜ込むだけでなく、例えばある 1つのオブジェクトに関して色・形・動きなどといった複数の要素を変化させる際に、それぞれ異なるイージングで変化させるというようなこともできればと思っています。
「世界一流エンジニアの思考法」読了後感想まとめ


**米マイクロソフトシニアエンジニア、牛尾剛さんが書かれた「世界一流エンジニアの思考法」を読了しました。** 感想を書きたいと思います。

### 全体の感想

**私が日頃考えている内容と合致する部分が多く、読み終えた後ホッとすると共にやる気がみなぎる、そんな本でした。** （事実読了後すぐに本書のメソッドを実行に移しました）

**考えが合致した部分は「基礎理解重視」「健康第一」「ワークライフバランス」などです。** これらに関しては「このまま続けていってもいいんだな」と読了後安心感を得ることができました。

### どんな本か？

**著者の牛尾さんが「（牛尾さん的に）普通こうじゃないの？」と考えていたことや、仕事の進め方が、米マイクロソフトのスーパーエンジニアとの対話を通して徐々に変わっていく過程が描かれている本です。**

**あとがきにも書かれているのですが、有益な行動をどんどんプラスする本ではなく、無駄な行動をマイナスする（※1）方法が書かれている本です。** マイナスする対象は勉強法だけでなく、コミュニケーションやマネジメントまで幅広いです。

**マイナスするとは、自身の行動を振り返り、改善し、無駄をそぎ落とす事です。その結果、自己肯定感（※2）が上がります。** ここでいう無駄は「効率の悪い勉強法」「ネガティブマインド」などを指します。無駄をマイナスすると、自己肯定感が上がるだけでなく、アウトカムも最大化するので仕事でも成果を出すことができるようになります。

※1:本書の中で「マイナスする」という表現は使われていません。
「無くす」場合と「割合を減らす」場合があるため、表現したく「マイナスする」という表現を私が勝手に作りました。

※2:本書の中では自分自身や仕事をコントロールできている感覚、などと表現されています。

### 共感したフレーズ

（太字部分は本書より抜粋、太字以下は私のメモです。）

**どんなに頭がいい人でも理解には時間がかかるもの**
このフレーズでめちゃくちゃ安心しました。安心して技術書を周回できますよね。

**試行錯誤は「悪」である。**
何も考えずに手をいきなり動かすな、ファクトを積み重ね仮説を立ててそれを検証していこう。

**振る舞いが変わらずソリューションとしてシンプルなら、そのほうがより価値が高い**
自分が育てたコードに固執せず、良いものは取り入れよう。

**初歩の学習を「簡単だ」と馬鹿にせず、本当に一からやり直してみた**
C#のチュートリアルからやり直したらしい。私も大事にしているところ。わかっている（本当はわかっていると思い込みたい）と馬鹿にする状態は危険。

**Be Lazy**
本書では7つBe Lazyたる考えを挙げている。よく「最低限の努力」というフレーズがつよつよエンジニアから出るが、それは「考え抜かれた最低限の努力」ということ。適当にやるわけではない。

**スケジュール自体に価値はない**
スケジュールを守ることがそのビジネスに必須かどうかきちんと判断しようよということ。スケジュールに無理に合わせるのではなく、必要最小限のスコープでリリースするように調整するのもありなんですよ。

**過大な要求は人を追い詰める**
新人教育で自覚なくやっている人がいます。

**技術を徹底的に理解し、理解した情報の整理をして、すぐに取り出せるレベル１の状態にしてこそ、長い目で見たさいの生産性は上がる**
何勉強したら効率がいいですか？と聞く人に、「好きなことを、時間はかけて理解して」と今後は答えようと思いました。

**最初から全部説明せず、「情報量を減らす」コミュニケーションの仕方が重要（略）**
私は全部説明しようとして、私自身がよくわからなくなることがある。正確に説明したとて、相手がいっぺんにわかるわけないから対話しようということ。

**そこで意を決して、何かをしたら必ず完了まで一息にやるように意識した**
この記事を書いているのもこのフレーズの影響。この部分は自閉症気味やADHD気味の自覚がある人はぜひ読んでほしい。第6章です。

**「自分の人生や幸せに責任をもって、自分でコントロールする」**
「自分の事を自分でコントロールするとめっちゃハッピーですよ。」というのが本書のメッセージのように私は感じました。これを目指して日頃から基礎をおろそかにしないことを心掛けているので「めっちゃわかる～」となりました。

### 私がおすすめしたい人

**自分の仕事や勉強のやり方に自信が持てていない頑張り屋さんにおすすめしたいです。** 私自身年間1000時間近く仕事外で勉強しているのですが、もともと自己肯定感が皆無なため、天才は一発でなんでも理解できる超人だと誤解していました。しかし実態は陰に努力があることを知り、いつか私の努力も実を結ぶだろうと考えを転換できたからです。

https://amzn.to/3toCuoa
重なったデータのクラスタリング

・　データの内容からふたつのグループに分ける
・　ガウスモデルで近似
・　共分散行列



# データを分ける
ここでは、２変量データを、ふたつのグループに分けることをしてみます（クラスタリング）。

ひとつめのデータは簡単そうです。青グループと、赤グループ（実際は橙色）は離れているので、分けやすそうです。
<br>
<img width = 480 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333980/9a8afd06-59bb-6268-4db5-5f66a883a042.png">

<br>

# 混合ガウスモデル

混合ガウスモデルのクラスタリングを使って分けてみます。教師なし学習の一種なのですが、グループの数を指定する必要があります。「ガウスモデルを２個使ってフィッティング」を指示すると、このようにきれいに二つに分けてくれます。


<img width = 480 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333980/018d1616-4797-e478-611f-bfe9442e4cb3.png">


実は、青のデータと、赤のデータは、もともとガウスモデル（正規分布に由来するモデル）に少し手を加えてノイズを入れて作ってあるもので、混合ガウスモデルで上手くフィッティングできます。

今回使ったのは、MATLAB　Statistics and Machine Learning Toolbox という、統計と機械学習モデルのツールボックスです。けっこういろいろなものが入っていて、わりとお世話になってます。



# 重なりがある場合

二個目のデータは、次の図でみるように特徴的な分布をしています。何年か前に、こういうデータを見たことがあり、どうするんだろう？　という場面がありました。

実際のデータは人の運動の測定から出てきたもので、測定を含む、もっと複雑な経緯でできたものです。ここでは簡単にガウス分布をベースに共分散行列と呼ばれる 2 × 2 の行列を使って、似たようなものを作っています。

<img width = 480 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333980/59fdb9fc-0c46-f123-b07e-e0652036ada7.png">

クラスタリングには、上と同じように混合ガウスモデルを利用して計算してみます。

<img width = 480 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333980/bf2ae349-fb43-97eb-d761-ec3ad1d9ed34.png">

データがふたつのグループに分けられてて、青グループのガウスモデルと、赤グループのガウスモデルが、上手いことフィッティングされているように見えます。しかし、ここでふと疑問が。赤グループと、青グループが重なり合っている真ん中らへんはどうするんでしょう？　ある点が、赤グループか、青グループか、なんてわかるんでしょうか？

# 重なりをどうする？
真ん中の重なった部分に関しては、どちらのグループに属するかがわかりませんね。試しに、出てきたクラスタリングモデルの結果を見てみると、ちょうど上手く半分ずつになるように割り当ててあり、双方のグループは、おおむね両方とも1000個ずつのグループになっていました。

# どう利用する？
真ん中の部分がきれいにグループに分かれないのに、クラスタリングする意味があるかどうか？　と思われるかもしれません。このデータを使っていたときは、クラスタリングの結果を元にシミュレーションを作ることにしたんです。詳しくは長くなるのでここには書けませんが、青と赤、それぞれのガウスモデルの共分散行列から、シミュレーションで疑似データを生成して使うことができました。

教師なし学習は、データの内容そのものから規則性を見つけることで、クラスタリングなどが主な手法になると思います。宝探しみたいな側面があって、教師なし学習の結果からデータの特徴をみつけたときは、とても面白かった記憶があります。
Blazorアプリで2年間放置していたコードの警告と向き合います

# はじめに

[マークシートシステム Mark2](https://omr.mark2.org/)をUWPからBlazor WebAssemblyに移行して2年になりました。少しずつ利用者も増えているようです。

Blazor WebAssemblyに移行して以下のような警告が表示されていました。想定している動作には影響が無かったので警告を見なかったことにしていたのですが、そろそろ向き合うことにしました。

## GitHub Actionsでビルドしたときの警告

> deploy: Models/Survey.cs#L45
> Possible null reference assignment.
> 
> deploy: Pages/Index.razor#L319
> Possible null reference argument for parameter 'repositoryPayloadName' in 'void Survey.SetupPositionsFromRepository(string repositoryPayloadName)'.

## dotnet runで実行した時の警告

```zsh
% dotnet run
ビルドしています...
/Mark2/Models/Survey.cs(45,39): warning CS8601: Null 参照代入の可能性があります。
[/Mark2/Mark2.csproj]
/Mark2/Pages/Index.razor(307,49): warning CS8604:
'void Survey.SetupPositionsFromRepository(string repositoryPayloadName)'
内のパラメーター 'repositoryPayloadName' に Null 参照引数がある可能性があります。
[/Mark2/Mark2.csproj]
info: Microsoft.Hosting.Lifetime[14]
```

# 警告について調べる

発生している警告が何を示しているのか、まずはMicrosoftのドキュメントを見てみます。

https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/compiler-messages/nullable-warnings

Mark2で発生しているのは以下の警告でした。

- CS8601 - null 参照代入の可能性があります。
- CS8604 - パラメーターに null 参照引数がある可能性があります。

# 警告が表示されないように修正

Mark2でマークシートの画像処理をする際、以下の2種類のファイルを指定します。

1. マーク欄の座標を記述したエクセルファイル
1. スキャンしたマークシートの画像

学力調査のマークシートのように同一のフォーマットを多数の拠点で実施することがあります。そのため、エクセルファイルを指定するのではなく、URLのパラメーターを指定して外部のリポジトリから座標情報を読み込む方法を追加していました。

外部への通信は失敗することもあるのでnull許容値型を適切に使用する必要がありますが、それができていなかったようです。

と、このあたりでタイムアップになってしまい、ひとまず以下のようにして警告は表示されないようにしました。`!`を使ってしまったのはよくなかったかもしれません。

```diff:Models/Survey.cs
public class Survey
{
    public List<RepositoryPayload> repositoryPayloads = new();

    public async Task FetchRepository(string surveyId)
    {
        HttpClient client = new();
        string url = "https://repository.mark2.org/api/" + surveyId;
        var repository = await client.GetFromJsonAsync<Repository>(url);
        if (repository != null)
        {
            this.title = repository.name;
-           this.repositoryPayloads = repository.payloads;
+           this.repositoryPayloads = repository.payloads!;
        }
    }

-    public void SetupPositionsFromRepository(string? repositoryPayloadName)
+    public void SetupPositionsFromRepository(string? repositoryPayloadName)
    {
    }
}
```

# おわりに

きちんと解決できたわけではないのですが、これまで無視していた警告が何を意味していたのかを認識しました。すぐに修正できるかと思っていたのですが、一朝一夕には難しかったです。この冬はMark2のソースコードをきれいにしていきたいと考えています。

# その他、Mark2で取り組みたいこと

久しぶりにMark2のソースコードを眺めて、変数名の命名規則を公式ドキュメントに準拠させることを思い出しました。現状では変数名がcamelCaseだったり、Rubyで書いたプロトタイプの影響でsnake_caseだったりしています。

https://learn.microsoft.com/ja-jp/dotnet/csharp/fundamentals/coding-style/identifier-names

また、Blazor Advent Calendar 2023の14日目に投稿されていたBlazor WebAssemblyとOpenCVで画像処理をしている記事が興味深かったです。

https://koudenpa.hatenablog.com/entry/2023/12/14/000000

Mark2ではマークシートの四隅の矩形検出を連結領域の最大面積で求めていますが、OpenCVが使えるのであればOpenCVの矩形検出を使ったほうが精度がよくなりそうです。