OmniAICreator/Qiita-1.07M huggingface dataset:
[Vision API] Javaで画像内のロゴを検出する

Googleが提供しているVision APIをJavaで使ってみました。

APIを使用し、画像内に含まれているロゴを検出します。

:::note info
APIを利用する環境の準備から始める場合や、コードを実行する際は、
[⧉[Vision API] Javaで画像内のいろいろなものを検出する](https://qiita.com/doran/items/444cb6231b7dffb9ddac)
を参照ください。
:::

|No||目次|
|---|---|---|
|1||[Feature.Typeの指定](#1-featuretypeの指定)|
|2||[実行結果の取得](#2-実行結果の取得)|
||1|[レスポンスの出力](#21-レスポンスの出力)|
||2|[レスポンスの内容](#22-レスポンスの内容)|
|3||[結果の検証](#3-結果の検証)|
||1|[Googleの場合](#31-googleの場合)|
||2|[楽天の場合](#32-楽天の場合)|
||3|[トヨタの場合](#33-トヨタの場合)|
||4|[Bandai Visualの場合](#34-bandai-visualの場合)|

# 1. Feature.Typeの指定
ロゴを検出する場合は、
**Feature.Type.LOGO_DETECTION**
を指定します。

以下の記事でexecApi()にタイプを指定します。
[⧉[Vision API] Javaで画像内のいろいろなものを検出する](https://qiita.com/doran/items/444cb6231b7dffb9ddac#25-apiを呼び出す)

# 2. 実行結果の取得
### 2.1. レスポンスの出力
取得した結果をコンソールに出力します。
```
private static void output(BatchAnnotateImagesResponse response){
    List<AnnotateImageResponse> responses = response.getResponsesList();

    for (AnnotateImageResponse res : responses) {
        if (res.hasError()) {
            System.out.format("Error: %s%n", res.getError().getMessage());
            return;
        }
    
        for (EntityAnnotation annotation : res.getLogoAnnotationsList()) {
            System.out.println(annotation.getDescription());
        }
    }
}
```
### 2.2. レスポンスの内容
BatchAnnotateImagesResponseの
getResponsesListでAnnotateImageResponseリストが取得できます。
検出されなった場合は、空のリストが返ってきます。

#### AnnotateImageResponse
|メソッド|戻り値|内容|
|---|---|---|
|getLogoAnnotationsList|List\<[EntityAnnotation](#entityannotation)\>|検出された情報|
#### EntityAnnotation
|メソッド|戻り値|内容|
|---|---|---|
|getMid|string|OpaqueエンティティID|
|getDescription|string|検出されたロゴの説明文|
|getScore|float|検出結果の信頼度。範囲は0〜1|
|getBoundingPoly|[BoundingPoly](#boundingpoly)|ロゴの画像領域|
#### BoundingPoly
|メソッド|戻り値|内容|
|---|---|---|
|getVerticesList|List\<[Vertex](#vertex)\>|境界ポリゴンの頂点。<br>左上、右上、左下、右下の順|
#### Vertex
|メソッド|戻り値|内容|
|---|---|---|
|getX|int|X座標|
|getY|int|Y座標|

## 3. 結果の検証
画像に含まれるロゴが検出されるか検証してみました。
企業のロゴは扱いが難しいのでGoogle以外、元画像は貼り付けていません。
どれも有名なロゴなので検索すればすぐに出てきます
(Googleの場合はチュートリアルで使っていいよ。と書いてあったので)

### 3.1. Googleの場合
**検出させる元画像**
<img width="480" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/4cb5c6fd-2ec8-83b5-161b-cb8996721997.jpeg">
**検出された結果**
検出信頼度：0.8186716
ロゴ: Google
ちゃんと読み取れました。

### 3.2. 楽天の場合
**検出させる元画像**
赤文字「R」だけで、下に線があるロゴ

**検出された結果**
検出信頼度：0.56306803
ロゴ: Chrome Hearts
なんと、クロムハーツが出てきました。
楽天、RAKUTENとか書いてある方のロゴが正式なのでしょう。

### 3.3. トヨタの場合
**検出させる元画像**
誰でも知っているトヨタのマーク（文字がないやつ）

**検出された結果**
検出信頼度：0.977188
ロゴ: Toyota
さすが世界のトヨタ。

### 3.4. Bandai Visualの場合
**検出させる元画像**
モアイの絵に、EMOTIONと書いてるやつ

**検出された結果**
検出信頼度：0.7809801
ロゴ: Bandai Visual
バンダイとはどこにも書いていないのにしっかりと検出されました。

<BR>
<BR>
おしまい。。。
PS1形式が実行できない環境で管理者権限でPSスクリプトを実行する方法

# これは？
**グループポリシーなどによって制御されている環境下だけどPS1ファイルを管理者権限で実行したい！**　という方向け（ごく少数）の技術共有となります。

# 実際のコード
```bat:test.bat
powershell -NoProfile -ExecutionPolicy unrestricted -Command "Start-Process PowerShell.exe -Verb runas 'Get-Content -Raw -Encoding UTF8 ((Split-Path ''%0'' -Parent) + ''\test.txt'') | iex'"
```

# 使い方
①任意の名前のbatファイルを作成し上記コードを記述します。
②任意の名前のPS1ファイルをtxt拡張子に変更し、bat内test.txtの部分をTXTファイル名に置き換えます。
③batファイルと同じ階層にTXTファイルを置きます。

# 注意点
## batと同じ階層にTXTファイルを置かない場合
```bat:test.bat
powershell -NoProfile -ExecutionPolicy unrestricted -Command "Start-Process PowerShell.exe -Verb runas 'Get-Content -Raw -Encoding UTF8 ""FileFullPath"" | iex'"
```

## カレントディレクトリについて
立ち上がったPowerShellは**System32**をカレントディレクトリとして立ち上がるため、スクリプト内でファイルの読み込み等する際は**フルパス記述推奨**

# 最後に
システム管理者向けの共有となります。
これはスクリプトの内容をよく理解している場合にのみ使用すべきであり、不明なスクリプトを実行する際にはスクリプトの内容を検証し、信頼できるものだけを実行するようにしてください。
M3のMacbookが配備されたので、Unityもインストールしておこうメモ

M3のMacbookが配備されたので、Unityもインストールしておこうで実施したメモ

### 目標
いろいろ入れる方法はあるが、
いかにApple Sillicon版をHomebrew管轄でいれるか

### 大まかな流れ
1. HomebrewでUnity Hubをインストール
1. HomebrewでUnity Editorをインストール
1. Unity Hubの対象にインストールしたUnity Editorを認識させる


### 1. HomebrewでUnity Hubをインストール
ターミナルを起動して以下のbrewコマンドを投下
```bash
brew install --cask unity-hub
```

インストールが完了したら、アプリケーションの中から "Unity Hub" を実行

![スクリーンショット 2024-03-07 11.58.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435600/406ea889-6f4b-6a12-e5d6-b823c84366d9.png)

起動したらサインインを求められるのでサインイン。
（アカウントもってなかったら作成）

![スクリーンショット 2024-03-07 10.36.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435600/2c573e33-6b28-dc49-0436-cd2936427431.png)

サインインすると "Unity Editor" のインストールを促されるが、後に別途brewでインストールするので、ここではSkip。

"Unity Hub" を日本語（または他の言語）にしたかったら、
~~~
⚙（歯車） ▶ Appearnce ▶ Language
~~~
で日本語（または他の言語）


### 2. HomebrewでUnity Editorをインストール

ターミナルを起動して以下のbrewコマンドを投下
```bash
brew install --cask unity
```
アプリケーションの中に "Unity" というフォルダが作られ、その中に "Unity" と "Unity Bug Reporter" というのが作られる

![スクリーンショット 2024-03-07 12.06.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435600/fb1d57ec-6401-19e0-c6f8-8b85e33705a4.png)

3. Unity Hubの対象にインストールしたUnity Editorを認識させる

"Unity-Hub" から以下の手順で認識させます

```
インストール ▶ リストに追加
```

"アプリケーション/Unity" にある "Unity"(.app) を選択
![スクリーンショット 2024-03-07 12.14.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435600/f601390a-c859-a829-d5f9-138a9e481740.png)

日本語にしてない場合は、以下
```
Installs ▶ Locate
```
![スクリーンショット 2024-03-07 12.13.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435600/4df5d9d2-2439-abd1-2215-55e322ec5c09.png)

以下の様に "Unity Hub" に Apple Sillicon版の "Unity Editor" が認識されれば、目的達成。

![スクリーンショット 2024-03-07 11.30.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435600/f1c80627-c6f1-97ef-d7c2-35259f891ed7.png)
UiPath Automation Ops 編 ソリューション管理 (Solutions Management)

## UiPath Automation Ops ソリューション管理とは？
Automation Opsのソリューション管理はフォルダー内の「プロセス、アセット、キュー」などの構造をパッケージ化したり、どこかのAutomation Opsでパッケージ化したものを取り込み専用のフォルダー構成を構築できます。

詳しくは下記をご確認ください。
Automation Ops

https://docs.uipath.com/ja/automation-ops/automation-cloud/latest/user-guide/introduction

ソリューション管理

https://docs.uipath.com/ja/solutions-management/automation-cloud/latest/user-guide/solutions-management-overview

## 環境設定
- Automation Cloudの管理からAutomation Opsを有効に設定
- Orchestratorのアクセス権を管理からフォルダ操作のロール設定

## 実装
### ①テストフォルダーを作成
テスト用のフォルダーを作成して、プロセス、アセット、キュー、トリガー、マシンを適当に設定しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736921/12ec722d-ad35-cbc8-3c1e-01be50a2b78a.png)
****
### ②UiPath Automation Ops ソリューション管理 フォルダパッケージ化
**(1)Automation Opsを開きソリューション管理から「新しいプロジェクト」を押下**

![スクリーンショット 2024-03-07 092701.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736921/c37827e4-c076-1f0c-ea21-0b39b39b95e8.png)

**(2)プロジェクトを作成**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736921/0369dfdf-cadc-de63-a8f2-a5210254745c.png)

**(3)Solutionsbuilderに移動するのでプラスボタンを押下**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736921/9b5b6094-3d0e-d0f8-8777-51111a6de53f.png)

**(4)対象のフォルダーを選択し、対象種類を選択追加**
![スクリーンショット 2024-03-07 093827.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736921/fb7e343c-b6f8-795c-b547-0b6913db76c3.png)

**(5)パブリッシュを押下、フォルダー名、パッケージ名、バージョンを記載しパブリッシュ**
パブリッシュするとZipがダウンロードされます。
![スクリーンショット 2024-03-07 095032.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736921/eb5e8790-4c9c-86b1-4df5-dd69764bb976.png)

:::note info
***パブリッシュ設定***
![スクリーンショット 2024-03-07 101300.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736921/73d88dd9-1941-e1e2-9ea1-844410bfd6a8.png)
ソリューションのルート フォルダー名：適当
パッケージ名：適当
パッケージのバージョン：適当　
(パッケージの修正時には同じバージョンで作成できない)
:::

****
### ③UiPath Automation Ops ソリューション管理 フォルダー構成の構築

作成したパッケージを下記の設定でデプロイします。
![スクリーンショット 2024-03-07 103857.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736921/2928025c-0fad-c06a-ff4a-fbe64dc952f4.png)

:::note info
**デプロイ設定**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736921/751df313-619e-9c3d-a0be-c750bab529a9.png)
デプロイの名前：適当
ターゲットフォルダー：親フォルダー名
ソリューションのルートフォルダー名：作成するフォルダー名
:::

****
### ④フォルダー構成の確認
デプロイ後のフォルダ構成を確認すると正常に「パッケージコピー」フォルダーが作成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736921/1c6ccb08-ffac-4798-7785-b5bb78c43f71.png)

## まとめ
UiPath Automation Ops ソリューション管理で「プロセス、アセット、キュー、トリガー」+「対象フォルダに紐づくパッケージ(ソース)」をパッケージ化できるようです。
「ユーザー、マシン」の設定はデプロイ後に設定する必要がありそう・・・
今後もUiPath Automation Opsの投稿をしていきたいと思います。
auto-bootをfalseにしたらMacが起動できなくなった件について

タイトルの通り、NVRAMのauto-bootをfalseに変えたらMacが起動できなくなったので、その経緯と復旧方法をまとめてみました。

# 経緯
MacBookを開いても自動で起動しないようにしたいなと思って、色々調べた結果、NVRAMの`AutoBoot`の値を変更することで実現できるとわかりました。
>NVRAMは、音量、ディスプレイの解像度と輝度、起動ディスクの選択、時刻設定などの周辺データを保存するものです。

<font color="red">**ただしIntelしかダメなようです。**</font>
https://discussionsjapan.apple.com/thread/254818483?sortBy=best

M2 Macを使っていますが、それを知らずに間違ったパラメータを変更したせいで、再起動してみたら起動できなくなったというわけです。

# やったこと
以下のコマンドでNVRAMのすべての情報を確認することができます。
```bash
$ nvram -p
```
grepでAutoBootを確認してみます。（Intel Macはたぶん表示されると思うがM2 Macでは表示されなかった）
```bash
$ nvram -p | grep AutoBoot
```
あれ？何も表示されないじゃん。bootで検索してみたらどうなるかな。というわけで以下のコマンドを打ったら何か出てきました。
```bash
$ nvram -p | grep boot
boot-volume	<省略>
boot-note	<省略>
upgrade-boot-volume	<省略>
auto-boot	true
bootdelay	0
```
おお、auto-bootってやつあるじゃん、これじゃね？ってなって、以下のコマンドを打ったのです。
※良い子は真似しないでね
```bash
$ sudo nvram auto-boot=false
```

ふう。
再起動してみるか。

![IMG_0282.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/edcb02f4-6c31-57a5-3d45-05944caa6a94.jpeg)

あれ、WTF？！
やってしまった...

# 復旧方法
幸いリカバリーモードでターミナルを開いてパラメータの値をもとに戻したら復旧できました。

リカバリーモードの起動方法ですが、電源OFFの状態で、「オプション」が表示されるまで電源ボタンを長押しします。
![IMG_0294.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/aff2e62e-6e8f-4c8e-85e0-762e575b49f4.jpeg)
![IMG_0288.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/68d6ff22-ba46-db97-e6fa-ddc1ca45c471.jpeg)
「オプション」が表示されたら「続ける」をクリックします。
![IMG_0289.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/d619d0bd-0d83-c2a8-0bc0-132c95dbe284.jpeg)
ユーザの選択画面が表示されたら、パスワードがわかっているユーザを選択します。「次へ」をクリックし、そのユーザの管理者パスワードを入力します。
![IMG_0290.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/6250639e-bfcb-d568-daf0-fe82effd32aa.jpeg)
リカバリーモードに入ったら、一番上のバーに移動して、「ユーティリティ」をクリックします。 メニューの中から「ターミナル」を見つけてクリックし、リカバリーモードで開きます。

![IMG_0291.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/2abaf4a0-d2ae-7ec3-9a7c-f27e154c2e68.jpeg)
auto-bootの値をtrueに戻します。
```bash
nvram auto-boot=true
```
![IMG_0284.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/20fa71a6-0df2-fe76-b182-02339cbfa685.jpeg)

 再起動すればOKです。

 # 参考URL
 - https://support.apple.com/ja-jp/HT204904
 - https://discussionsjapan.apple.com/thread/254818483?sortBy=best
【Java】並列処理【Thread】

備忘録としての投稿です
記事にしておきながらなんですが、人に見せることは目的をしておりません。
ですが、見かけた方が内容についていろいろとツッコミを入れてくださると嬉しいです。

【自分について】
となるITベンチャー企業に入社し、日々勉強中です。
主にJavaを勉強しています。

## スレッドとは？
プログラムの実行の流れ
基本的にプログラムは一行ずつ、上から下に実行される
この、上から下へのプログラムの実行の流れを「スレッド」という

## シングルスレッド / マルチスレッド
・シングルスレッド：上記のスレッドが１つのみ。
  そのため、一つのプラグラムが順番に実行される
・マルチスレッド：複数のスレッドを同時に実行する
  処理A と 処理B を同時進行できる

## 並行処理 / 並列処理
・並行処理：2つの処理の実行を切り替えながら、「並行」して処理を進めること
  ある時点では、個別の処理しかしていないが、全体像としてみると、同時に進行「しているように」見える
  →シングルコアでも可能

・並列処理：実際に2つの処理を同時に行うこと

イメージとしては、
料理をしているときに、煮物の煮ている時間 (=待ち時間) に別の作業をする = 並行処理
二人で同時に料理する = 並列処理
と理解しています。（間違っていたら教えてくださいm(__)m）

## Java の Thread
Java では、Thread クラスを使うことで並行 / 並列処理の実装が可能です。

以下、簡素なものですが、サンプルを作成しました。

①シングルスレッド
```Java:SingleThread.java
package MultiThread;

public class SingleThread {

	public static void main(String[] args) {
		
		System.out.println("開始");
		
		int t = 0;
		
		for (int i = 0; i < 10000; i++) {
			t += i;
		}
		
		System.out.println(t);
		
		System.out.println("終了");

	}

}
```

②マルチスレッド
```Java:MultiThread.java
package MultiThread;

class MyThread extends Thread {
	public void run() {
		
		int t = 0;
		
		for(int i = 0; i <= 10000; i++) {
			t += i;
		}
		
		System.out.println(t);
		
	}
}

public class MultiThread {

	public static void main(String[] args) {
		
		System.out.println("開始");
		
		MyThread t = new MyThread();
		t.start();
		
		System.out.println("終了");
	}
}
```

どちらも、プログラムの上下の流れで見れば、"開始" → for ループ → "終了" となっていますが、マルチスレッドの方は、main スレッドと MyThread が同時に処理されるため、forループの処理終了を待たずに "終了" と出力されます。

### 補足
Java ではどうやら並行 / 並列は区別されないらしく、どちらも Thread クラスを用いて実装する、らしいです。

## まとめ
まだまだ表面的な理解しかできていませんが、並列処理ができると、いろんなことができそうですね。

インターバルタイマーとか作れそうです。

あと、Thread クラスのほかに Runnnable インターフェースもありますが、こちらは現在勉強中です。
クエリビルダーの whereAll() および whereAny() メソッドが Laravel 10.47 に追加

2024/03/06にリリースされたLaravel 10.47から、新しいクエリビルダーとして `whereAll()` と `whereAny()` メソッドが追加されました。

# 使い方
1つの値を複数のカラムと比較する検索のロジック等を作成する場合があります。
例えば、名、姓、電子メール、電話番号でユーザーを検索する場合は、これまで以下のような書き方をしていました。

```php:Controller
User::query()
    ->where(function ($query) use ($search) {
    $query
        ->where('first_name', 'LIKE', "%$search%")
        ->orWhere('last_name', 'LIKE', "%$search%")
        ->orWhere('email', 'LIKE', "%$search%")
        ->orWhere('phone', 'LIKE', "%$search%");
    });
```
これだと大量の`orWhere`を書かなければなりませんし、useを使ってクロージャへ変数を渡してやる必要もあり、少々分かりにくい印象でした。

Laravel 10.47 からは以下のように書くことができます。
```php:Controller
User::whereAny(
    [
        'first_name',
        'last_name',
        'email',
        'phone'
    ],
    'LIKE',
    "%$search%"
);
```
冗長なコードが無くなり、クロージャも不要になってスッキリした書き方になりました。
また、AND条件にしたい場合は`whereAll()`を使うことができます。
```php:Controller
User::whereAll([
    'first_name',
    'last_name',
    'email',
], 'LIKE', "%$search%");
```

# 参考情報
https://laravel-news.com/laravel-10-47-0

# 最後に
次のメジャーバージョンである**Laravel 11 は2024年3月12日にリリース予定**で、おそらく**10.47は10.xブランチへの最後のリリース**になるようです。Laravel 10 は引き続き2024年8月6日までバグ修正を受け取り、セキュリティ修正は2025年2月4日まで受け取るとの事です。
接続が無効です。完全な詳細を読み込むために接続を更新してください


機能からずっとこのエラーでフローを作成できないです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/a379524d-0d30-1e9c-9ae5-ea8de9f33e02.png)

前回も悩まされたけど今回はもっと分からない

[Power Automate: Invalid Connection](https://qiita.com/Keiji_otsubo/items/6b3091c2fe1f515811d0)

change connectionがないんですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/747a4098-2662-0be8-c6a9-40f66ed30e5c.png)

英語でも検索しましたが分からないですね。

ちょっとヒントがあった

https://kirinote.com/powerautomate-frowerror/

どうも新しいデザイナーではダメみたい。これを見たら古いバージョンみたいです。

>エラーが発生している項目の右上「・・・」をクリックし

とりあえず接続を作ったらつながったけど、新しいデザイナーでは毎回このエラーになる。
AnacondaのWindows10アンインストールエラー対策メモ

## Windows10で完全にアンインストールできない現象が発生
Anacondaが有償化された際にアンインストールしていたのですが、Windows10のアプリと機能上ではゴミとして残っており、完全にアンインストールできていませんでした。すでに実態は消えているため、アンインストールボタンを押してもuninstallプログラムの実態は既に存在しないため消せなくてどうしようもない状態が続いていました。このuninstallプログラムの参照先はユーザーフォルダ配下のようでしたので、インストール時にユーザー限定で入れたのが良くなかったのかもしれません。実態は消えているのでコンプライアンス的に問題はないはずなのでしばらく放置していたのですが、残っているのも嫌なので完全に消す方法を調べることにしました。

## トライ1 レジストリの手動削除
Windowsのアンインストールが上手くいかない場合レジストリを手動で削除する方法があるようですが、該当するレジストリがHEKY_LOCAL_MACHINE SOFWARE配下に見つかりません。
ユーザーフォルダ配下に入れると書き込み先が違うのかもしれません。

## トライ2 コントロールパネルからの削除
　ダメもとでコントロールパネルのプログラムと機能のプログラムのアンインストールまたは変更から削除で実行したところ消えました。
Windowsのアプリと機能とコントロールパネルのプログラムと機能の削除機能は微妙に違うようです。動きを統一してほしいものです。
 
## まとめ
　Windowsでアンインストールがうまくいかない場合、コントロールパネルから削除してみるのを試してみると上手くいくケースがあるかもしれません。
【AWS】CloudFrontとは


# CloudFrontとは
**Amazon CloudFront**の略

 <img width="150" src="https://excelrcom.b-cdn.net/assets/admin/ckfinder/userfiles/images/2023_UPLOADS/AWStools/Tools_5.png">
 

効率的にユーザーにデータ･動画･アプリケーションなどのコンテンツを配信することができる、**コンテンツ配信ネットワーク(CDN)サービス**



# CDN
**Contents Delivery Network**の略


コンテンツ本体を保存しているサーバー(**オリジンサーバー**)に代わり、**キャッシュサーバー**(**エッジロケーション**)がコンテンツを配信する。

キャッシュサーバーは、オリジンサーバーに保存してあるコンテンツを複製(＝キャッシュ)し保存する。そして、ユーザーからアクセス要求があると、ユーザーから最も近いキャッシュサーバーがオリジンサーバーに代わり応答する。

<img width="500" src="https://blog.paessler.com/hubfs/cdn-orange.png">


#### ・エッジロケーション
 CloudFrontでは、世界中に400カ所以上配置されているエッジロケーションというデータセンターからコンテンツを配信する。



# 特徴
#### ・サーバーやネットワークの負荷を軽減できる
ユーザーに最も近いキャッシュサーバーが配信を行うことで、オリジンサーバーや関連ネットワークの負荷を分散することができる。

#### ・表示や配信速度を改善できる
オリジンサーバーの負荷軽減や、ユーザーとの物理的距離の短縮によってコンテンツの表示・配信速度を改善できる。

#### ・DoS/DDoS攻撃に強くなる
CDNでは送られてきたデータをキャッシュサーバーが受け止めるため、オリジンサーバーがダウンする可能性は低い。また、「**AWS Shield**」というDDoS保護サービスも無料かつ自動で適応されている。



# 利用料金
従量課金制
→実際に利用したデータ転送量とリクエスト数

:::note warn
従量課金制ではあるが、データ転送量は月1TBまで、HTTPSリクエスト数は月1,000万リクエストまでは無料で利用可能
:::



# 参考文献
以下を参考にさせていただきました。

[【入門】CDNとは？仕組みやメリットを図入りで分かりやすく](https://www.kagoya.jp/howto/it-glossary/web/cdn/)
[図解 Amazon Web Servicesの仕組みとサービスがたった1日でよくわかる](https://www.amazon.co.jp/%E5%9B%B3%E8%A7%A3-Amazon-Web-Services%E3%81%AE%E4%BB%95%E7%B5%84%E3%81%BF%E3%81%A8%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%81%8C%E3%81%9F%E3%81%A3%E3%81%9F1%E6%97%A5%E3%81%A7%E3%82%88%E3%81%8F%E3%82%8F%E3%81%8B%E3%82%8B-NRI%E3%83%8D%E3%83%83%E3%83%88%E3%82%B3%E3%83%A0%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE-ebook/dp/B09MQ14XR1)
Node.jsでCSVファイルを読み込む方法

# はじめに
`Node.js`でCSVファイルを読み込む実装をしたので、備忘録として記事にしたいと思います。
`TypeScript`で実装しているので、`Node.js` + `TypeScript`で、CSV読み込みを実装したい方の参考になれば幸いです。

# 必要なパッケージをインストール

`csv-parse`を使うので、以下をターミナルで実行してください。

```bash
npm install csv-parse
```

`Node.js`でCSVファイルを読み込むパッケージはいくつかあるそうです。
気になる方は以下をご参照ください。

https://qiita.com/t-yama-3/items/ab488c5a026de3cc92ab

# CSVを作成
```
ts_demo         // プロジェクトのルート
 ├ dist         // コンパイルしたjsファイルを格納
 ├ src          // tsファイルを格納
 ├ package.json // package.json
 └ users.csv    // 読み込むCSV
```

CSVは上記の位置に追加します（フォルダ構成は一部省略してます）
CSVの内容は下記です。
```csv
id,name,age,created_at
0001,John,18,2023/10/22 11:00:00
0002,Mike,23,2023/12/25 13:00:00
0003,Kevin,34,2024/1/22 11:00:00
0004,Ronald,42,2023/8/1 23:00:00
0005,Jake,36,2023/9/22 17:00:00
0006,Alice,54,2023/10/22 11:00:00
```

# コード
```ts
import * as fs from "fs";
import { parse } from 'csv-parse/sync';

class User {
    id: string;
    name: string;
    age: number;
    createdAt: Date;

    constructor(id: string, name: string, age: number, createdAt: Date){
        this.id = id;
        this.name = name;
        this.age = age;
        this.createdAt = createdAt;
    }
}

const users: User[] = [];

function readCsv() {
  const data = fs.readFileSync('users.csv');
  const records = parse(data, {
    //  BOM付きの場合はtrueにする
    bom: true,
    // ヘッダを無視したいので、2行目から読み込む
    from: 2,
  });
  for (const record of records) {
      const id = record[0];
      const name = record[1];
      const age = Number(record[2]);
      const createdAt = new Date(record[3]);

      const user = new User(
        id,
        name,
        age,
        createdAt,
      );
      users.push(user);
  }
}

readCsv();
console.log(users);

```

# おわりに
今回のコードは下記のリポジトリの`import_csv.ts`に格納しています。

https://github.com/AppDeveloperMLLB/ts_demo
sold outに関する続き

先ほどのものの追記です。

商品の詳細ページに遷移後、売り切れの表示をするためには

```ruby
      <% if @item.order.present? %>

```
となる。最初は＠をつけておらず、エラーが出ておりましたが
1つの決まりきった商品＝＠item とでもいう認識でしょうか。

自己満で失礼:zzz:
Optunaでsqliteを使った並列化をしようとしたら詰まった

# 起きた問題

Optunaで機械学習のハイパーパラメータ探索を，複数プロセスで同時に動かすよう並列化をしようと，以下の実装を動かしたらエラーになった．

```python:main.py(抜粋)
study = optuna.create_study(
    study_name="my_study",
    storage=args.optuna_db,  # sqlite:///path/to/study.db のような文字列を指定
    load_if_exists=True,  # すでに↑のファイルがある場合は，それを読み込んで並列化
)
```

```bash:実行スクリプト
source venv/bin/activate;
# 3つ同時に実行して探索
python main.py --optuna_db sqlite:///result/study.db &
python main.py --optuna_db sqlite:///result/study.db &
python main.py --optuna_db sqlite:///result/study.db &
wait
```

```plaintext:エラー
Traceback (most recent call last):
  File "/path/to/venv/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1960, in _exec_single_context
    self.dialect.do_execute(
  File "/path/to/venv/lib/python3.9/site-packages/sqlalchemy/engine/default.py", line 924, in do_execute
    cursor.execute(statement, parameters)
sqlite3.OperationalError: table alembic_version already exists
```
`load_if_exists=True,` を指定したのに，なんで…?

# 環境
optuna==3.5.0
SQLAlchemy==2.0.27

# 解決策
2つ目移行の実行前にsleepを挟むことで解決した．

```bash:実行スクリプト
source venv/bin/activate;
# 3つ同時に実行して探索
python main.py --optuna_db sqlite:///result/study.db &
sleep 3;  # 追加
python main.py --optuna_db sqlite:///result/study.db &
python main.py --optuna_db sqlite:///result/study.db &
wait
```

新たなDBファイルを作る時にmigrationが走るようで，その最中は `load_if_exists=True,` を指定したとしてもロックがかかっていたりするのか，DBファイルを正しく開いてくれないことが原因ではないかと推測した．
そこで，1つ目のプロセスでmigrationが終わるまでの数秒間の待機を挟んでから2つ目以降のプロセスを走らせることで解決したと考えられる．
出口のない迷路

https://paiza.jp/works/mondai/class_primer/class_primer__closed_maze

ぶっちゃけ文章をよんで全然意味がわからなかったです。
とりあえず入力例を見てみます

```
4 4 1
p 2 4
a 3 1
i 4 2
z 1 2
1
1
1
2
```


・最初の行は地点の数 N と、移動の回数 K , 移動を開始する地点の番号 S
・脱出するには、迷路の地点を与えられた指示通りに移動し、移動で訪れた（移動の開始・終了地点を含む）地点に置かれたアルファベットをつなげた文字列を呪文として唱える必要があります。
・各頂点からは、他の頂点に向かって一方通行の 2 つの道が伸びています。
・続く N 行のうち i 行目(1 ≦ i ≦ N)では、番号 i 地点に置いてあるアルファベット a_i と
　1 つめの道のつながっている地点の番号 r1_i , 2 つめの道のつながっている地点の番号 r2_i 　が与えられます。
・続く K 行のうち i 行目(1 ≦ i ≦ K)では、
　i 回目の移動で選んだ道の番号 M_i が与えられます。

ということなので、

要するに、地点というのがそれぞれの地点になっていて、最初の例だと
ポイントの数が4個。移動できる回数も4個。で、ポイントの中で最初のスタート地点が１だと。
おそらく、ポイントには名前がついていて、１，２，３，４となってると思う。
で、それぞれ、P,A,I,Zがあるわけ。
次に、地点１から２つ道が伸びていて、それはどこかというと、地点２と地点４ってことか。
でそれを地点４まで情報が与えられてるわけね。
次に、スタート地点から選んだ道が１番目か２番目かってことだけど、地点２が１番目の道で、地点４が２番目の道ってことか。だから、選んだのは１なので、地点２を選んだことになる。
次も１番目で地点３、次も１番目で地点４，次も１番目で地点１。
でこれらをつなぐと、P,A,I,Z,Aとなる。これが答えか。

入力例２も確かめてみて、ロジックは間違いない。
なるほどわかったややこしい。

うーん。まあ、構造体データにすればいけそう。
最初から考えるの難しそうだけど。
まあ、ポイントの情報を入れるってことになりそうだな。
ポイントのクラスってことで、character(落ちてる文字）、route1(道がどこに通じてるか）、route2(道がどこに通じてるか）をクラスに登録して、
到着した時点に落ちてる文字を返して、
次に行動のときの選択で１番目だったらroute1、２番目だったらroute2を返す
ということにして
落ちてる文字を格納する変数を作っておいて
それを出力すれば良さそう。

ということで下でOKでした。

```py
class Point():
    def __init__(self,letter,route1,route2):
        self.letter = letter
        self.route1 = int(route1)
        self.route2 = int(route2)
    def getletter(self):
        return self.letter
    def getroute1(self):
        return self.route1
    def getroute2(self):
        return self.route2

N,K,S = map(int,input().split())

#route情報取得
points =[Point(*input().split()) for _ in range(N)]

#行動情報から集めた文字を収集
#最初の地点がわかっているのでその地点の文字を取得して格納
#同様に地点も最初の地点がわかっているのでそれを格納
spell = points[S-1].getletter()
point = S

for _ in range(K):
    if int(input()) == 1:
        S = points[S-1].getroute1()
    else:
        S = points[S-1].getroute2()
        
    spell = spell + points[S-1].getletter()

print(spell)
```
SwiftUIでPhoto Libraryを使う

## Photo Libratyから写真を読み込む
iPhoneに保存されている写真を選択して表示するのを今回は、SwiftUIでやってみようと思います。

全体のコード:
```swift
import PhotosUI
import SwiftUI

struct PhotoLibrary: View {
    @State private var pickerItem: PhotosPickerItem?
    @State private var selectedImage: Image?
    
    var body: some View {
        VStack {
            PhotosPicker("Select a picture", selection: $pickerItem, matching: .images)
            
            selectedImage?
                .resizable()
                .scaledToFit()
        }
        .onChange(of: pickerItem) { Task {
            selectedImage = try await pickerItem?.loadTransferable(type: Image.self)
        }
        }
    }
}

#Preview {
    PhotoLibrary()
}
```

こんな感じになります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303722/6a843c17-8526-c516-feeb-f1a39d3b7a32.png" width="320px" />

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303722/cea9ec8d-1f9e-a929-bee5-48ee328ad780.png" width="320px" />
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303722/9becb5b8-7084-6a67-21bc-089ed9d295b9.png" width="320px" />


## 最後に
今回は、端末に保存されている写真を選択して表示するのをやってみました。SwiftUIの学習でよくお世話になっているこちらの動画を参考に勉強しました。

https://www.youtube.com/watch?v=mEdXRmIIvVc
AWS Hands on for Beginners 完走した感想

# 目的
[前回](https://qiita.com/okigaruni_/items/6804e66ca63a982de56b)の記事からだいぶ間が空きまして、実は Hands on for Beginers を完走しておりました。その過程で、AWS学習方法の考え方が大きく変わったので、そこら辺を体験談として記事にしたいと思いました。
    僕はAWS初学者ですが、最終的なゴールはAWSの主要なサービスを理解し、使いこなせるようになることです。


# 思ったこと➀

### マネジメントコンソール、サービスの設定画面が変化しすぎ！
ほとんどのサービスはハンズオン収録時点(2020~2023) からあまり変わっていないのですが、Cloud9 や CloudWatch などの使われやすいサービスには変更点が多く、これから慣れていきたいと思いました。

※ CloudWatch Events → EventBridge に統合

# 思ったこと➁

### AWS のサービスは奥が深すぎる！
ハンズオンでは、１テーマあたりで3~8個くらいのサービスに触れます。
また、サービスにはそれぞれ機能があり、その機能にもオプションや設定項目が山ほどあり、気にしだすとハンズオンが全然進まなかったので、まずは次の３点だけを意識して進めました。

➀ そのサービスで何ができるのか
➁ 基本的な使い方だけを理解する
➂ マネジメントコンソールで手を動かす


# 思ったこと➂

### とはいえ、機能やオプションを分からないままにしたくない！
分からないままにして進めたくなかったので、分からないことをNotionにメモしながら進めていきました。今後はそれらの不明点をサービス、機能ごとに Notion で整理しようと考えています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/850329/a0f469c5-82fd-bb02-0c81-1774670897b5.png)



# 今後の学習

➀ 資格勉強
とりあえず、AWSの認定資格 [Solutions Architect - Associate](https://aws.amazon.com/jp/certification/certified-solutions-architect-associate/, "公式サイト") の勉強を通じて、サービスごとの細かいオプションなどの知識を詰め、体系的な理解を目指します。

➁ AWS で遊ぶ
AWSを手順通りに構築するだけでなく、意図的に不具合を発生させることで、他のサービスへの影響やエラー表示などを調べたいと思います。

##### また、長い目線のAWS学習で次の懸念点への対策を考えました。

##### 懸念➀：サービスに新しい機能が追加,削除される
→ 気持ち新たに学ぶ

##### 懸念➁：マネジメントコンソールのレイアウトが変わる
→ 以下のツールを利用して開発を効率化する
1. AWS CLI：
    コマンドでサービスを管理する<p>

2. CloudFormation, AWS SAM
    テンプレートを利用するとメリットが多い
    メリット➀：サービスの設定が可視化されるので共有しやすい
    メリット➁：マネジメントコンソールの操作ミスを減らせる
    メリット➂：サービスの複数起動が簡単になる

# その他

最後まで記事を読んでくださり、ありがとうございます。
今後は、読者に配慮した読みやすい記事を目指そうと心に決めました。
何卒、よろしくお願いします。
PHP oci_connect SELECT テンプレ Smarty .tplで出力

### ■ 開発環境
・PHP7.4
・Smarty 2.xxx
・RedHat7.9
・oracle 19

### ■ ソース概要
・OCIで、oracleへ接続
・接続後、SELECT文で値を配列へ格納
・上記で取得した値を、foreachで回して、別々の配列へ格納

--- ここから Smarty .tpl
・PHP側で取得した値を出力

### ■ PHPソース
```php index.php

	function GET_KASOU_KUBUN()
	{

		// OCI
		$conn = oci_connect(DB_USER, DB_PASSWORD, DB_CONNECTION_STRING, DB_CHARSET);

		if (!$conn) {
			$e = oci_error();
			self::fnDispError(DB_ERROR, $e['message'], true, DEBUG_MODE);
		}

		$sql = "SELECT カラム01, カラム02 FROM テーブル01 WHERE カラム01 < 3";
		$stid = oci_parse($conn, $sql);
		if (!$stid) {
			$e = oci_error($conn);
			self::fnDispError(DB_ERROR, $e['message'], true, DEBUG_MODE);
		}

		$r = oci_execute($stid);
		if (!$r) {
			$e = oci_error($stid);
			self::fnDispError(DB_ERROR, $e['message'], true, DEBUG_MODE);
		}

		$nrows = oci_fetch_all($stid, $res, null, null, OCI_FETCHSTATEMENT_BY_ROW);

		$arr_Kasou_k = array();
		$arr_Kasou_k_Name = array();

		$idx = 0;
		foreach ($res as $k_val) {
			$arr_Kasou_k[$idx] = $k_val['カラム01'];
			$arr_Kasou_k_Name[$idx] = $k_val['カラム02'];
			$idx += 1;
		}

		if (
			$nrows > 0
		) {
			//Ut_Utils::printR($res);
			$this->arrKsou_K = $arr_Kasou_k_Name;
		}

		oci_free_statement($stid);
		oci_close($conn);
	}

```
### ■ Smartyソース
```Smarty index.tpl

     <tr>
            <th class="alignC w_20">
            火葬区分
            </th>
            <td colspan="7">
            <!--{html_radios name="$key1" options=$arrKsou_K selected=$kasou_idx|default:0}-->
            </td>

     </tr>

```
【初心者向け】状況に応じたソフトウェア開発：ライフサイクルモデル

[徹底攻略 JSTQB Foundation教科書&問題集 シラバス2018対応](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5-JSTQB-Foundation%E6%95%99%E7%A7%91%E6%9B%B8-%E5%95%8F%E9%A1%8C%E9%9B%86-%E3%82%B7%E3%83%A9%E3%83%90%E3%82%B92018%E5%AF%BE%E5%BF%9C/dp/4295017671/ref=asc_df_4295017671/?tag=jpgo-22&linkCode=df0&hvadid=654833321247&hvpos=&hvnetw=g&hvrand=7317531869461544354&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009293&hvtargid=pla-2199686852302&psc=1&mcid=140f9d5d8ea8321d9cdbe1b981b50a4c&th=1&psc=1)を勉強しているので、自分のメモとしてまとめています。第８弾。

# プロジェクトやプロダクトの特性に応じたモデルの選択
シラバスでは、以下のファクターを考慮してモデルを選択し、必要に応じてアレンジすることを推奨している。

- プロジェクトのゴール
- 開発するプロダクトの種類
- ビジネス上の優先度（市場に参入するまでの時間など）
- プロダクトリスクやプロジェクトリスク

例に以下を挙げる。
<dl>
  <dt>小規模な内部向けの管理システム開発</dt>
  <dd>アジャイル開発モデルを使って自由に作る方が効率的でよいものができる可能性がある。</dd>
  <dt>自動車のブレーキシステム</dt>
  <dd>セーフティクリティカルシステムなどは、きちんと設計してて、徹底的にテストするシーケンシャル開発モデルのほうが向いている。</dd>
  <dt>文化に合わせたモデル選定</dt>
  <dd>自由に情報共有する風土がない組織でアジャイル開発モデルを取り入れた場合、チームメンバーのコミュニケーションが悪くて開発が今くいかないことが懸念される</dd>
</dl>

# テストレベルの組み合わせ
プロジェクトの状況によっては、テストレベルやテスト活動を組み合わせたり、再編成したりする場合もある。

市販ソフトウェア（Commercial Off-The-Shelf:COTS:コッツ / 棚から出してすぐ使える商品の意味、日本ではパッケージソフトともいわれている）を購入して大規模システムに組み込む場合、統合テストと受け入れテストを一緒にテストすることになる。
（市販ソフトウェアの大規模な連携を統合テストで検証しながら、受け入れテストで運用性を確認する作業が一緒に行われる。）

ウォーターフォール開発モデルでは、通常4つのテストレベルをシーケンシャルに実施するが、４つのテストレベルが必ずしもシーケンシャルに独立して行われるとは限らない。

# ソフトウェア開発ライフサイクルモデルの組み合わせ
プロジェクトによっては、複数のソフトウェア開発ライフサイクルモデルを組み合わせる場合もある。

⏬例
- フロントエンドシステムのUI開発とテスト
    → アジャイル開発モデル：徹底的に使い勝手の良いものを作るため
- バックエンドシステムとテスト
    → V字モデル：ロジックにエラーが起きないように、きちんと設計・テストするため

プロジェクトの初期段階ではスパイラルにより試行を繰り返し、試行フェーズが完了した後はインクリメンタル開発モデルで機能拡張していくというように、アジャイル開発モデル同士を組み合わせる場合もある。

# 開発対象に応じたソフトウェア開発ライフサイクルモデルの適用
開発対象はソフトウェアだけとは限らない。

⏬例
- IoTシステム
    - デバイス：シーケンシャル
    - ソフトウェアプロダクト：アジャイル
        - **開発対象ごとに個別のソフトウェア開発ライフサイクルモデルを適用するのが一般的**

> IoT（Internet of Things）とは、「モノのインターネット」と訳される。センサーや駆動装置、家電製品、車など、これまでインターネットに接続されていなかった様々なモノをネットに接続することで、飛躍的に便利に使うことができるようになる。

# モデルを組み合わせる理由
プロジェクトやプロダクトの特性に適合させる理由は主に以下の３つ。

## システムのプロダクトリスクが違う
業務上重要なシステムほど大規模で複雑なシステムになり、故障したときのリスクが高くなる。
部門内で使用するような小規模システムは、故障したときのリスクが限定されるためリスクが低くなる。
そのため、複雑なプロジェクトにはシーケンシャル開発モデルを採用し、単純なプロダクトにはアジャイル開発モデルを採用するという使い分けが行われる。

## 多くの部署がプロジェクトやプログラムに参加している
部署によって通常使っているソフトウェア開発ライフサイクルモデルが異なる場合が多くなる。
シーケンシャルに慣れている部署とアジャイルに慣れている部署が同じプロジェクトに参加したとき、無理にソフトウェア開発ライフサイクルモデルを統一させるよりも、それぞれが慣れたモデルを使ったほうが成功の確率が高い可能性がある。

## プロダクトを市場に投入する時間が短い
ビジネス上の理由で、短期間でプロダクトを市場に投入しなければならないことがある。
複数テストレベルを同時に行ったり、複数のテストタイプを同時に行ったりすることで、市場投入までの期間を短縮する。

# 次回
https://qiita.com/1225/items/c921f82e6c79df021f2c
変圧器の規約効率と最大値について

# はじめに
変圧器といった電気機器の運用効率を運転中に計測するのは難しい。そこで、あらかじめ変圧器の損失（負荷損、無負荷損）を別の手段で求めておいて、理論計算により効率を推定するという方法が多用される。このようにして求めた効率を規約効率といい、出力/入力=出力/(出力+入力)によって求めることができる。今回は、規約効率が最大になるときの条件を理論計算により求めた上でPythonを用いてグラフ化することを試みる。
# 規約効率の定義
## 導入
まず、変圧器とは入力された電力の電圧と電流を変成して出力する装置である。しかしもちろんのことながら、その変換過程において損失が生じてしまう。それは、ジュール熱による損失であり負荷に流れる電流の二乗に比例する負荷損と負荷に依存しない損失である無負荷損と大別することができる。
## 定義
そこで、全負荷時の負荷に流れる電流を$I$とし、負荷率$\alpha$,変圧器の銅線の抵抗成分を$r$とすると、銅損である負荷損は以下のように表すことができる。

```math
P_c(\alpha)=(\alpha I)^2 r =\alpha^2I^2
```

ここで、出力を力率角$\theta$、系統電圧$V$で表すと、最大出力$P_{max}$は、以下のように表すことができる。

```math
P_{max}=VIcos\theta
```

したがって、負荷率$\alpha$の時の出力$P(\alpha)$は以下のように表すことができる。

```math
P(\alpha)=V(\alpha I)cos\theta =\alpha P_{max}=\alpha VIcos\theta
```

ゆえに、規約効率$\eta$は以下のように表すことができる。ただし$P_i$は固定損である無負荷損である。

```math
\eta(\alpha)=\frac{\alpha VI cos\theta}{\alpha VI cos \theta +(\alpha I)^2 r +P_i}
```
## 規約効率の最大値

これの分子と分母を$\alpha$で除して、相加・相乗平均を用いると以下のようになる。

```math
\eta(\alpha)=\frac{VIcos\theta}{VI cos\theta+\alpha I^2 r+P_i/\alpha}\le\frac{VIcos\theta}{VI cos\theta+2\sqrt{P_c P_i}}(\because{P_i=P_c})
```

このことから、銅損(負荷損)と鉄損(無負荷損)が等しいとき規約効率は最大になることが分かった。

# プログラム
さて、このことについてPythonを用いてグラフ化してみよう。
負荷率を0から1まで変化させた時の効率[%]を求めるプログラムを書いた。

```python efficient.py
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
fig, ax = plt.subplots()

I = 10
theta = 0
alpha = np.linspace(0,1,100)
V= 100
r=1.0

P_c = (alpha*I)**2*r
P_i = 10+0*alpha#定数配列と認識させるため

eta = (alpha*V*I*np.cos(theta)/(alpha*V*I*np.cos(theta)+P_c+P_i))*100

c1,c2,c3, = "blue","green","red",      # 各プロットの色
l1,l2,l3, = "効率","鉄損","銅損",   # 各ラベル

ax.set_xlabel('負荷率')  # x軸ラベル
ax.set_ylabel('効率・損失')  # y軸ラベル
ax.set_title("変圧器の効率[%]") # グラフタイトル
# ax.set_aspect('equal') # スケールを揃える
ax.grid()            # 罫線
#ax.set_xlim([-10, 10]) # x方向の描画範囲を指定
#ax.set_ylim([0, 1])    # y方向の描画範囲を指定
ax.plot(alpha, eta, color=c1, label=l1)
ax.plot(alpha, P_i, color=c2, label=l2)
ax.plot(alpha, P_c, color=c3, label=l3)

ax.legend(loc=0)    # 凡例
fig.tight_layout()  # レイアウトの設定
plt.savefig('変圧器の効率.png') # 画像の保存
plt.show()
```
これを実行すると以下のような画像が出力される。確かに、無負荷損と負荷損が同じ大きさであるとき、効率が最大になるようである。

![変圧器の効率.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/c1548122-bb17-0ea0-f73c-311b496e9508.png)

# まとめ
今回は、変圧器の規約効率について定義を確認して、最大値を求めた。ただし、負荷損は、ジュール熱より負荷電流の2乗に比例する一方で、無負荷損は負荷電流に依存しないことを注意した。また、最大値を求めるためには、一般に微分法を用いるが、今回のような場合は、相加・相乗平均を用いて最大値を求めた。それにより、規約効率が最大になるのは、負荷損と無負荷損が等しくなるときであるということが分かった。また、負荷率を変化させていったとき、規約効率がどのように変化するのかをグラフ化するためにPythonを用いた。このような、最大・最小をグラフから求める問題は電気工学では頻出なので、しっかりと押さえておきたいところである。

# 参考文献
https://jeea.or.jp/course/contents/12148/
mouseup イベント後、要素外で mousedown されるとイベントが発火せず困るので何とかしたい

# やりたいこと

Chrome 拡張機能でボタンを埋め込んでいます。

ボタンがクリックされたことが視覚的に分かりやすいよう、マウスが押し込まれたらボタンの css を変更し、離されたら元に戻したい。

![スクリーンショット 2024-03-07 103511.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76272/0ec8e2d4-6ddd-3ed1-1273-1e33b8ef0d03.png)


## 修正前のコード

脳死で mousedown, mouseup のイベントリスナーをそれぞれ登録していました

```javascript
document.addEventListener('DOMContentLoaded', () => {
  const copyButton = document.getElementById('copyButton');

  // マウスが押し込まれたら css を変更
  copyButton.addEventListener('mousedown', function() {
      // 変更する css を記入
      // this.style.xxxxxxx
  });
  // マウスが離されたら css を戻す
  copyButton.addEventListener('mouseup', function() {
      // 元に戻すための css を記入
      // this.style.xxxxxxx
  });
});
```

mousedown イベントは正常に発火しました
**※クリック時のデザインが駄目駄目なのは分かっていますので後で修正します**

![スクリーンショット 2024-03-07 103816.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76272/1d778560-1227-b1c4-90ec-6948f77f46e9.png)

押し込んだボタンをすぐ離すのであれば、このコードでも問題なく動作します。
ですが開発者の想定通りにユーザーが動いてくれないのは世の常です。

このコードだとボタンを押し込んだままカーソルを copyButton 要素外に出してから離してしまうと mouseup イベントは発火しません。mouseup イベントリスナーは copyButtn に登録されたので、当然といえば当然なのですが…。

例え要素外で離されたとしても、正常に動作するよう修正したい

## 修正後のコード

マウスが押し込まれた時点で、document（画面全体）に mouseup イベントリスナーを登録
そうすることによって、画面のどこでマウスを離しても mouseup イベントが発火するようになります

~~mouseup イベントが発火した後は、document に登録された mouseup イベントリスナーを削除~~
~~※そうしないと、document で mouseup イベントが発火し続けてしまうため~~

コメント欄でご教示いただきましたが、once という超便利なオプションがあるようなのでそちらを利用するよう修正

```javascript
document.addEventListener('DOMContentLoaded', () => {
  const copyButton = document.getElementById('copyButton');

  copyButton.addEventListener('mousedown', () => {
    // マウスが押し込まれたら CSS を変更する
    
    // 変更する css を記入
    // copyButton.style.xxxxxxx
    
    // documentでmouseupイベントを捕捉する（要素外でもイベントを補足出来るように）
    // 1回発火したら削除されるるよう、once オプションを指定
    document.addEventListener('mouseup', () => {
      // 元に戻すための css をここに記入
      // copyButton.style.xxxxxxx
     
    }, { once: true }););
  });
});
```



JavaScript、難しい
GAS　Git Hub アシスタントの使用上気をつけるところ

GASではGitのrevision情報を持ってないため、*Pull*の動作は本物のPullと違ってマージができない、じゃあどういう挙動になるのかというと、単に最新のソースをfetchしてプロジェクトに上書きする動作を取る。
等方的な積分で成り立つ恒等式

# 結論

次の恒等式が成り立つ：

- ３次元
$$ 
\int d^3x (x^2+y^2)^2 = 8 \int d^3x\ x^2 y^2,
$$
- ４次元
$$ 
\int d^4x (x_1^2+x_2^2+x_3^2)^2 = 15 \int d^4x\ x_1^2 x_2^2.
$$

# 説明
左辺と右辺の積分をそれぞれ極座標で書き下し比較すれば上述の恒等式が確認できる．
確かめたい読者のために極座標と直交座標の変換，ヤコビアン，変数の範囲を示しておく：

- ３次元
$$ 
x = r \sin \theta \cos \phi,\ 
y = r \sin \theta \sin \phi, \ 
z = r \cos \theta, 
$$
$$
d^3x = r^2 dr d\Omega = r^2 dr \sin \theta d\theta d \phi,
$$
$$
0\leq r \leq R,\ 0 \leq \theta \leq \pi,\ 0 \leq \phi \leq 2\pi.
$$
- ４次元
$$
x_1 = r \sin \theta \sin \phi \cos \psi,\ 
x_2 = r \sin \theta \sin \phi \sin \psi, 
$$
$$
x_3 = r \sin \theta \cos \phi,\ 
x_4 = r \cos \theta, 
$$
$$
d^4x = r^3 dr d\Omega = r^3 dr \sin^2 \theta d\theta \sin \phi d \phi d\psi,
$$
$$
0\leq r \leq R,\ 0 \leq \theta \leq \pi,\ 0 \leq \phi \leq \pi,\ 0 \leq \psi \leq 2\pi.
$$

# 詳細
４次元の具体的な計算を以下に示す：
$$
\int d^4x (x_1^2 + x_2^2 +x_3^2)^2 = \int r^3 \cdot r^4 dr \int_0^\pi \sin^2 \theta \cdot \sin^4 \theta d \theta \int_0^\pi \sin \phi d\phi \int_0^{2\pi} d\psi
$$
角度積分が$\dfrac{5\pi^2}{4}$を与える．一方，
$$
\int d^4x\ x_1^2 x_2^2 = \int r^3 \cdot r^4 dr \int_0^\pi \sin^2 \theta \cdot \sin^4 \theta d \theta \int_0^\pi \sin \phi \cdot \sin^4 \phi d \phi \int_0^{2\pi} \cos^2 \phi \sin^2 \psi d\psi 
$$
こちらの角度積分は$\dfrac{\pi^2}{12}$を与える．比をとれば$15$という因子が現れる．３次元の場合も全く同様にして確かめられる．

# まとめ
同様の方法で様々な形の積分を"等方的な場合に限り"変形できる．

# あとがき
なぜこんなものを？：論文を読んでいて「何この変形」ってなって試行錯誤してたら出てきた恒等式．

役立った？：その論文の式を再現できたから役だったといえる．
Railsで生じたDeviseの設定エラー(undefined method 'devise' for User:Class`)を解決する方法

Railsアプリケーションでユーザー認証機能を追加する際、Deviseはその強力なサポートとカスタマイズの容易さから、非常に人気のある選択肢です。しかし、Deviseの設定や初期化の過程で問題が発生することがあります。この記事では、`NoMethodError: undefined method 'devise' for User:Class`という特定のエラーの解決方法に焦点を当て、その発生原因と対処法を解説します。

## エラーの発生原因

このエラーは主に、Deviseのジェネレータが正しく実行されなかった場合などに発生します。エラーメッセージは、`User`クラスでDeviseのメソッドが認識されていないことを示しています。

## エラーが発生したときの手順・経緯

1. `rails generate devise:install`を実行（当初見落としていましたが`Could not find generator 'devise:install'.`というエラーが発生）。
2. `Gemfile`に`gem "devise"`を追加。`bundle install`を実行。
3. `rails generate devise User`を実行。ユーザーモデルとルーティングが生成。
4. `rails db:migrate`を実行。`NoMethodError: undefined method 'devise' for User:Class`というエラーが発生。
5. `rails generate devise:install`を実行。``method_missing: undefined method `devise' for User:Class (NoMethodError)``というエラーが発生。
6. `config/initializers`ディレクトリに`devise.rb`が存在しないことに気が付く。

## 解決方法

この問題を解決するための手順は以下の通りです：

1. **`config/routes.rb`から`devise_for :users`を一時的に削除**:
   - これにより、`rails`コマンドが再び使用できるようになります。特に`rails db:migrate`や`rails generate`コマンドを含みます。

2. **Deviseのインストールコマンドを正しく実行**:
   - 再度`rails generate devise:install`を実行します。今回は成功し、設定に関する指示が表示されるはずです。

3. **データベースマイグレーションの実行**:
   - `rails db:migrate`を実行し、Deviseによって追加されたマイグレーションを適用します。

## 追加情報

- `Gemfile`に記述された`gem "devise"`と`gem 'devise'`の間に機能的な差異はありません。Rubyではシングルクオートとダブルクオートは文字列を定義するために交換可能です。
- この問題が発生する主な理由は、Deviseの設定が完全には完了していないか、あるいは`routes.rb`での設定が先行してしまったためです。

## 結論

RailsアプリケーションにおけるDeviseの設定は複雑に感じることがありますが、適切な手順を踏むことでスムーズに設定を完了させることができます。この記事で紹介したエラーとその解決策は、Deviseを使用したアプリケーション開発において一般的な障害の一つですが、適切な対応を行うことで簡単に解決可能です。
bundle installエラー解決法：An error occurred while installing mimemagic

環境構築中に、`bundle install`をした後に`mimemagic`というものに関するエラーが発生しました。初めてみるエラーだったので、メモに残そうと思います。

まだ、初学者なので間違っていたら教えていただければ幸いです。

:::note info
設定したいバージョン(mac環境)

Ruby 2.6.4
Rails 5.2.3以降
:::

## エラーが発生するまでの流れ
1. Ruby 2.6.4をインストール
1. Rails 5.2.8をインストール
1. rails -vを実行後に以下のエラー文が発生
```
Could not find rails-5.2.3
Run `bundle install` to install missing gems.
```
文章に従い、`bundle install`を実行しましたが、またもやエラー文が発生。今回はこのエラーを解決していきます。
## 解決したいエラー
`bundle install`実行後に発生したエラー文はこちらです。
```
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

An error occurred while installing mimemagic (0.3.10), and Bundler cannot continue. Make sure that `gem install mimemagic -v ‘0.3.10’ –source ‘https://rubygems.org/’` succeeds before bundling.

In Gemfile:
　rails was resolved to 5.2.3, which depends on
　　activestorage was resolved to 5.2.3, which depends on
　　　marcel was resolved to 0.3.3, which depends on
　　　　mimemagic
```
簡単に要約すると、「mimemagic -v ‘0.3.10’をインストール時にエラーが発生したので、bundlerを続けることができません。」ということみたいです。
## エラーの原因
いろいろと調べてみたところ、ライセンス問題が原因のようです。

今回だと、GPL-2.0のライセンス問題により、「mimemagic gem」が「rubygems.org」から取り下げられてしまったみたいです。そうすると「mimemagic」は使えなくなってしまいますよね。

よって、`mimemagic <= 0.3.5`に依存しているRailsアプリが`bundle install`に失敗するためエラーが発生しました。

つまり、「mimemagic」がライセンス問題で無くなってしまったことが原因であるならば、ライセンス問題をクリアした「mimemagic」をインストールすれば解決できるはずです。

それでは、次の章で解決法を説明します。

エラーの原因で参考にした記事はこちらです。

https://hackmd.io/@mametter/mimemagic-info-ja

## エラーの解決法
解決法はとても簡単で、ターミナルで以下の2つのコマンドを打てば終わりです。
```
brew install shared-mime-info
```
まず、上のコマンドを打つことで、新しくライセンスし直した、`mimemagic`がインストールされます。
```
bundle install
```
そして、`bundle install`すれば解決です！これで、`rails -v`をしてもエラー文は出なくなりました。
## まとめ
今回は、ライセンス問題によるエラーでした。ライセンス問題によるエラーはこれまでにも何回か遭遇してきたので、これからも慌てず調べて行こうと思います。

この記事が参考になれば幸いです。

最後まで読んでいただきありがとうございます。
ActionController::UnknownFormat エラーの解決法

今回は、個人的に解決するのに時間がかかったエラーだったのでメモに残そうと思います。

もし、同じエラーで悩まれている方がいれば参考になれば嬉しいです！

:::note warn
まだ、初学者なので間違っているところがあればご指摘ください。
:::

## エラーが発生した流れ
やりたいこと：ログイン機能を実装したい。

user_sessionsコントローラーを作り、それに対応する`new.html.erb`のviewも作成。

ログイン画面をブラウザ表示しようとしたところ以下のエラーが発生。
## ActionController::UnknownFormat
今回、発生したエラー文です。
```
ActionController::UnknownFormat (UserSessionsController#new is missing a template for this request format and variant.

request.formats: [“text/html”]
request.variant: []

NOTE! For XHR/Ajax or API requests, this action would normally respond with 204 No Content: an empty white screen. Since you’re loading it in a web browser, we assume that you expected to actually render a template, not nothing, so we’re showing an error to be extra-clear. If you expect 204 No Content, carry on. That’s what you’ll get from an XHR or API request. Give it a shot.):
```
## エラーの原因
調べてみたところ、次の一文がヒントになるようです。
```
UserSessionsController#new is missing a template for this request format and variant.
```
リクエストされたフォーマットに対して、テンプレートがないよという意味みたいです。

つまり、今回で言うと、`UserSessionsController#new`に対応するviewがないため発生したエラーのようです。
## 解決法
今回のエラーはリクエストされたフォーマットに対してのviewがないことが原因でした。

ですが、`UserSessionsController#new`に対応するviewである、`new.html .erb`は存在していますし、user_sessions配下に配置もしています。

なぜエラーが解消されないのか？

もう一度view名を確認してみました。
```
new.html .erb
```

よくよくみると、htmlの後に半角スペースが空いていることに気づきました。
```
new.html.erb
```

半角スペースを消して、リロードすると、無事ログイン画面が表示されました！
## まとめ
小さな半角スペースがあるだけでも、エラーが発生してしまうことを今回身をもって知ることができました。

また、同じエラーが起きた場合は、焦らず細かい部分もしっかりみていこうと思います。

最後まで、読んでいただきありがとうございます。
enumを使ってUIStateを管理する

## 状態でUIを切り替えてみる
enumを使って、ロード中、成功、エラーの分岐処理を作りswitchを使って、Objextを切り替えるのをやってみました。

英語で、loading(ロード中....)、success(成功!)、failed(失敗した!)を意味する`enum`を定義して今回使ってます。
```swift
enum LoadingState {
        case loading, success, failed
    }
```

全体のコード
```swift
import SwiftUI

struct LoadingView: View {
    var body: some View {
        Text("Loading...")
    }
}
struct SuccessView: View {
    var body: some View {
        Text("Success!")
    }
}

struct FailedView: View {
    var body: some View {
        Text("Failed.")
    }
}

struct SwitchingView: View {
    enum LoadingState {
        case loading, success, failed
    }
    
    @State private var loadingState = LoadingState.failed
    
    var body: some View {
        switch loadingState {
        case .loading:
            LoadingView()
        case .success:
            SuccessView()
        case .failed:
            FailedView()
        }
    }
}

#Preview {
    SwitchingView()
}
```

Previewの画面:

![スクリーンショット 2024-03-07 10.26.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303722/eb84ef45-2816-0dc2-e3ab-e4bb07ac12cf.png)

## 最後に
今回は、enumを使って状態の管理をして、表示するObjectのロジックを作ってみました。こちらの海外の動画がSwiftUI学習の参考になるのでよく見ています。

https://www.youtube.com/watch?v=IWcmNBoT0-s
WPFのWebView2が実行環境で表示されない場合、exeがあるフォルダに実行ユーザーの書き込み権限が無いのが問題かも

# 概要

WPFの画面にWebView2を実装。デバッグ実行すると問題ないが、実行環境にインストールすると表示されない・・・？

そういう場合、WebView2はexeがあるフォルダへの書き込み権限を要求するという特徴のせいかもしれません。その説明と解決策です。

# 最初に結論まとめ

 * WebView2のインスタンスに、下記※1のように設定して、確実に書き込み権限があるフォルダを使わせるようにしましょう。
 * 処理に時間がかかること、処理が終わるまでWebView2を使用できない（Sourceを与えたりしてはいけない）という点に注意です。

※1
```csharp
//xaml側でName="webView"と定義している前提です
var webViewUserDataFolder = @"＜このexe専用の、ユーザーが書き込み可能なフォルダのフルパス＞";
var cwv2Environment = await CoreWebView2Environment.CreateAsync(null, webViewUserDataFolder, new CoreWebView2EnvironmentOptions());
await webView.EnsureCoreWebView2Async(cwv2Environment);
```


# 説明と解決方法

実行環境にインストールすると、WebView2コントロールだけが表示されない。例外やメッセージが出たり異常終了するわけでもなく、ただ表示されないだけ。こんな現象に出会って、解析に手間取りました。

そういう場合、WebView2を実装しているexeファイルのインストール先に、実行ユーザーの書き込み権限があるかを確認しましょう。

実行はできるが書き込み権限が無いというのは、意外にあり得るケースです。例えば、インストーラで管理者権限を使ってProgram Filesへインストールしたexeを、UAC昇格せずにユーザーが実行する場合、書き込み権限が無い状態になります。

なぜその権限が必要かというと、WPF向けWebView2がデフォルトでは、実装されたexeと同じフォルダにデータファイルを作ろうとするためです。

こうした場合、exeから確実に書き込み可能なフォルダを、データファイル作成用の場所として与えてやる必要があります。例えばそのユーザーのTempフォルダ等です。

WebView2のインスタンスを生成してから、最初に次のようにすることで設定できます。この例では、Tempの下の「MyExeFolder」というこのexe固有のフォルダを与える例としました。

```csharp
var webViewUserDataFolder = Environment.ExpandEnvironmentVariables(@"%Temp%\MyExeFolder");
var cwv2Environment = await CoreWebView2Environment.CreateAsync(null, webViewUserDataFolder, new CoreWebView2EnvironmentOptions());
await webView.EnsureCoreWebView2Async(cwv2Environment);
```

WebView2を動かしてから（例えばSourceを設定してから）変更することはできないので、処理順序に注意しましょう。WPFのウインドウに置く場合、Window.Loadedなどのタイミングで最初に処理してしまうのが良いと思います。

またawaitが入っているところからも見て取れると思いますが、処理に時間がかかるという点にも注意です。「最初はWebView2部分が非表示で、処理が終わり次第表示される」という動きで良ければ上記のように単純な呼び出しで良いですが、「表示されるまでの間はプログレスバーを出すなど動きを変える」といった場合は呼び出し箇所や順序に一工夫が必要になると思います。

# まとめ

普通のコントロールと同じ感覚でWebView2をWPFの画面上で使ったら、デバッグ実行では気づけないような意外な落とし穴がありました。使う機会があったら思いだしてみてください。
PostgreSQLでSQLをコマンド実行する場合に、1回限りのパスワード認証をする方法

# 概要

PostgreSQLでプログラム上から単発のSQLを実行したい場合に、ファイルを経由せずに1回限りのパスワードを与える方法の話です。

# 最初に結論まとめ

コマンドプロンプトの/cのセッション内で環境変数を設定し、そのままコマンドも実行します。例えば次のようになります。

`cmd /c "set PGPASSWORD=user1password&&psql.exe --username=user1 --dbname=postgres --command="CREATE DATABASE database1'""`

# 話の背景

PostgreSQLでpsql.exeを使って、--commandオプションや--fileオプションで単発のSQLを実行したい場合があります。手動で実行するのならば簡単で、インタラクティブでそのままパスワードを入力すれば済みます。

しかしこれをプログラム上から実行したい場合に、普通の手段だといったんファイルへユーザー名とパスワードを保存する必要があります。WindowsではACLを設定してファイルの内容を保護するようにという説明がありますが、できればファイル保存もしたくないところです。

ファイル保存せずに、1回限りのパスワードをプログラムから与えて実行する方法を考えたので、この記事を書きました。

# 説明と解決方法

psql.exeの仕様としては、ファイル保存の他にも環境変数を与える方法があります。環境変数の方は非推奨となっていますが、その理由はセキュリティにあるようです。ユーザー環境変数にしても、条件次第では他のユーザーから値を見ることができる可能性がある、と。

その点が問題なのであれば、コマンドプロンプトの実行セッションの間だけ存在する環境変数を使えば問題は無いはずです。ただ、コンソールアプリではないプログラムからコマンドを実行する場合、単発のコマンドでセッションが終わってしまうので、環境変数を与えられません。いったんバッチファイルを作成して実行すれば容易ですが、それではファイル保存しているので本末転倒です。

そこで、/cオプションの1つのセッションで、全体を""で囲みコマンドは&&で繋げる、という形で環境変数を与えたところ、上手く行きました。

まず、環境変数でパスワードを与える部分はこうなります。パスワードはuser1passwordだとします。

`set PGPASSWORD=user1password`

&&で続けてpsqlのコマンドです。例えば次のようになります。

`set PGPASSWORD=user1password&&psql.exe --username=user1 --dbname=postgres --command="CREATE DATABASE database1'"`

これを/cオプションの対象として、まとめるとこうなります。

`cmd /c "set PGPASSWORD=user1password&&psql.exe --username=user1 --dbname=postgres --command="CREATE DATABASE database1'""`

--commandオプションを例にしましたが、--fileオプションで.sqlファイルを与えることも同じように可能です。

`cmd /c "set PGPASSWORD=user1password&&psql.exe --username=user1 --dbname=database1 --file="C:\Temp\Script.sql""`

# まとめ

PostgreSQLのpsql.exeを、パスワード認証しながら単発で実行する方法が見つかりました。ベストな方法かどうかは分かりませんが、とりあえず私の要求は満たしていて問題はなさそうです。同じような物が必要になったら思いだしてみてください。
LLMのまとめ

# Transformer

Transformerを知らずしてNLPは語れない。Transformerは、2017年12月の論文「Attention Is All You Need」で提案された。特に、自己注意機構が独特な構造を持っている。自己注意機構は、クエリQに対応するキーKを選択し、キーKに対応するバリューVを出力する。これにより、入力データに対して動的に変化するニューラルネットワークが誕生した。

https://qiita.com/omiita/items/07e69aef6c156d23c538

https://qiita.com/momo10/items/e5d7e2d0f9701b71b5e0

# GPT：Generative Pretrained Transformer
TransformerのDecoder側を用いて、入力した文章に対する、次の単語を予測することで、文章を生成する。

https://qiita.com/momo10/items/ebe861e994864c93d964
単語のトークンIDは、Open-AIやGoogleが用意したトークナイザーで事前に設計されたと想定する。そのため、単語のトークンIDは事前に与えられており、GPTが予測した各単語に対する算出値と、真の各単語のトークンIDの確率値から、Cross Entropy Lossを算出する。

Cross Entropy Lossが最小となるように、GPTのモデルのパラメータを推定する。

https://qiita.com/ground0state/items/8933f9ef54d6cd005a69

https://note.com/npaka/n/ncb4864df31c9

GPTのPyTorchのサンプル実装はGitHubにある。

https://github.com/karpathy/minGPT/tree/master

# RLHF：Reinforcement Learning from Human Feedback
Instruct-GPTは、GPT-3に対して強化学習を適用することで、ラベラーにとって望ましい文章を生成する。ラベラーにとって望ましい文章が、ユーザーに受け入れられのであれば、適切な文章が生成できていることになる。

https://qiita.com/momo10/items/7c67748623185149b501

# DPO：Direct Preference Optimization:

RLHFは強化学習を用いるため、学習が不安定になってしまうことがある。そこで、DPOは、RLHFと数学的に等価なモデルを考えることで、より安定した学習を実現させた。

https://qiita.com/momo10/items/cf2105f26676a416820a

# GRPO：Group Relative Policy Optimization

https://horomary.hatenablog.com/entry/2025/01/26/204545#GRPO-%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%95%E3%82%8C%E3%81%9FREINFORCE


# RAG：Retrieval-Augmented Generation

RAGは、プロンプトに関連する社内情報や秘匿情報にアクセスし、文章を生成する技術である。社内情報や秘匿情報は公開されていないため、多くの場合、LLMは学習されておらず、使い物にならない。LLMを触れない状況で、プロンプトエンジニアリングで対応が出来ないときに、RAGを検討するとよい。

**検討する優先順位**
1. プロンプトエンジニアリング
2. RAGの構築
3. ファインチューニング
4. LLMの作成

# LLMのエラー対応
https://qiita.com/momo10/items/ebe861e994864c93d964