OmniAICreator/Qiita-1.07M huggingface dataset:
LeetCodeを1日1題解いてみる (day17)

17日目に取り組んだ問題はこちら！

# 100. Same Tree

https://leetcode.com/problems/same-tree/description/

## 問題文
Given the roots of two binary trees p and q, write a function to check if they are the same or not.

Two binary trees are considered the same if they are structurally identical, and the nodes have the same value.

## 僕の回答 (失敗作)
```py
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
        stack = []
        result = [[None]] * 2

        for idx, curr in enumerate([p, q]):
            while curr or stack:

                while curr:
                    stack.append(curr)
                    curr = curr.left

                curr = stack.pop()
                result[idx].append(curr.val)
                
                curr = curr.right
        
        return result[0] == result[1]
```

## GPTの回答
```py
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
        stack = [(p, q)]

        while stack:
            node1, node2 = stack.pop()

            if not node1 and not node2:
                continue
            
            if not node1 or not node2 or node1.val != node2.val:
                return False

            stack.append((node1.left, node2.left))
            stack.append((node1.right, node2.right))

        return True
```

## 他の効率の良い回答例

```py
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
        if p==None and q==None:
            return True
        if p==None or q==None or p.val!=q.val:
            return False
        return(self.isSameTree(p.left,q.left) and self.isSameTree(p.right,q.right))
```

### コメント
一つ前に解いた問題の実装を活用しようと考えたが、うまくいかなかった。

### 次の問題はこちら!
https://qiita.com/h_y_s_d/items/0cd1f950d967d65d475f
【Build failed because of webpack errors】による'Unexpected end of JSON input' が突然起きた話

Next.jsを使用して開発している時に、突然陥ったエラーについて記録を残しておこうと思います📝

## 結論
**ローカルのnodeのバージョン(23.1.0)と、開発中アプリケーションが期待するnodeのバージョン(20.11.0)が異なっていた。**

（背景：他の言語の環境構築をしようとHomebrewを動かした時にどうやらnodeがバージョンアップされてしまったようです。絶対的にこれが原因かわからないですが、これくらいしか思い当たるものがないため..）

## 状況の詳細
- `npm run dev`では何もエラーが起こらず、正常に動作。
- `nom run buil`において下記のエラーが発生。
    ```bash
    client %  npm run build
    
    > client@0.1.0 build
    > next build
    
      ▲ Next.js 14.2.11
      - Environments: .env
    
       Creating an optimized production build ...
    Failed to compile.
    
    ./node_modules/next/dist/build/webpack/loaders/next-app-loader.js?
    ..
    ..
    ..
    ..
    ..... + 4 modules
    Unexpected end of JSON input
    
    ./node_modules/next/dist/build/webpack/loaders/next-app-loader.js?..
    ..
    ..
    ..
    .....  + 1 modules
    Unexpected end of JSON input
    
    ./node_modules/next/dist/build/webpack/loaders/next-app-loader.js?..
    ..
    ..
    ..
    ..... + 1 modules
    Unexpected end of JSON input
    
    ./node_modules/next/dist/build/webpack/loaders/next-app-loader.js?..
    ..
    ..
    ..
    .....  + 1 modules
    Unexpected end of JSON input
    
    ./node_modules/next/dist/build/webpack/loaders/next-app-loader.js?..
    ..
    ..
    ..
    .....  + 1 modules
    Unexpected end of JSON input
    
    
    > Build failed because of webpack errors
    ```

## 原因特定のために試したこと
- 自分の環境が原因かを確認する（Xや公式の情報をチェックしたり、周りの人に聞く）
- `.next`、`node_module`、`package-lock.json`の削除→再度インストール
- `prisma generate`してみる
- ローカルの別フォルダにクローンして動かしてみる
- nextのバージョンがおかしくなってないか確認
- npm のバージョン確認
- npm のキャッシュ削除
- nodeのバージョン確認 ← これだった

## 原因特定後にやったこと
- `nvm`のインストール
    ```bash
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
    ```
　
- シェル再起動 or 以下実行
    ```bash
    export NVM_DIR=“$([ -z “${XDG_CONFIG_HOME-}” ] && printf %s “${HOME}/.nvm” || printf %s “${XDG_CONFIG_HOME}/nvm”)“[ -s “$NVM_DIR/nvm.sh” ] && \. “$NVM_DIR/nvm.sh” # This loads nvm
    ```
　
- 欲しいnodeのバージョンのインストール
    ```bash
    nvm install 20.11.0
    ```
　
- インストールしたバージョンのnodeを適用（これやらなくてもinstallで勝手にセットされた感じではありましたが一応）
    ```bash
    nvm use 20.11.0
    ```
　
- nodeのバージョン確認
    ```bash
    node -v
    ```
　
- `.next`, `node_modules`, `package-lock.json`の削除
　
- npm のキャッシュ削除（マストなのかわからないですが一応）
    ```bash
    npm cache clean --force
    ```
　
- 依存関係のインストール
    ```bash
    npm install
    ```
　
- ビルドを試す（成功）
    ```bash
    npm run build
    ```

## おわりに
もし同じような状況に遭遇した方がいたときに、少しでも参考にれば幸いです。
Laravel6/PHP7でのセッション管理をRedisからDynamoDBに変更する

Laravel6/PHP7/Redisで構成されたシステムの、セッションストアで使用していたRedis部分をDynamoDB(AWSのNoSQLデータベース)に置き換えたときのメモです。

LaravelもPHPもバージョン古めですがごめんなさい。

```terminal:terminal
% php artisan -V         
Laravel Framework 6.20.45

% which php
/usr/local/opt/php@7.3/bin/php
```

Laravel で DynamoDB を使うための AWS SDK for PHP は2024年11月時点での最新版（バージョン3.326.0）を入れています。
AWS SDK for PHP のインストール方法やAWSのアクセスキーID確認方法などは今回記載しません。
```php:php
dd(\Aws\Sdk::VERSION);

"3.326.0"
```

## セッションの保存先をRedisからDynamoDBへ変更

### 1) .env を修正

それではまず、 ```.env``` ファイルを修正していきます。

```php:.env
# 中略

SESSION_DRIVER=redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
```

↑これをこうします。↓

```php:.env
# 中略

SESSION_DRIVER=dynamodb
AWS_REGION=ap-northeast-1
AWS_ACCESS_KEY_ID=your_aws_access_key_id
AWS_SECRET_ACCESS_KEY=your_aws_secret_access_key
DYNAMODB_SESSION_TABLE=table_name
DYNAMODB_PARTITION_KEY=partition_key_name
```

### 2) app/Providers/AppServiceProvider.php を修正

次に ```app/Providers/AppServiceProvider.php``` を修正します。

実際のコードでは ```.env``` の値をそのまま呼び出さずconfig挟んでから呼び出したりはしていますが、シンプルに書くと以下のような感じかと。

```php:app/Providers/AppServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Routing\UrlGenerator;
use Illuminate\Support\Facades\Session;
use Aws\DynamoDb\SessionHandler;
use Aws\DynamoDb\DynamoDbClient;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot(UrlGenerator $url)
    {
        $dynamoDb = new DynamoDbClient([
            'region'  => env('AWS_REGION'),
            'credentials' => [
                'key'    => env('AWS_ACCESS_KEY_ID'),
                'secret' => env('AWS_SECRET_ACCESS_KEY'),
            ],
            // PHP7でAWS SDK for PHPを使うと出てくる警告を抑制
            'suppress_php_deprecation_warning' => true,
        ]);

        $handler = SessionHandler::fromClient($dynamoDb, [
            'table_name' => env('DYNAMODB_SESSION_TABLE'),
            'hash_key' => env('DYNAMODB_PARTITION_KEY'),
        ]);

        Session::extend('dynamodb', function ($app) use ($handler) {
            return $handler;
        });
    }
}
```

基本これだけだったと思います。

いろいろな記事やサイトを見ているとカスタムのセッションハンドラーを自作してファイル配置しているような内容も多かったのですが、せっかくSDKを導入しているので一番シンプルな方法をメモしておこうと思いました。

変なところがあったらぜひ教えてください。

#### 参考URL
[aws SDK for PHP 3.x APIリファレンス　- Aws/DynamoDb/DynamoDbClient](https://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.DynamoDb.DynamoDbClient.html)
[LaravelでAWS SDKのS3を扱う](https://qiita.com/silver40/items/b704a8b4e7582e4e1132)
[Laravel 6.x（またはLumen 6.x）でDynamoDBに接続する](https://qiita.com/k_takaya/items/075c470ee80cddc95252)
[Laravel 8でセッションドライバーをDynamoDBに設定](https://qiita.com/Yudetahakusai/items/a9fda6938b02774951b8)
【Web】プロバイダとは

# はじめに
こんにちは！アメリカの大学で語学を学びながら、独学でソフトウェアエンジニアを目指している者です。

インターネットは現代社会に欠かせない存在ですが、その仕組みを詳しく理解している人は少ないのではないでしょうか？
調べても「プロバイダはインターネットを提供するために必要な存在」という抽象的な説明が多く、具体的なイメージがつかみにくいですよね。

そこで今回は、皆さんが日常的に利用する携帯キャリアやWi-Fiサービスを例に挙げながら、「プロバイダ（ISP）」について説します。
この記事を読むことで、プロバイダがどのようにインターネット接続を支え、格安SIMやWi-Fi業者がどのような役割を果たしているのかを理解できるはずです。

この記事の対象者はほんとにWebの勉強初心者なのであしからず。

# プロバイダ（ISP）とは？
プロバイダ（ISP: Internet Service Provider）は、インターネット接続サービスを提供する業者のことです。
スマートフォンやWi-Fiを使ってインターネットに接続するとき、このプロバイダがデータ通信の中継や管理を行っています。

プロバイダは、以下の役割を果たしています
* ネットワークの中継
インターネット全体にアクセスするための接続を提供。
* IPアドレスの割り当て
ユーザーごとに一意のアドレスを割り当て、通信を可能にする。
* トラフィックの管理
データが効率よく送受信されるように調整。

# プロバイダの階層構造：一次ISP、二次ISP、三次ISP
プロバイダには役割の違いによる階層構造があります。それぞれを簡単に説明します。

### 一次ISP（Tier 1 ISP）
世界規模のインターネット接続網を持ち、他のプロバイダに依存せず直接インターネット全体にアクセス可能で国際通信も担います
例をあげるとNTTコミュニケーションズ、KDDI、ソフトバンクテレコムなどがあります。

### 二次ISP（Tier 2 ISP）
一次ISPのネットワークを借りて、一般の家庭や企業にインターネット接続サービスを提供しています。
主に固定回線（Wi-Fiサービス）や携帯キャリア（モバイル通信）を通じてユーザーとインターネットをつなぐ役割を果たしています。
例を挙げると、楽天モバイル、auひかり、OCNなどがここに含まれます。

### 三次ISP（Tier 3 ISP）
二次ISPのネットワークを借りてさらに小規模なサービスを提供する業者。
格安SIM（MVNO）や一部の地域限定Wi-Fiサービスがこれに該当。

# 一次ISPか二次ISPはどうやって決めているの？
一次ISPと二次ISPは、そのプロバイダが直接的な国際通信網を保有しているかどうかで区別されます。

## 大手キャリア（NTT、KDDI、ソフトバンク）の場合
これらのキャリアは、国内外に広がる通信網を持ち、インターネットバックボーン（基幹ネットワーク）に直接接続しているため、一次ISPに分類されます。
たとえば、ソフトバンクは国際的なケーブル網を保有しており、日本国内だけでなく、世界中の通信を担っています。

## 楽天モバイルの場合
楽天モバイルは自社で基地局を持ち、国内の通信網を構築しています。
しかし、楽天モバイルは国際通信網を保有しておらず、トラフィックの一部を一次ISP（たとえばKDDIやソフトバンク）に依存しています。
そのため、楽天モバイルは二次ISPに分類されます。

# 格安SIMの例：三次ISPになる理由
格安SIM事業者（MVNO: Mobile Virtual Network Operator）は、自社でインターネット接続網や基地局を持たず、大手キャリア（MNO: Mobile Network Operator）のネットワークを借りてサービスを提供します。

たとえば、IIJmioやmineoといった格安SIMは、楽天モバイルやソフトバンクなどのネットワークを利用してサービスを展開しています。これが三次ISPと分類される理由です。

* 自社でネットワークを持たない
* 二次ISPから借りた回線を利用してサービスを提供
* その結果、コストを削減し、安価なプランを提供可能

# まとめ
この記事では、プロバイダの役割や階層構造について、身近な例を挙げながら解説しました。以下が主なポイントです：

* 一次ISP
国際通信網を保有し、世界規模のネットワークを管理
* 二次ISP
一次ISPのネットワークを借りて、一般家庭や企業に接続サービスを提供
* 三次ISP
二次ISPのネットワークを借りて、格安SIMや地域限定のサービスを展開

楽天モバイルのような新興キャリアがどのような位置づけにあるのかを理解することで、インターネット接続の仕組み全体をイメージしやすくなったのではないでしょうか？

普段はRuby関連の記事を中心に書いていますが、インターネットの仕組みなど、周辺知識にも目を向けていきます。ぜひ次回の記事もお楽しみに！
【git-hub】Your personal access token (classic) is about to expire と言われた時の対応

# 前提
　MacでGit-Hub、Sourcereeを使用している。

# 概要
　以前に作ったアクセストークンに期限を設けていると、期限切れ時にメールが届く。
　再作成することで、再度git-hubが使えるようになる。

# 1. access token 再作成

　メール記載のURLに飛んで、アクセストークンをリジェネレイトする
　作られたキーをメモ帳に取っておく。
 　※あとからコピーできないので注意。もしコピー漏れしたら、作り直すこと

# 2. キーチェーンアクセス再設定

　キーチェーンアクセスで「git」などで検索し、でてきたものを右クリックから削除
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3850966/75f7b7f5-344f-84c9-b470-f16ecb43e18a.png)

# 3. Sourcetreeに設定

　SourceTreeを起動するとパスワードを聞かれるため、1のアクセストークンを設定する。

 # 参考：
 https://qiita.com/noid11/items/580996fd5918cad056d7
故障診断とデバッグは同じ。

# 先入観、思い込みは捨てよう

これに尽きます。結論です。
---

### デバッグの考え方

**デバッグとは**  
デバッグは、プログラムのバグを見つけて解決するプロセスです。


**デバッグのステップ**
1. **証拠集め（情報収集）**
    - エラーの確認
    - 動かない状況を特定
    - 確実に動作する部分の確認

2. **証拠を解釈（情報の意味を把握）**
    - エラーメッセージの意味を理解
    - 翻訳ツールや検索で情報を収集
    - 同じ問題を経験した人を探す

3. **犯人を推理（原因を推測）**
    - 問題の箇所を特定
    - ブレークポイントで値を確認

**具体例**
`undefind method 〇〇 `というエラーが出た場合、エラーメッセージを翻訳し、原因を調べることが重要です。

---

### 故障診断手順と考え方

クルマの不具合解消には「故障診断」という重要な工程があります。この工程を無視すると、修理がうまくいかないことがあります。

**故障診断のフロー**
1. **不具合状況の把握**
    - 事実を整理し、詳細な状況を把握

2. **不具合箇所・原因の推測**
    - 得られた情報から仮説を立て、優先順位をつける

3. **原因追及（測定、目視点検など）、判定**
    - 仮説を基に点検し、NG箇所を特定

4. **修理方法の決定、部品調達**
    - 修理方法や部品の調達方法を決定

5. **修理**
    - 決定した方法に従って修理を実施

6. **完了確認（試運転など）**
    - 作業後に動作確認を行う

**ヘッドライト接触不良の例**
特定の箇所が接触不良を起こす場合、ピンの調整や配線のバイパスなどの対応が必要です。

カイエンのヘッドライトは、着脱が比較的簡単ですが、コネクタの接触不良が報告されています。特に長期間使用すると、コネクタの接触不良が発生しやすくなることがあります。これは、ヘッドライトの取り付け部分が時間とともに劣化するためです。

もし接触不良が発生している場合は、コネクタを清掃するか、交換することを検討してみてください。




以上
Test Double, Dummy, Stub, Spy, Mock の違いは？

# はじめに

呼び出すとコストがかかる処理やそもそもテスト環境で呼び出せない処理を「モックする」ことはよくある。ただ「モック」に関する用語が色々あってよくわからない 🤯

<img title='ねねっち.png' alt='ねねっち' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6697/58d370de-0c82-e115-dbbe-acaad2a1eb14.png' width="800">


# この記事は？

- 『[Clean Craftsmanship 規律、基準、倫理](https://www.kadokawa.co.jp/product/302206001224/)』という書籍で説明されている定義を紹介する
  - 原典は [EndoTesting at XUnitPatterns.com](http://xunitpatterns.com/EndoTesting.html)
-  RSpec の文脈だとまた話が変わってきそう

# 説明

Test Double, Dummy, Stub, Spy, Mock は並列なものというわけではない。階層構造になっている。

```plantuml
@startuml
abstract class "Test Double"
class "Dummy"
class "Stub"
class "Spy"
class "Mock"

"Test Double" <|-- "Dummy"
"Dummy" <|-- "Stub"
"Stub" <|-- "Spy"
"Spy" <|-- "Mock"
@enduml
```

## Test Double

<img alt='カストロ' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6697/7e055d5c-bed2-7f29-eb54-d211210223f0.png' width="300">

- あるオブジェクトの代わりを演じる
- double: 代役、影武者
  - 俳優の代わり: スタントダブル
  - 俳優の手の代わり: ハンドダブル
  - 俳優の身体の代わり: ボディダブル

## Dummy

<img alt='身代わり人形' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6697/49b8096d-31f3-eef4-6608-4ee21014bf61.png' width="250">

- 何もしない実装を持つテストダブル
  - メソッドが値を場合は null や 0 を返す
- dummy: マネキン人形、模造品

## Stub

<img alt='きこりの切り株' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6697/1afe10e6-ba9f-48ee-cbcd-8c37d3943d54.png' width="250">

- メソッドが null や 0 ではなく、固有の値を戻すダミー
  - テストする経路に関数を仕向ける。 
- stub: (鉛筆などの) 使い残り、半券、切り株

## Spy

<img title='image.png' alt='image' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6697/611ccdc4-97ff-092c-0011-66347ddc8688.png' width="300">

- 何が行われたかを記憶するスタブ
- spy: スパイ、〜をひそかに調べる

## Mock

<img alt='あざ笑う' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6697/a97ead12-42f2-9f6b-97b1-4839c6c50e3d.png' width="259">

- メソッドが null や 0 ではなく、固有の値を戻すダミー
- 何が行われたかを記憶するスタブ
- 何が期待されているかを把握し、その期待に基づいてテストを成功あるいは失敗させるスパイ
- mock: 〜をあざ笑う、模擬の、偽の

# 参考

## Web

- [Test Double Patterns at XUnitPatterns.com](http://xunitpatterns.com/Test%20Double%20Patterns.html)
- [これで迷わないテストダブルの分類(ダミー、スタブ、スパイ、モック、フェイク) - Qiita](https://qiita.com/marchin_1989/items/3abaf7d57c501bb2c5a6)
- [instance_doubleとinstance_spyの使い分け](https://mogulla3.tech/articles/2020-07-04-01)
- [Spies - Basics - RSpec Mocks - RSpec - Relish](https://relishapp.com/rspec/rspec-mocks/docs/basics/spies)

## 書籍

- [Clean Craftsmanship 規律、基準、倫理](https://www.kadokawa.co.jp/product/302206001224/)
  - 第 3 章: テスト駆動開発応用 > テストダブル
Laravelのリレーション

# Laravelのリレーション
Eloquentを用いることで、テーブルと対応するモデル間のリレーションを簡単に設定することができる。
リレーションのパターンは下記3種類。
- 一対一
- 一対多
- 多対多

# パターンごとのリレーションの書き方
下図のようなテーブルを想定
![LaravelリレーションのER図サンプル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1830892/c0b566da-0055-2d43-0998-5899fe3365e1.png "ER図")

各モデルクラスにリレーションをメソッドとして定義する。
## 一対一
```php:UserモデルがProfileモデルを1つ所有する →hasOne（Userモデルに定義）
public function profile(){
    return $this->hasOne(Profile::class);
}
```
```php:ProfileモデルがUserモデルに属する →belongsTo（Profileモデルに定義）
public function user(){
    return $this->belongsTo(User::class);
}
```
※メソッドは利用するものだけを定義すればよい。

## 一対多
```php:Userモデルが複数のPostモデルを所有する →hasMany（Userモデルに定義）
public function posts(){
    return $this->hasMany(Post::class);
}
```
```php:Postモデルが1つのUserモデルに属する →belongsTo（Postモデルに定義）
public function user(){
    return $this->belongsTo(User::class);
}
```

## 多対多
```php:Userモデルが複数のRoleモデルを所有する →belongsToMany（Userモデルに定義）
public function roles(){
    return $this->belongsToMany(Role::class);
}
```
```php:Roleモデルが複数のUserモデルを所有する →belongsToMany（Roleモデルに定義）
public function users(){
    return $this->belongsToMany(User::class);
}
```

デフォルトの命名規則が適用されない場合（中間テーブル名や外部キーの命名が標準と異なる場合）は次のように明示的に定義する必要がある
※今回の場合であれば不要
```php:Roleモデルが複数のUserモデルを所有する →belongsToMany（Roleモデルに定義）
//('関係するモデル', '中間テーブル', '中間テーブル外部キー', '中間テーブル外部キー(関係するモデル)');
public function users(){
    return $this->belongsToMany(User::class, 'role_user', 'role_id', 'user_id');
}
```

## リレーションを利用したデータ取得のサンプル
### 一対一のリレーション
```php:IDが1のuserのprofileを取得
$user = User::find(1);  // IDが1のUserを取得
$profile = $user->profile;  // Userに関連するProfileを取得
```
### 一対多のリレーション
```php:IDが1のUserの全てのPostのcontentを取得
$user = User::find(1);
$contents = $user->posts->pluck('content');
```
### 多対多のリレーション
```php:"育成"を含むdescriptionのRoleを持つUserを全て取得
$users = User::whereHas('roles', function ($query) { // Userモデルに関連する Roleモデルの条件に基づいて Userを絞り込み
    $query->where('description', 'like', '%育成%');
})->get();
```

### 参考記事
- [リレーションって何](https://qiita.com/Tunapon/items/14c3febf3f2da1ef217d)
- [Laravel 学習記録 #008 リレーションを学ぶ](https://note.com/mura_lara/n/n8b0dc0cd54a5)
- [Laravel Eloquentのリレーションの種類を徹底解説](https://kinsta.com/jp/blog/laravel-relationships/)
- [【Laravel】WhereHasの使い方・デメリット](https://qiita.com/monji586/items/7e20ec601cefdf9140e6)
SQLパズル 29 最頻値を求める　解法メモその３

# 概要
p126 29 最頻値を求める　解法メモその３

Having句とALL述語を組み合わせて最頻値を求めています。



# 要件

支払い伝票に対して、金額の最頻値を求めたい。
※最頻値とは、母集団の中で最も多かった値

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/73f6a888-9d71-137b-8995-3a92413b9f2a.png)


# SQL

## DDL
```sql
drop table if EXISTS Payroll;
create table Payroll(
    check_nbr Integer NOT NULL Primary Key,
    check_amt DECIMAL(8,2) NOT NULL
);

INSERT INTO Payroll VALUES(1, 100);
INSERT INTO Payroll VALUES(2, 100);
INSERT INTO Payroll VALUES(3, 200);
INSERT INTO Payroll VALUES(4, 150);
INSERT INTO Payroll VALUES(5, 300);
INSERT INTO Payroll VALUES(6, 150);
INSERT INTO Payroll VALUES(7, 300);
INSERT INTO Payroll VALUES(8, 300);
INSERT INTO Payroll VALUES(9, 100);
```



## 答えのSQL
ALL述語を使っています。
Having COUNT(*) >= ALL ()なので、COUNT(*)が最大値の時以外　偽です。
今回の場合だと
check_amtが
300,100 →最大値の３なので　3 > ALL(3,2,1)を満たすので真
150,200 → 1 or 2なので　 1 or 2 >ALL(3,2,1)を満たさないので偽

```sql
SELECT check_amt,COUNT(*) AS check_cnt
FROM Payroll
GROUP BY check_amt
HAVING COUNT(*) >= ALL (SELECT COUNT(*) AS check_cnt
                        FROM Payroll
                        GROUP BY check_amt)
                        ;
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/7cdbee46-7a63-cdb1-077f-1934f60f635e.png)

# 参考

SQLパズル　p126 29 最頻値を求める　その3

SQLパズル　サポートページ
https://mickindex.sakura.ne.jp/database/db_support_sqlpuzzle.html#LocalLink-p29

達人に学ぶSQL徹底指南書第２版 p111 最頻値を求める　ALL述語の利用

github
https://github.com/RYA234/SQL_Puzzle_Learning/commit/e9f30131f0bff66e2151704836ca7a74a8033894
HelmCharts使用時のPriorityClass変更

## 概要

dcgm-exporter（NVIDIA Device Plugin）をkube-system以外のnamespaceにデプロイしようとした際、DaemonSetがDesiredを持つものの、Warningが出てポッドが作成されない

```
Type: warning
Reason: failedCreate
From: daemonset-controller
Message: Error creating: insufficient quota to match these scopes: [{priorityClass In [system-node-critical system-cluster-critical]}]
```

## 原因

上記のエラーメッセージにあるように、PriorityClassの設定が原因です。
dcgm-exporterはデフォルトで`system-node-critical`というPriorityClassを使用しようとしますが、このPriorityClassは`kube-system`ネームスペース以外では使用が制限されています。

### そもそもPriorityClassとは(Claude君による説明)

PriorityClassは、Kubernetesにおいてポッドの優先順位を定義するリソースです。主な役割は：

- ポッドのスケジューリング優先順位の決定
- リソース競合時の振る舞いの制御
- システムクリティカルなポッドの保護

特に`system-node-critical`や`system-cluster-critical`といった高優先度のPriorityClassは、通常システムコンポーネント用に予約されており、`kube-system`ネームスペースでのみ使用可能です。

## 解決方法

DaemonSetにパッチを適用することで解決できました。
`ValuesInline`でがんばって変更しようとしたけどうまくいかなかった。

```yaml
kind: Kustomization
helmCharts:
- name: dcgm-exporter
  # 他の設定...

patches:
- patch: |
    - op: add
      path: /spec/template/spec/priorityClassName
      value: ""  # または任意のPriorityClass名
  target:
    kind: DaemonSet
    name: dcgm-exporter
```
Rails8で採用されている「Thruster」の主な特徴５選

Rails 8で採用された「Thruster」は、Pumaウェブサーバーの前に配置されるHTTP/2プロキシで、以下の特徴を持ちます：

1. **HTTP/2サポート** ThrusterはHTTP/2をサポートし、より高速で効率的な通信を実現します。

‌

1. **自動TLS証明書管理** Let's Encryptを利用して、TLS証明書の自動取得と更新を行い、HTTPS対応を簡素化します。

‌

1. **アセットのキャッシングと圧縮** 静的ファイルの効率的な配信をサポートし、アセットのキャッシングと圧縮を行います。

‌

1. **X-Sendfileサポート** X-Sendfileヘッダーをサポートし、静的ファイルの配信を効率化します。

‌

1. **シンプルな設定** 設定ファイルを持たず、環境変数で動作を制御するため、シンプルな構成が可能です。

これらの機能により、ThrusterはNginxなどの外部ウェブサーバーを必要とせず、Railsアプリケーションのデプロイメントを簡素化します。
2024/11/15 Spring MVC DoS脆弱性 (CVE-2024-38828)




# Spring MVCで発生するサービス拒否（DoS）脆弱性。

https://spring.io/security/cve-2024-38828


- 韓国人として、日本語とコンピュータの勉強を同時に行うために、ここに文章を書いています
- 翻訳ツールを利用しているため、不自然な表現があるかもしれません。
- 内容が正確でない可能性があります。ご意見をいただけると幸いです

## 問題の状況
- `@RequestBody`と`byte[]`パラメーターを使用するコントローラーメソッドがDoS（サービス拒否）攻撃にさらされる可能性があります


> DoS（Denial-of-Service attack）とは？
- 攻撃者が特定のマシン、ネットワーク、またはホストに過剰なトラフィックを発生させたり、脆弱性を悪用したりして、サービスが正常に動作しなくなるようにするサイバー攻撃

https://en.wikipedia.org/wiki/Denial-of-service_attack

## 脆弱性
- Spring MVCが`byte[]`でリクエストボディを逆シリアライズする際、過剰に大きいまたは悪意を持って操作されたリクエストを処理することで、メモリ不足が発生する可能性があります
```java
@RestController
public class ExampleController {

    @PostMapping("/upload")
    public ResponseEntity uploadFile(@RequestBody byte[] fileData) {
        // ... 
    }
}
```


## 脆弱なバージョン

-  Spring Framework 5.3.0から5.3.41までのバージョン
- より古いサポートが終了したバージョンも影響を受けます

| バージョン | 状態 |
|-----------|------|
| 5.3.0 ~ 5.3.41 | 脆弱性あり |
| サポート終了の古いバージョン | 脆弱性あり |



## 推奨事項
- Spring Framework 5.3.42以上にアップグレードして脆弱性を解消してください
- サポートが終了した古いバージョンでは、メソッドパラメーターをbyte[]ではなくInputStreamに変更することで脆弱性を緩和することが可能です。
```java
@RestController
public class ExampleController {

    @PostMapping("/upload")
    public ResponseEntity<String> uploadFile(InputStream inputStream){
        // ... 
    }
}
```
メモ：Jacocoで打鍵試験のカバレッジレポートを出力する

## Jacocoで打鍵試験のカバレッジレポートを出力する

pom.xmlに以下を追記する。

```xml:pom.xml
<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.10</version>
    <executions>
        <execution>
            <id>default-prepare-agent</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <execution>
            <id>report</id>
            <phase>verify</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
</plugin>
```

コマンド実行する。

```:jarファイルを出力
mvn clean package
```

```:アプリケーションを実行
java -javaagent:パス/jacocoagent.jar=destfile=jacoco.exec -jar jarファイルパス
```
※-javaagentオプションは、-jarオプションの後に記述することはできません。
-javaagentオプションはJVM起動時のオプションであり、-jarの前に指定する必要があります。

```:jacoco.execをもとにしてhtmlを出力
mvn jacoco:report
```

target\site\jacoco配下にhtmlが出力されていればOK。
rosbag(mcap)に記録された各トピックサイズを求める

### コード
``` python
from mcap.reader import make_reader
from mcap_ros2.decoder import DecoderFactory
from tqdm import tqdm


mcap_file = "hoge.mcap"

topic_sizes = {}

with open(mcap_file, "rb") as f:
    reader = make_reader(f, decoder_factories=[DecoderFactory()])
    for schema, channel, message, ros_msg in tqdm(reader.iter_decoded_messages(), dynamic_ncols=True):
        topic = channel.topic
        msg_size = len(message.data)

        if topic not in topic_sizes:
            topic_sizes[topic] = 0
        topic_sizes[topic] += msg_size

for topic, size in topic_sizes.items():
    # バイトからMBに変換
    size_mb = size / (1024 * 1024)
    print(f"Topic: {topic}, Size: {size_mb:.2f} MB")

print(f"Total size: {sum(topic_sizes.values()) / (1024 * 1024):.2f} MB")

```

### 実行結果
```
383109it [01:09, 5543.74it/s]
Topic: /topic1, Size: 3.01 MB
Topic: /topic2, Size: 4.02 MB
Total size: 7.03 MB
```
Rails8で採用されている「Kamal 2」の主な特徴４選

Rails 8で採用されている「Kamal 2」は、デプロイメントを大幅に簡素化するツールです。その主な特徴は以下の通りです：

1. **単一コマンドでのサーバーセットアップ** Kamal 2を使用すると、`kamal setup`コマンド一つでLinuxサーバーをアプリケーションサーバーに変換できます。これにより、クラウドVMや自社サーバーへのデプロイが容易になります。

‌

1. **Thrusterとの統合による高速デプロイ** Kamal 2は、Thrusterという新しいプロキシと統合されており、高速なゼロダウンタイムデプロイやSSL証明書の自動化を実現します。これにより、Nginxなどの外部ウェブサーバーが不要となり、デプロイメントの複雑さが軽減されます。

‌

1. **複数アプリケーションのサポート** Kamal 2は、単一のサーバー上で複数のアプリケーションを同時にホスティングすることが可能です。これにより、サーバーリソースの効率的な活用が可能となります。

‌

1. **自動SSL証明書の取得と更新** Let's Encryptを利用して、SSL証明書の自動取得と更新を行います。これにより、HTTPS対応が容易になり、セキュリティが強化されます。

‌

1. **Dockerベースのデプロイ** Kamal 2はDockerを基盤としており、Docker化されたアプリケーションであれば、Rails以外のフレームワークでもデプロイが可能です。また、Dockerがインストールされていないサーバーでも、Kamal 2が自動的にインストールを行います。

‌

これらの特徴により、Kamal 2は開発者がインフラの専門知識を持たなくても、簡単かつ効率的にアプリケーションをデプロイできる環境を提供します。
LeetCode解説　No.6 Zigzag Convention [Go]

問題：https://leetcode.com/problems/zigzag-conversion/description/?envType=study-plan-v2&envId=top-interview-150

この問題では、文字列をジグザグの形に並べて、その結果を読み取るということを求めています。

**問題の流れ**
1,ジグザグパターンを作る
与えられた文字列を指定された行数でジグザグ状に並べる。

2,ジグザグの並びを読み取る
ジグザグパターンを行ごとに読み取り、1つの文字列として結合する。

**具体例**
入力:
PAYPALISHIRING (文字列)
numRows = 3 (行数)

まず、この文字列を3行のジグザグパターンで配置します。

最初の文字 P を1行目に置きます。
次の文字 A を2行目に。
次の文字 Y を3行目に。
その次の文字 P を再び2行目に戻ります。
さらに次の文字 A を1行目に戻ります。
こうして「ジグザグの順序」で配置されます。
```
P   A   H   N
A P L S I I G
Y   I   R
```

文字の並び方として，
1, 上から下へ移動（各行に文字を順番に置く）。
2, 一番下の行に到達したら、上へ戻る。
3, 一番上の行に到達したら、再び下に移動する。

となっています.

それではGolangで実装してみます．

```
package main

func convert(s string, numRows int) string {
	if numRows == 1 {
		return s
	}

	rows := make([]string, min(numRows, len(s)))
	curRow := 0
	goingDown := false

	for _, c := range s {
		rows[curRow] += string(c)
		// 一番上か一番下の行に到達したら方向を変える
		if curRow == 0 || curRow == numRows-1 {
			goingDown = !goingDown
		}
		// 一行進む
		if goingDown {
			curRow++
		} else {
			curRow--
		}
	}
	result := ""
	for _, row := range rows {
		result += row
	}
	return result
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

```

**コードの詳細解説**
なぜ min(numRows, len(s)) なのか？
A. numRows が len(s) より大きい場合の最適化
例えば、文字列 s = "ABC" で numRows = 5 の場合を考えてみます。この場合：

実際に必要な行数は、最大でも文字列の長さ len(s) = 3 行です。
文字列が3文字しかないため、5行のうち3行だけ使われ、残りの2行は空になります。
Rails6の主な特徴１０選

Rails 6は、モダンなアプリケーション開発をサポートするために多くの新機能と改善を導入しました。以下は、Rails 6の主要な特徴です

---

### **1. Action Mailbox**

- 受信したメールをアプリケーションで処理する新しいフレームワーク。
- メールをデータベースに保存し、その内容を解析して処理可能。
- 例えば、サポートメールの自動処理やブログ投稿のメール送信を通じた投稿管理などに利用。

---

### **2. Action Text**

- リッチテキスト編集と保存を統合する新しいフレームワーク。
- Trixエディタを使用して、ユーザーが簡単にリッチテキストを作成可能。
- リッチテキストデータ（画像、リンクなどを含む）をActive Storageで管理。

---

### **3. 並列テストのサポート**

- テストを並列に実行できる機能が追加され、テストスイートの実行速度が向上。
- デフォルトで複数のCPUコアを利用可能。

---

### **4. Webpackerの公式採用**

- Rails 6では、Webpackerが標準のJavaScriptビルドツールとして採用されました。
- モダンなJavaScriptフレームワーク（React, Vue.js, Angularなど）の統合が容易に。

---

### **5. Multiple Databases（マルチデータベース）のサポート**

- 複数のデータベースを簡単に管理可能。
- プライマリデータベースとレプリカデータベースを簡単に設定し、読み取り専用クエリをレプリカに送信。
- 高可用性やスケーラビリティをサポート。

---

### **6. Active Storageの強化**

- Rails 5.2で導入されたActive Storageがさらに進化。
- 複数ファイルの直接アップロードや画像処理機能の改善。
- サービス間でのデータ移行（例：S3からGoogle Cloudへの移行）をサポート。

---

### **7. Action Cableの改善**

- WebSocketを活用したリアルタイム機能をさらに強化。
- 複数の接続ポイントやバックエンドサービスのスケーリングに対応。

---

### **8. Zeitwerkモードの採用**

- ZeitwerkがRailsのデフォルトのコードローダーに。
- 自動ロードがより直感的かつ高速に。
- 名前空間に基づいたファイル構造を採用することで、コードの構造化が容易に。

---

### **9. セキュリティとパフォーマンスの向上**

- 標準でコンテンツセキュリティポリシー（CSP）のサポートを追加。
- RedisやMemcachedを使用したキャッシング機能の強化。

---

### **10. その他の改善点**

- Active Recordでの `upsert_all` や `insert_all` メソッドの導入により、複数のレコードを効率的に挿入可能。
- アソシエーションの読み込みを効率化する `eager_load` 機能の強化。

---

Rails 6は、リッチなアプリケーション機能を迅速に構築しながら、モダンな開発ワークフローをサポートするための強力なアップデートでした。Action TextやAction Mailboxのような新しいフレームワークが導入されたことが特に注目されます。
エンジニア用ヒアリング、質問のきっかけテンプレート

### 概要
相手の話をなかなか理解できないということを自覚したので、それを補うために、以下の項目を意識して穴埋めしていくことで、相手の話を理解できるようにする。

### 項目
#### 5w
* WHYなぜ
    * 本質：一番大事なことは？
    * 理由：なぜそうするのか？
    * 原因：なぜそうなるのか？
    * 意味：なぜそれをするのか？
    * 目的：目指すものは？最終目標、中間目標
    * 想い：どういう思いで？
* WHERE どこ　場所
    * どこ：やる場所。手順、資料や参考書の場所。
    * どこが：
    * どこで：
    * 環境：開発環境は？必要なソフトや構築は？
    * 移動：今の場所でいい？別のところに移すべき？
* HOW どう　方法
    * どうする：方針ややり方は？
    * 程度：全部やるのか？５０％くらいの完成度？
    * 手順：具体的な手順は決まっている？手順書は？一から考える？
    * どんな：何を使うのか？
    * スキル：必要な知識やスキルは？
    * 変える：事前に申請が必要か？何か変更が必要か？
    * 影響：どこかに影響が出る？
* WHO 誰　人
    * 依頼：実行する場合、誰に聞けばいい？頼めばいい
    * 共有：誰かと共有必要？
    * 連携：誰かと一緒に進めるのか？だれかと相談しながら進める必要があるか？
    * 責務：誰が主体ですか？（責任・管理）
    * 誰が：誰にメリットがある？デメリットがある？
    * 誰を：
* WHAT　なに　事実
    * 何が：何が問題ですか？
    * 何を：何をすればいいか？
    * 対象：何を解決すればいい？
    * 何に：
    * モノ：外側、概要、アウトライン。中身、詳細
    * コト：事象、対処、対応
* WHEN いつ　時間
    * 時間：どれくらいかかるか？
    * 期限：いつまで？
    * 開始：いつから始めればいい？
    * 優先：これに時間を割く意味は？
    * 機会：どんなときにやればいい？
* 

### その他
    * 報告：どれくらいの進捗まで行けば報告すべき？
    * 連絡：開始時は誰かに連絡、通知すべき？
    * 相談：誰に聞けばいい？頼ればいい？
#### 質問時注意
* そのまま質問するのではなく、きちんと意図を伝える
    * この質問に答えてもらうことで何が分かる・解決するのか？
    *
AI医療の未来へ：Med-Botがもたらす革新と課題

# Med-Bot: AIを活用した信頼性の高い医療情報アシスタント

今回は、医療AIの新たなステージを示す研究、「Med-Bot: An AI-Powered Assistant to Provide Accurate and Reliable Medical Information」を詳細に紹介します。この研究は、AIと医療の融合によって、医療情報の即時性、正確性、信頼性を高める新たなアプローチを提案しています。本記事では、背景、技術詳細、実験結果、課題、応用例、将来展望に至るまで、幅広く深掘りします。

---

## 論文情報
- **タイトル**: Med-Bot: An AI-Powered Assistant to Provide Accurate and Reliable Medical Information
- **リンク**: [arXiv:2411.09648v1](https://arxiv.org/abs/2411.09648v1)
- **発表日**: 2024年11月14日
- **著者**: Ahan Bhatt, Nandan Vaghela
- **DOI**: 未提供

---

## 背景と目的

### 医療分野におけるAIの必要性
医療は高度化・複雑化しており、医療従事者不足や情報アクセスの格差が世界的課題となっています。特に以下の点が医療チャットボットに求められています：
1. **患者の即時アクセスニーズ**: 遠隔地や緊急時において、医療情報への即時的なアクセスが求められる。
2. **医療従事者の業務軽減**: 繰り返し質問や一般的な情報提供業務を自動化。
3. **情報精度の向上**: 信頼できる医療情報を個別の患者に適応。

本研究はこれらの課題に対応し、次世代型医療チャットボット「Med-Bot」を開発することを目的としています。

### Med-Botの目的と範囲
Med-Botは以下を実現するために設計されました：
- ユーザーに正確かつ信頼できる医療情報を提供。
- 会話型AIとして文脈に応じた動的な回答を生成。
- 医療業界全体の効率性を向上させる。

---

## 研究の焦点

### 使用技術の詳細
Med-Botの設計には、最先端技術が組み込まれています：
1. **Llamaアシストによるデータ処理**  
   - 大規模医療文献からの高精度な情報抽出を実現。
2. **AutoGPT-Qによるモデル量子化**  
   - モデルサイズを効率的に削減し、リソース制約下でも高性能を維持。
3. **LangChainを用いた文脈管理**  
   - 外部データソースとのシームレスな統合により、適切な文脈を維持。

### 他研究との差別化
Med-Botは従来の医療チャットボットと以下の点で異なります：
- **文脈認識能力**: 会話の流れを理解し、動的に回答を調整。
- **専門性の高さ**: 医療分野に特化したトレーニングデータを利用。
- **効率性とスケーラビリティ**: AutoGPT-Qにより、メモリ使用量を削減しつつ高精度を維持。

---

## 実験の概要と結果

### データ収集と前処理
- **データソース**: PubMed、Medline、WHOデータベースなどの信頼性の高い医療文献。
- **前処理手法**: 
  - PyPDFDirectoryLoaderでPDFを解析。
  - RecursiveCharacterTextSplitterで1024トークン単位に分割。

### トレーニングの詳細
以下のコードスニペットは、AutoGPT-Qを活用したモデル量子化のプロセスを示しています：
```python
from transformers import AutoTokenizer, AutoGPTQForCausalLM

model_name_or_path = "TheBloke/Llama-2-13B"
tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, use_fast=True)

model = AutoGPTQForCausalLM.from_quantized(
    model_name_or_path,
    device="cuda",
    quantize_config=None
)
```

### 結果と分析

- **評価指標**:  
  - 精度（Accuracy）：92.3%  
  - 再現率（Recall）：89.7%  
  - F1スコア：90.8%  

- **成果**:  
  従来モデルに比べて15%以上のパフォーマンス向上を達成。

---

### 課題と応用可能性

#### 現在の課題
1. **データバイアス**: 新興疾患や稀少疾患への対応が限定的。  
2. **多言語対応**: 現時点では英語のみ。  
3. **リアルタイム学習**: 継続的な学習機能が限定的。  

#### 応用例
- **遠隔医療**: 医師不足地域での情報提供。  
- **患者支援システム**: 症状管理や服薬指導の自動化。  
- **医療教育**: 医学生や研修医への補助教材として活用。  

---

### 将来的な展望

1. **専門分野への拡張**  
   - 精神疾患、小児科医療、老人医療への特化モジュールを開発。  

2. **多言語対応**  
   - 世界中のユーザーに対応するため、主要言語をサポート。  

3. **医療システムとの統合**  
   - 電子カルテ（EHR）や診療予約システムとの連携。  

---

この記事が皆さんの研究や実務に役立つことを願っています。ご質問やフィードバックがあれば、コメント欄でお知らせください。
【Git】チーム制作で押さえておきたい基本概念とコマンド

【Git】チーム制作で押さえておきたい基本概念とコマンド

Gitは、チーム開発で欠かせないバージョン管理システムです。リモートリポジトリを使ってチームで効率的に作業を進めるためには、Gitの基本概念や主要コマンドを正しく理解することが重要です。特にpull、fetch、mergeの違いを知っておくことで、トラブルを未然に防ぐことができます。

Gitの基本概念

### 1. リポジトリ（Repository）

リポジトリは、プロジェクトのファイルや変更履歴を管理する場所です。
	•	ローカルリポジトリ: 開発者のPC上で作業するためのリポジトリ。
	•	リモートリポジトリ: GitHubやGitLabなどのサーバー上に保存されるリポジトリで、チームで共有します。
### 2. ブランチ（Branch）

ブランチは、作業の分岐点を意味します。機能ごとや修正内容ごとにブランチを作成することで、複数人で同時に作業が可能になります。
	•	メインブランチ: リリースや安定版コードを管理（通常mainやmaster）。
	•	作業ブランチ: 機能追加やバグ修正用の一時的なブランチ（例：feature/add-login）。
### 3. マージ（Merge）

マージは、異なるブランチの内容を統合する操作です。
	•	Fast-forwardマージ: 分岐がなく、単純にブランチを進めるだけのマージ。
	•	マージコミット: 変更点が複数あり、コミット履歴を統合する場合に発生。

### 4. コンフリクト（Conflict）

コンフリクトは、複数の開発者が同じファイルの同じ部分を変更した場合に発生します。手動で競合箇所を修正する必要があります。

# よく使うGitコマンド

リポジトリ操作

	•	git init: 新しいローカルリポジトリを作成します。

git init


	•	git clone: リモートリポジトリをローカルに複製します。

git clone <リポジトリURL>

ファイルの追跡と変更

	•	git status: 現在の変更状況を確認します。

git status


	•	git add: ファイルをステージングします。

git add <ファイル名>


	•	git commit: ステージングされた変更をローカルリポジトリに保存します。

git commit -m "コミットメッセージ"

ブランチ操作

	•	git branch: 現在のブランチ一覧を表示します。

git branch


	•	git switch: 他のブランチに切り替えます。

git switch <ブランチ名>


	•	git checkout -b: 新しいブランチを作成して切り替えます。

git checkout -b <ブランチ名>

### pull、fetch、mergeの違い

チームで作業する際、リモートリポジトリから最新のコードを取得するのは日常的な操作です。このとき、git pullとgit fetch、git mergeの役割を明確に理解することが重要です。

#### 1. git fetch

リモートリポジトリの変更をローカルに「ダウンロード」します。ただし、ローカルの作業ブランチには自動的に反映されません。
	•	動作:
リモートの変更内容を確認するために使用。

git fetch origin


	•	ポイント:
	•	ローカル作業を壊さず、リモートの最新情報を確認できます。
	•	git log origin/main でリモートの変更履歴を確認可能。

#### 2. git merge

git fetchで取得したリモートブランチの内容をローカルブランチに統合します。
	•	動作:
現在のブランチに対して、指定したブランチの変更を統合します。

git merge origin/main


	•	ポイント:
	•	コンフリクトが発生した場合、手動で修正が必要です。

#### 3. git pull

git pullは、git fetchとgit mergeを1回の操作で実行するコマンドです。リモートリポジトリから変更を取得し、そのまま現在のブランチにマージします。
	•	動作:

git pull origin <ブランチ名>


	•	ポイント:
	•	自動でマージを行うため、作業内容によってはコンフリクトの原因になる場合があります。
	•	チーム開発では、直接git pullを行わず、git fetch → git mergeの手順で安全に統合することを推奨。

# チーム開発のベストプラクティス

	1.	git pullは慎重に使用する
	•	コンフリクトを避けるため、git fetchで最新状態を確認してからマージする方が安全です。
	2.	作業ブランチの運用ルールを明確化する
	•	ブランチ名はfeature/機能名やfix/バグ内容など、用途がわかるように命名。
	3.	頻繁なプッシュ・プルで最新状態を保つ
	•	最新状態を取り込むことで、不要なコンフリクトを防ぎます。
	4.	適切なコミットメッセージを書く
	•	他のメンバーが変更内容を理解しやすくするために、簡潔かつ明確に記述。

まとめ

Gitをチーム開発で正しく使うためには、pull、fetch、mergeの役割を理解し、状況に応じて使い分けることが重要です。特に、リモートリポジトリの変更を取り込む際は、fetchを活用して慎重に統合することで、コンフリクトや意図しない変更を防ぐことができます。今回紹介したコマンドとベストプラクティスを参考に、効率的でトラブルの少ない開発を目指しましょう。
React Router v6 子階層のルーティング

React Router v6 にてネストされたルーティングに躓いたので備忘録です。

## 子階層のルーティング
[公式](https://reactrouter.com/en/v6.3.0/getting-started/overview)
>**ネストされたルーティング**
React Routerの最も強力な機能の1つで、複雑なレイアウトコードに煩わされる必要がなくなります。 レイアウトの大部分はURLのセグメントと結合しており、React Routerはこれを完全に受け入れています。 ルートは互いに入れ子にすることができ、そのパスも入れ子になります（子が親を継承します）

ここでは `<Outlet>` を使用します。
`<Outlet>` は、親コンポーネント内で子ルートをレンダリングするために使われ、「親のレイアウトを保持しながら異なるページを表示できます」
```Router.tsx
import {memo,FC} from "react"
import { Routes, Route } from  "react-router-dom"

import {Login} from "../components/pages/Login"
import {Home} from "../components/pages/Home"
import { Setting } from "../components/pages/Setting"
import { UserManagement } from "../components/pages/UserManagement"

export const Router : FC = memo(() => {
	return (
    <Routes>
      <Route path="/" element={<Login />} />
      <Route path="home" element={<Home />}>
        <Route path="user_management" element={<UserManagement />} />
        <Route path="setting" element={<Setting />} />
      </Route>
    </Routes>
	)
})
```
```Home.tsx
import { memo,FC } from "react"
import { Outlet } from "react-router-dom"

export const Home : FC = memo(() => {
	return (
		<>
    		<p>ホーム</p>
			<Outlet />
		</>
	)
})
```

これで
`/home`
`/home/user_management`
`/home/setting`
と子階層に遷移します。

`/home/user_management`
![スクリーンショット 2024-11-16 0.02.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668222/8c48e9b6-2eb7-d0ab-0be9-cdd398a56e58.png)

## ルートパスを別ファイルへ切り分けmapで展開
ルートパスは別ファイルで作成します。
`HomeRoutes.tsx` を作成。
```HomeRoutes.tsx
import { Home } from "../components/pages/Home";
import { Setting } from "../components/pages/Setting";
import { UserManagement } from "../components/pages/UserManagement";

export const homeRoutes = [
  {
    path: "",
    children: <Home />
  },
  {
    path: "user_management",
    children: <UserManagement />
  },
  {
    path: "setting",
    children: <Setting />
  }
];
```

```Router.tsx
import {memo,FC} from "react"
import { Routes, Route } from  "react-router-dom"

import {Login} from "../components/pages/Login"
import { homeRoutes } from "./HomeRoutes"

export const Router : FC = memo(() => {
	return (
    <Routes>
      <Route path="/" element={<Login />} />
      <Route path="/home">
        {homeRoutes.map((route) => (
          <Route
        	key={route.path}
			path={route.path}
			element={route.children}
    	/>
        ))}
      </Route>
    </Routes>
	)
})
```
`/home/user_management`
![スクリーンショット 2024-11-16 1.03.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668222/56d82a26-7861-36db-44f7-a2ac07fc659f.png)

シンプルな表記で子階層へルーティングできました。以上です。
【C#】ボックス化を避けるべき理由

# ボックス化とは
まず、ボックス化とは何か？
ひとことで言えば、値型のデータをオブジェクト（参照型）に変換するプロセスのことです。

以下のような型変換は典型的なボックス化の例です。
ちなみに、オブジェクトから値型に変換することをボックス化の解除と言います。
```csharp
int num = 1;
object obj = num; // ボックス化

obj = 123;
i = (int)obj; // ボックス化の解除
```
「いやいやこんな型変換使わないでしょ😗」と思われるかもしれませんが、実は色々な場面で不意に起きがちです。

例えば、様々な型を受け付ける`myList`という変数を宣言する際に、`var myList = new List<object>();`と宣言してしまうと値型のデータを`add`するたびにボックス化が起きます。

多くの型を受け入れ可能で一見便利に見えるボックス化ですが、アプリケーションに悪影響を及ぼす可能性があるため、使用するかどうかは慎重に検討すべきです。ボックス化の解除も同様ですね。

# なぜ悪影響が及ぶのか？
ボックス化が悪影響を及ぼす理由を以下の2点の観点から考察していきます。

1. メモリの割り当て
2. 処理のオーバーヘッド

### 1. メモリの割り当て
ボックス化が起きる際、値型のデータを参照型のオブジェクトの内部にコピーして値を格納します。

参照型として扱うということは、メモリはヒープ領域という領域に割り当てられます。
それに対して値型のデータの場合、スタック領域という領域に割り当てらます。

1番最初に例として挙げたコードを図で表すとこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3889500/7c570a9d-12ae-7503-50eb-f626a21d3ead.png)

スタック領域のデータは処理終了とともに破棄されていきますが、ヒープ領域のインスタンスはガベージコレクションの対象となり、使い終わった後もガベージコレクションによって破棄されるまでメモリに残り続けます。

スタック領域で持てるデータをわざわざヒープ領域に割り当てることでガベージコレクションの負荷を増加させ、アプリケーションのパフォーマンスを低下を招くというわけですね。

### 2. 処理のオーバヘッド
上記のメモリ負荷に加え、ボックス化、ボックス化解除の操作自体が、単純な値の代入や参照に比べて計算コストが高いです。

値型のデータには必要のない値コピーのコストやガベージコレクションの管理コストも踏まえるとこれは自明ですね。

特に頻繁に実行される処理やループ処理内でのボックス化には注意です。

# 見逃しがちなボックス化集
最後に実装者が見逃して不意に起きがちなボックス化の例をいくつか挙げておきます。

実装時は要注意！

#### 値型でインターフェース実装
```csharp
interface IExampleInterface { }
struct MyStruct : IExampleInterface { }

// 構造体は値型のため、構造体がインターフェースを実装するとボックス化
IExampleInterface obj = new MyStruct(); 
```

#### ジェネリックでないコレクションの使用
```csharp
using System.Collections;

// ジェネリックでないリストに値型のデータを追加でボックス化
var list = new ArrayList();
list.Add(123);
```

#### パラメータがobject型のメソッドを呼び出し
```csharp
void WriteObject(object obj)
{
    Console.WriteLine(obj);
}

// 値型をobject型のパラメータに渡すとボックス化
WriteObject(123);
```

#### ~~補間文字列で値型を使用~~ → C#10以降では改善されてました
```csharp
int height = 3776;
Console.WriteLine($"富士山の標高は{height}mです");
```

**【追記】**
C#10で可能な限りボックス化が起きないように改善されたみたいですね。
ただ、`string.Concat`や`+`演算子で値型を連結する際は依然としてボックス化が起きるようです。

https://learn.microsoft.com/ja-jp/dotnet/csharp/whats-new/csharp-10#interpolated-string-handler

#### 値型の`GetType()`メソッド呼び出し
```csharp
int num = 123;
Type t = num.GetType();
```

#### `params object[]`を使用するメソッド
```csharp
void WriteObjects(params object[] values)
{
    foreach (var value in values) Console.WriteLine(value);
}

int one = 1, two = 2, three = 3;
WriteObjects(one, two, three);
```

# 参考
[Effective C# 6.0/7.0](https://www.amazon.co.jp/More-Effective-C-6-0-7-0/dp/4798153982/ref=pd_sbs_d_sccl_1_2/356-7634902-3355205?pd_rd_w=OHlzC&content-id=amzn1.sym.dcca1cb7-d8ee-4f71-9db0-310358fcccf4&pf_rd_p=dcca1cb7-d8ee-4f71-9db0-310358fcccf4&pf_rd_r=QHY2B9S90GCSC8W641SD&pd_rd_wg=99dVn&pd_rd_r=ddd36e2e-1255-4249-bcaa-731b854bbd13&pd_rd_i=4798153982&psc=1) Bill Wagner (著), 鈴木 幸敏 (監修, 翻訳)

https://learn.microsoft.com/ja-jp/dotnet/csharp/programming-guide/types/boxing-and-unboxing

https://www.engineer-walk.com/engineer/csharp-memory/
Rails7の主な特徴８選

Rails 7では、モダンな開発環境をサポートしつつ、開発者体験を大幅に向上させるために、多くの新機能と改善が導入されました。以下がその主要な特徴です

---

### **1. Hotwireによるリアルタイムフロントエンドのサポート**

- **Hotwire（HTML Over The Wire）** が標準でサポートされ、モダンなフロントエンド開発がシンプルになりました。
  - **Turbo**: ページ遷移を高速化し、サーバーサイドでHTMLを生成することで、従来のSPAのような体験を提供します。
  - **Stimulus**: JavaScriptのコードを最小限に抑え、HTMLベースで動的なインタラクションを構築可能。
- ReactやVue.jsのようなフロントエンドフレームワークを使わず、リッチなインターフェースを実現。

---

### **2. WebpackerからImport Mapsへの移行**

- **Import Maps** がデフォルトになり、JavaScriptモジュールの管理が簡素化されました。
  - WebpackやNode.jsのセットアップが不要。
  - 必要なJavaScriptライブラリをサーバーから直接読み込み可能。

---

### **3. Active Recordの強化**

- Active Recordがさらに進化し、以下のような機能が追加されました：
  - **Async Query Loading**: クエリを非同期で実行し、パフォーマンスを向上。
  - **Strict Loading**: 未定義のリレーションへのアクセスを防止し、N+1問題を回避。
  - **Encryption**: データベースレベルでの暗号化がサポートされ、機密情報のセキュリティが向上。

---

### **4. メール配信機能の改善**

- **Action Mailbox** や **Action Text** の統合が進化。
  - メールを受信して処理する機能（Action Mailbox）。
  - リッチテキスト編集機能（Action Text）。

---

### **5. JavaScriptランタイムへの依存の削減**

- Rails 7では、Node.jsやYarnの依存が不要になり、シンプルな開発環境が提供されています。
- UJSの置き換えとしてHotwireが導入されたことで、Railsのフロントエンドがより洗練されました。

---

### **6. 新しいジェネレーター**

- Rails 7では、`bin/rails generate` コマンドが改良され、以下のような新しいジェネレーターが利用可能です。
  - TurboとStimulusを組み込んだコンポーネントの作成が容易に。

---

### **7. Ruby 3の完全サポート**

- Ruby 3の **並列処理（Ractors）** や **パターンマッチング** などの機能を活用可能。
- Ruby 3との統合によるパフォーマンス向上。

---

### **8. Zeitwerkモードの改良**

- デフォルトのコードローダーがZeitwerkに変更され、コードの自動読み込みがより効率的に。
- クリーンなオートローディングが実現。

---

Rails 7は、モダンなアプリケーション開発をシンプルかつ効率的に行うための強力な基盤を提供しています。Hotwireの導入やImport Mapsの採用により、JavaScriptへの依存を減らしつつリッチなユーザー体験を実現できる点が特徴です。
build.gradleのbuildscriptとpluginsの違い

# 背景

Gradleの`build.gradle`には様々な記法があります。その中でも`buildscript`と`plugins`の違いがわからなかったので調べてみました。

`build.gradle`の記述言語はGroovyを使用しますが、Kotlinでも本質は同じです。

# `buildscript`

`buildscript`では`build.gradle`の中で使用するプラグインなどを指定します。
- 社内でリポジトリを運用していて、そこでGradleプラグインを管理しているような場合は`repository`の中に追記します。
- `dependancies`には`build.gradle`の中で使いたいプラグインのclasspathを指定します。
- ここで指定するのはあくまで`build.gradle`の中で使いたいプラグインを指定するのであって、アプリケーション内で使いたいライブラリ (たとえばAWS SDKなど)はここに書きません。
- `dependancies`に追加したプラグインは`apply plugin`で適用します。プラグインでないライブラリの場合はこれは不要です。

```groovy:build.gradle
buildscript {
    repositories {
        gradlePluginPortal()
        mavenCentral()
        maven { 
            url 'https://my-internal-repository.example.com/'
        }    
    }
    dependencies {
        classpath "org.jlleitschuh.gradle:ktlint-gradle:12.1.1"
    }
}

apply plugin: "org.jlleitschuh.gradle.ktlint"
```

:::note warn
`dependancies`に書く`classpath`と`apply plugin`の記法は異なります。考えてもよくわからないので使用したいライブラリがある場合は[Gradle Plugin Portal](https://plugins.gradle.org/)で検索してコピペしましょう。
:::

# `plugins`

`plugins`も同様に`build.gradle`の中で使いたいプラグインを指定します。
- リポジトリの設定などはありません。
- 使いたいプラグインとそのバージョンを指定します。プラグインでないものは指定できません。
- [Core Plugin](https://docs.gradle.org/current/userguide/plugin_reference.html#plugin_reference)に指定されているものは省略記法が使えます。

```groovy:build.gradle
plugins {
    id 'java'
    id "org.jlleitschuh.gradle.ktlint" version "12.1.1"
}
```

# で、どっち使うの？

**`plugins`を使うことが推奨されています。**

`plugins`は簡潔でわかりやすいですが、`buildscript`はやや冗長です。また、リファレンスでは`buildscript`はレガシーとされていますので積極的には使わないほうがよいでしょう。

ただ、見てわかるように`plugins`の方には`repositories`の設定がありません。
実はデフォルトでは`plugins`は[Core Plugin](https://docs.gradle.org/current/userguide/plugin_reference.html#plugin_reference)か[Gradle Plugin Portal](https://plugins.gradle.org/)にあるプラグインしか指定できません。つまり、これらで管理されていないプラグインを使用できないわけです。
そのような場合は`buildscript`を使うのも手でしょう。

もし、どうしても`plugins`を使いつつ、独自のリポジトリのプラグインも使いたい場合は`settings.gradle`に`pluginManagement`のブロックを作成してリポジトリを指定します。このあたりの説明は下記の記事などを参照してください。

https://zenn.dev/aa/articles/4ee69840056ac4
WSL2で動作しているdevcontainer上で、Raspberry Pi Picoの開発をしたい

## 条件
Raspberry Pi Picoで遊びたいけど、、、

* WSL2(Ubuntu)上に構築したい
* VScode（というかdevcontainer）を利用したい

という条件で環境構築しました。

この条件だと、Picoを接続するのに一苦労だったので備忘録として。

## Windows上での準備

### 1. usbipd-winのインストール

``` PowerShell
winget install --interactive --exact dorssel.usbipd-win
```

### 2. Picoを接続

BOOTSELボタンは押さなくてOKです。
USBケーブルでRaspberry Pi PicoとPCを接続します。

### 3. BUSIDの確認

以下のコマンドでBUSIDを確認する。

``` PowerShell
usbipd list
```

どのデバイスかわからない場合は、デバイス抜き差しして前後に`usbipd list`をして増えてるものがどれかを確認すれば特定できます。

### 4. デバイスをバインドする

この手順は**管理者権限**のコマンドプロンプトから実行してください。

```
usbipd bind --busid <BUSID>
```

### 5. デバイスをアタッチする

```
usbipd attach --wsl --busid <BUSID>
```

これでUbuntu側からもUSBデバイスが認識できるようになります。

## WSL2(Ubuntu)上での準備

### 1. Windows側の設定がうまくいっているか確認

まずは、ここまでの手順がうまくいっているか確認します。

```
lsusb
```

うまくいっていれば、以下のようにPicoらしきデバイスが表示されます。
（下記でいうとMicroPython Boardですね。）

```
# lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 2e8a:0005 MicroPython Board in FS mode
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
```

### 2. WSL2(Ubuntu)上でのデバイス名を確認

WSL2(Ubuntu)上で認識されているPicoのデバイス名を確認します

```
dmesg | grep cdc_acm |grep tty
```

以下のように接続情報が確認できます。
私の場合は`ttyACM0`として接続されていることが確認できました。

```
# dmesg | grep cdc_acm |grep tty
[  675.390443] cdc_acm 1-1:1.0: ttyACM0: USB ACM device
```

### 3. devcontainer.jsonの編集
`devcontainer.json`に開発コンテナ起動時の追加の引数として、先ほど確認したデバイス名を渡します。

※`ttyACM0`部分は各自のデバイス名に変更すること。
``` devcontainer.json
{
    "name": "dev",
    // 略
    "runArgs": [
        "--device=/dev/ttyACM0"
    ],
    // 略
}
```

あとは、開発コンテナを起動するだけ。拡張機能を活用して便利に開発できますし、Gitも使いやすいので便利です。

## 参考
* [USB デバイスを接続する | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/wsl/connect-usb)
SQUEEZED ATTENTION: 長文脈LLM推論を4倍高速化する革新技術

# SQUEEZED ATTENTION: 長文脈LLM推論を加速する新手法

今回は、長文脈を扱う大規模言語モデル（LLM）の効率性を飛躍的に向上させる新しい手法「SQUEEZED ATTENTION」を紹介します。本論文は、固定文脈を効率的に処理することで、計算コストとメモリ使用量を大幅に削減し、長文脈タスクにおける推論効率を最適化することを目指しています。

---

## 論文情報
- **タイトル**: SQUEEZED ATTENTION: Accelerating Long Context Length LLM Inference
- **リンク**: [arXiv](https://arxiv.org/abs/2411.09688v1)
- **発表日**: 2024年11月14日
- **著者**: Coleman Hooper, Sehoon Kim, Hiva Mohammadzadeh, Monishwaran Maheswaran, June Paik, Michael W. Mahoney, Kurt Keutzer, Amir Gholami
- **DOI**: 10.48550/arXiv.2411.09688

---

## 背景と目的

### 現在の課題
LLMの文脈長が増加する中で、多くの応用タスクにおいて以下の課題が顕在化しています：

1. **メモリ使用量の増加**:
   - 注意計算（Attention Mechanism）は文脈長 \(L\) に比例して計算コストが増加します。たとえば、文脈長が32Kを超えると、モデル推論に必要なKVキャッシュが膨大なメモリを占有します。

2. **固定文脈の非効率利用**:
   - 実際のアプリケーションでは、多くの入力文脈が固定されており、これを逐次計算することはリソースの無駄につながります。

3. **既存手法の限界**:
   - QUESTやSparse Attentionは長文脈の一部をスパース化するアプローチを取っていますが、計算コストの大幅な削減には至っていません。

### 提案手法の意義
本研究の目的は、固定文脈を効率的に利用する「SQUEEZED ATTENTION」を提案し、以下の目標を達成することです：
- 推論速度を大幅に向上させる。
- 精度を維持しつつKVキャッシュのメモリ負荷を軽減する。
- 階層的クラスタリングを通じて計算複雑性を最適化する。

---

## 手法の詳細

提案手法は、以下の3つのステップで構成されています。

### 1. 固定文脈のオフラインクラスタリング
- **目的**: 固定文脈のキー（Key）をセマンティックに類似したグループに分割し、各グループの代表（セントロイド）を計算します。
- **アルゴリズム**:
   - K-meansクラスタリングを適用し、クラスタ \(C_j\) を生成。
   - 各クラスタのセントロイドを以下で計算：
   $$ C_j = \frac{1}{|K_j|} \sum_{k \in K_j} k $$
   - セントロイドは注意計算時に固定文脈の代表として使用されます。

### 2. クエリ対応のオンラインキー検索
- **クエリ処理**: 推論時にユーザー入力（クエリ）が与えられると、以下の手順でキー検索を実行します。
   - クエリ \(q\) とセントロイド \(C_j\) の内積を計算。
   $$ S_i = \frac{\exp(q \cdot C_i)}{\sum_{j} N_j \cdot \exp(q \cdot C_j)} $$
   - スコアが閾値を超えたクラスタのみを使用し、注意計算を実行します。

### 3. 階層的クラスタ検索
- **Level 1**: 粗粒度クラスタリングで検索範囲を大幅に絞り込む。
- **Level 2**: 細粒度クラスタリングで詳細な検索を実施。
- **計算効率の改善**:
   $$ O(L) \rightarrow O(\log L) $$

---

## 実験と結果

### 実験設定
- **使用モデル**: LLaMA-2-7B-32K、LongChat-7B-v1.5-32K。
- **データセット**: LongBench（長文QA）、PreFixQA（部分文脈QA）、RULER（規則生成タスク）。
- **評価指標**: F1スコア、推論速度、KVキャッシュ削減率。

### 主な結果
1. **速度向上**:
   - 推論速度が従来手法に比べて4.3倍向上。
   - 固定文脈のKVキャッシュ削減率は最大8倍。

2. **精度維持**:
   - 70%スパース化で精度を完全に維持。
   - 90%スパース化でも精度低下はわずか0.5ポイント。

3. **既存手法との比較**:
   - QUESTと比較し、精度で1ポイント向上。
   - SnapKVと比較して推論速度が約2倍高速。

---

## 応用可能性と限界

### 応用可能性
- **ドキュメントQA**: 長文脈を効率的に処理し、リアルタイム性が求められるタスクに最適。
- **コード生成**: 高速化により、大規模コードベースの生成を効率化。
- **検索エンジン**: 長文検索クエリの高速な処理を実現。

### 限界
- **動的文脈の処理**: クラスターの再構築が必要な動的文脈では適用が困難。
- **初期クラスタリング負荷**: オフライン処理の計算コストが高い。

---

## 結論と展望

SQUEEZED ATTENTIONは、長文脈LLMにおける推論効率の課題に対し、革新的な解決策を提供しました。特に固定文脈の有効活用という観点で、他手法と一線を画す性能を示しています。

今後の研究課題として以下が挙げられます：
1. 動的文脈に対応するリアルタイムクラスタリング手法の開発。
2. 階層的クラスタリングのさらなる高速化。
3. 他のスパース化手法とのハイブリッド化。

この記事が、読者の皆さんの研究や実務に役立つことを願っています。ご質問やフィードバックは、ぜひコメント欄にお寄せください！
LLMの幻覚現象をゼロショットで検出する新手法：最新研究の詳細解説

# LLM Hallucination Reasoning with Zero-shot Knowledg e Test

今回は、最新の研究成果である「LLM Hallucination Reasoning with Zero-shot Knowledge Test」という論文をご紹介します。この研究は、LLM（大規模言語モデル）が生成するテキストにおける「幻覚（hallucination）」を精密に分類し、その原因を特定する新しい手法を提案しています。特に、ゼロショットでの検出を可能にするアルゴリズムが注目を集めています。

---

## 論文情報
- **タイトル**: LLM Hallucination Reasoning with Zero-shot Knowledge Test
- **リンク**: [arXiv:2411.09689v1](https://arxiv.org/abs/2411.09689)
- **発表日**: 2024年11月14日
- **著者**: Seongmin Lee, Hsiang Hsu, Chun-Fu (Richard) Chen
- **DOI**: 不明

---

## 背景と目的

### LLMと幻覚現象の課題
大規模言語モデル（LLM）は、多くの応用分野で革新をもたらしましたが、信頼性の低い生成物、すなわち「幻覚現象」が実用化の大きな障壁となっています。この現象には、以下のようなタイプがあります：
1. **捏造（Fabrication）**: モデルが知識を持たないトピックについて、信憑性のない情報を生成する。
2. **不整合（Misalignment）**: モデルが知識を持っているにもかかわらず、生成されたテキストが知識と矛盾している。

幻覚現象は医療、法務、教育といった応用分野で重大な問題を引き起こす可能性があります。そのため、これらを正確に検出し、原因を明らかにする手法が求められています。

### 既存研究とその限界
従来の幻覚検出手法には以下のようなアプローチがあります：
- **外部知識との比較**: 生成テキストを信頼できるデータベースや知識ベースと照合する（例：FactScore）。
- **ファインチューニング**: ラベル付きデータを使用してモデルを調整する。
- **生成の一貫性チェック**: モデルの内部状態や生成結果の整合性を評価する（例：SelfCheckGPT）。

これらの手法には、外部知識への過度な依存や、捏造と不整合の原因を区別できないといった限界があります。

---

## 研究の焦点

本研究は、LLMが生成するテキストを以下の3つに分類する新しいタスク「Hallucination Reasoning」を提案しています：
- **整合（Aligned）**: モデルの知識と一致しているテキスト。
- **不整合（Misaligned）**: モデルの知識と一致していないが、知識自体は保有している場合。
- **捏造（Fabricated）**: モデルが知識を持たないトピックに関するテキスト。

提案手法は、外部知識や追加データに依存せず、LLM内部の知識を活用することでこれらの分類を実現しています。

---

## 提案手法

提案手法は、「Model Knowledge Test（MKT）」と「Alignment Test」の2段階で構成されています。

### Model Knowledge Test（MKT）
**目的**: モデルが提示されたトピックに関する十分な知識を持つかを判断。

#### アルゴリズム
1. **主題特定**:
   - SpaCyを用いて生成テキスト中の名詞句を抽出。
   - モデルの注意メカニズムを利用して、主題となるトピックを特定。

2. **主題の摂動**:
   - 主題に対応する埋め込みにガウスノイズを加える。
   - ノイズの付加が生成結果に与える影響を測定。

3. **モデル知識スコア（MKS）の計算**:
   - KLダイバージェンスを使用して、摂動の影響度を定量化。
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1150733/b83a9406-c37d-74b8-4447-f38ec7bb9999.png)
参照先：3.1 Model Knowledge Test の Step 3「Model Knowledge Score Evaluation」

### Alignment Test
**目的**: MKTを通過したテキストがモデル内部の知識と整合しているかを評価。

#### 方法
- SelfCheckGPTを利用し、ゼロショットで生成テキストの整合性を評価。

---

## 実験の概要と結果

### データセット
1. **NECデータセット**:
   - スポーツ、動物などの一般トピックを網羅。
   - 各カテゴリ（整合、不整合、捏造）に359件のデータポイント。

2. **Biographyデータセット**:
   - 人物伝記を対象とし、誤情報や虚偽の事実を含むデータを生成。

### 実験結果
提案手法は以下の性能を示しました：
- NECデータセット: 捏造検出率76.82%、整合分類精度92.39%。
- Biographyデータセット: 捏造検出率99.04%、整合分類精度85.23%。

---

## 応用可能性と社会的意義

提案手法は以下のような分野で活用が期待されます：
1. **医療**: 誤診や誤情報の防止。
2. **法務**: 合法的かつ信頼性のあるアドバイスの提供。
3. **教育**: 高品質な教材の生成。

---

## 課題と将来展望

### 課題
- 整合性テストの計算コスト。
- モデル依存性が高い点。

### 将来展望
- 高効率な整合性テストの開発。
- 幅広いデータセットでの検証と応用。

---

この記事が、皆さんの研究や実務に役立つことを願っています。ご意見やフィードバックをお待ちしています。