OmniAICreator/Qiita-1.07M huggingface dataset:
1次元の場合でも flex-shrink, flex-grow が必要なら CSS Grid でもいいんじゃない？

「**１次元なら Flexbox, ２次元なら CSS Grid**」

のように Flexbox と CSS Grid を使い分けると考えている人は多いのではないでしょうか？

じつは、１次元であっても、中身の文字列等の幅に関係ない(つまり 幅 が hug contents じゃない) 要素が含まれるときには、 Flexbox で書くよりも CSS Grid のほうが簡潔になる場合があります。

たとえば、「**左側は幅固定で、右側はあまった幅を埋める (ともに中身に左右されない)**」のように領域を左右に分ける場合です。

https://codesandbox.io/embed/flex-or-grid-linear-ov5vut?hidenavigation=1&theme=dark&view=split&editorsize=60&fontsize=10

(CodeSandbox のプレビュー画面のサイズを変化させると、左側領域の幅は変わらず、右側だけが変わっていることが分かります。)

## 1. Flexbox で実装する

flexbox で実装する場合は、次のように書きます。

```css
.flex-parent {
  display: flex;
}
.flex-child-fixed {
  flex-basis: 8rem;
  flex-shrink: 0;
}
.flex-child-fill {
  flex-grow: 1;
}
```

```html
<div class="flex-parent">
  <div class="flex-child-fixed">
    幅固定
  </div>
  <div class="flex-child-fill">
    幅可変
  </div>
</div>
```

子要素である .flex-child-fixed, .flex-child-fill それぞれに flex のアイテムとしての設定を書き込むことで幅の調節ができていることがわかります。

それぞれに書かれている flex-shrink: 0, flex-grow: 1 を消したらどうなるでしょうか？ CodeSandbox で試してみてください。

### flex-shrink: 0 を忘れた場合

左側の固定幅の領域に設定した flex-shrink: 0; を消すと、下の図のように、右側領域に入れた文字列が折り返すときに、幅の不足に反応して左側の領域の幅が縮んで (shrink) しまいます。(flex-shrink のデフォルト値が 1 だからです。)

![固定幅カラムのflex-shrinkを消した場合](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234029/d322f9b4-24f7-b5e0-81c0-ed5ce27c70a7.png)

### flex-grow: 1 を忘れた場合

右側の可変で埋める領域に設定した flex-grow: 1; を消すと、下の図のように、右側が広がってくれず、(hug content のまま) 中身の文字列の分の幅しか確保してくれません。


![fill幅カラムのflex-shrink](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234029/6d296581-04ca-c8a5-f6b2-11fa6a5a6f52.png)

## 2. CSS Grid を使うと簡単に

CSS Grid を使うと、ぐっと簡単になります。

```css
.grid-parent {
  display: grid;
  grid-template-columns: 8rem 1fr;
}
```

見ての通り、親要素に対して「このグリッドは、それぞれ 8rem, 1fr の幅の 2つのカラムがある」と指定するだけです。左右の各領域には何も指定する必要がありません。

### "1fr" とは

`fr` は、CSS Grid の columns, rows の幅指定に使われる単位です。たとえば、

```css
grid-template-columns: 8rem 2fr 3fr;
```

と書いた場合には、「一番左のカラムの幅は 8rem, 右側２つのカラムの幅は残った幅のそれぞれ 2/5　と 3/5 を割り当てる」という意味になります。

なので今回使った、 `8rem 1fr` は、 「左のカラムの幅は 8rem, 残りすべてを右側カラムに割り当てる」という意味です。

https://developer.mozilla.org/ja/docs/Web/CSS/CSS_grid_layout/Basic_concepts_of_grid_layout#the_fr_unit


![全部のケース](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234029/4085d3b2-a540-3cbe-3e5e-6e383985bb4b.png)



## 左側の幅を hug content にしたい

「右側は可変だけど、左側は、内容によって幅を決めたい」という場合は、諦めて Flexbox を使うしかないのでしょうか？

いいえ、 max-content を指定すれば可能です。

```css
.grid-parent {
  display: grid;
  grid-template-columns: max-content 1fr;
}
```

![左側の幅を hug content にする](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234029/889f67dd-6a69-0025-70e8-7cc8f0d24633.png)

https://developer.mozilla.org/ja/docs/Web/CSS/max-content

## まとめ


今回はこれ以上解説しませんが、 max-content だけでなく、 CSS Grid はかなり柔軟にカラム幅を制御する仕組みを持っているので、ぜひ１次元レイアウトでも CSS Grid で実現できるか試してみてください。
zsh でコマンド履歴を即座に保存する

# 解決したかったこと
通常の terminal から実行した zsh のコマンドは履歴に保存されるが、VSCode で開いた zsh で実行したコマンド履歴が保存されない。

# 原因
通常は zsh を終了したときに、そのセッションで実行していたコマンド履歴が ~/.zsh_history に保存されます。
しかし、VSCode で開いた zsh では、通常の終了処理が行われず、コマンド履歴が保存されないようです。

# 解決策
コマンドを打った直後に即座に履歴が保存されればこの問題は解決できます。
`.zshrc` などの設定ファイルに下記を追記すれば OK です。

```.zshrc
setopt incappendhistory
```

これは zsh の incappendhistory オプションを有効にするという意味です。


# 参考

https://www.webdesignleaves.com/pr/plugins/mac_terminal_basics_05.html

https://zsh.sourceforge.io/Doc/Release/Options.html#index-INCAPPENDHISTORY
cscの作法 その331

# 概要
cscの作法、調べてみた。
練習問題、やってみた。

# 練習問題
sqliteでdatagridviewでsortボタンを実装せよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/d6b47bbb-3fda-2662-d2c2-42ce8d3850bf.png)

# サンプルコード

```
using System;
using System.Text;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
using System.Data;
using System.Data.Common;
using System.Transactions;
using System.Data.SQLite;

class form1: Form {
	private SQLiteDataAdapter dataAdapter = new SQLiteDataAdapter();
	private DataGridView gd0 = new DataGridView();
	private Button rButton = new Button();
	private Button sButton = new Button();
	form1() {
		Text = "DataGridView";
		ClientSize = new Size(600, 400);
		rButton.Text = "sort1";
		rButton.Location = new Point(50, 20);
		sButton.Text = "sort2";
		sButton.Location = new Point(250, 20);
		gd0.Location = new Point(50, 60);
		gd0.Size = new Size(500, 300);
		rButton.Click += new EventHandler(RButton_Click);
		sButton.Click += new EventHandler(SButton_Click);
		Controls.AddRange(new Control[] {
			rButton,
			sButton,
			gd0
		});
		SQLiteConnection conn = new SQLiteConnection("Data Source=db0.sqlite;");
		conn.Open();
		SQLiteCommand command = conn.CreateCommand();
		command.CommandText = "SELECT * FROM fruit";
		dataAdapter = new SQLiteDataAdapter(command);
		DataTable dt = new DataTable();
		dataAdapter.Fill(dt);
		gd0.DataSource = dt;
		conn.Close();
	}
	private void RButton_Click(object sender, EventArgs e) {
		DataTable dt = (DataTable) gd0.DataSource;
		DataView dv = dt.DefaultView;
		dv.Sort = "name DESC";
	}
	private void SButton_Click(object sender, EventArgs e) {
		DataTable dt = (DataTable) gd0.DataSource;
		DataView dv = dt.DefaultView;
		dv.Sort = "name ASC";
	}
	[STAThread]
	public static void Main() {
		Application.Run(new form1());
	}
}




```


以上。
【npm】npm install でEEXISTエラーが出たときの対応

## expo / react / react-nativeをバージョン指定してインストールした
```shell
npm install expo@47 react@18.1.0 react-native@0.70.5
```

## こんなエラーが出た
```shell
npm ERR! code EEXIST
npm ERR! syscall rename
npm ERR! path ...省略...
npm ERR! dest ...省略...
npm ERR! errno EEXIST
npm ERR! Invalid response body while trying to fetch https://registry.npmjs.org/@urql%2fcore: EACCES: permission denied, rename '...省略...' -> '...省略...'
npm ERR! File exists: ...省略...
npm ERR! Remove the existing file and try again, or run npm
npm ERR! with --force to overwrite files recklessly.

npm ERR! A complete log of this run can be found in: ...省略....
```
## 解決方法
`EEXIST`でググってみると、「既にファイルが存在する」ということらしい。
▼ソース
https://linuxjm.osdn.jp/html/LDP_man-pages/man3/errno.3.html


```shell
npm ERR! Remove the existing file and try again, or run npm
// => 既に存在しているファイルを削除して、再度npmコマンドを実行してください
```
とあるので言われた通りにしてもいいのだが、その1行前で「permission denied,」と言われているので、とりあえずsudoで再度コマンドを実行してみた。
```shell
sudo npm install expo@47 react@18.1.0 react-native@0.70.5
```
これで無事にインストールできました。
データサイエンスのための微分積分 第18回 関数の不連続点

:::note info
本記事は数学講座[2.17関数の不連続点](https://www.matongxue.com/lessons/682/parts/961)を勉強して投稿したメモです。詳細は元の素晴らしい講座のページをチェックしてください。
:::

**定義：**
関数$f(x)$が$\mathring{U}(x_0)$に定義あり、もし函数$f(x)$が以下の三つのケースの一つであれば：
- $x=x_0$で定義なし
- $x=x_0$定義あり、$\displaystyle\lim_{x\to x_0}f(x)$が存在しない
- $x=x_0$定義あり、$\displaystyle\lim_{x\to x_0}f(x)$も存在、但し$\displaystyle\lim_{x\to x_0}f(x)\ne f(x_0)$

関数$f(x)$が$x_0$で連続しない （Discontinuous）、$x_0$が関数の不連続点です。

**定義：**
$x_0$が関数$f(x)$の不連続点：
- 左極限$\displaystyle\lim_{x\to x_0^-}f(x)$及び右極限$\displaystyle\lim_{x\to x_0^+}f(x)$とも存在すれば、$x_0$が関数$f(x)$の**第一種不連続点（Discontinuity of the first kind）**；
- その以外は全て**第２種不連続点 （Discontinuity of the second kind）**。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/5a8c2a62-8d54-1346-3d16-a27a424acd35.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/17b9b2ba-4508-f4e9-3cd8-eda80f3fd899.png)

# 練習

以下の関数の連続性などを分析する：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/e2911c92-f868-949b-1efd-4e9cadf42c9a.png)


# 参照：

https://ja.wikipedia.org/wiki/%E4%B8%8D%E9%80%A3%E7%B6%9A%E6%80%A7%E3%81%AE%E5%88%86%E9%A1%9E
[Python]画像をGETする、POSTする

Pythonで画像をサイトから保存する、画像をサーバやAPIにpostする。

# 画像をGETする
reqestモジュールを使って保存する。
```python
import requests

#画像のurlを設定
url = "https://xxx.com/yyyy/zzzzz.jpg"

#画像をGETする
response = requests.get(url)
image = response.content

#保存名を設定する
image_name = "image.jpg"

#画像を保存する
with open(image_name, "wb") as f:
    f.write(image)
```
#### 応用する
```python
import requests

#数字を設定
num = 1

#数字が10になるまで繰り替えす(10回繰り返す)
while num < 10:
    #画像のurlを設定
    url = "https://xxx.com/yyyy/" + str(num) + ".jpg"
    
    #画像をGetする
    response = requests.get(url)
    image = response.content
    
    #保存名を設定する
    image_name = str(num) + ".jpg"
    
    #画像を保存する
    with open(image_name, "wb") as f:
        f.write(image)

    #数字に+1する
    num += 1
```

# 画像をPOSTする
GETと同様に応用が可能。
```python
import requests

#postするurlを設定
url = "https://aaa.com/bbbb/ccccc.php"

#画像を読み込む
image = "./image.jpg"
data = open(image, 'rb')
file = {'image': data}

#postする
res = requests.post(url, files=file)

#レスポンスを表示する
print(res.text) #.textはなくてもよい
```
【React】State更新の際の注意点⚠️

# ReactにおけるState更新の際の注意点！！

## はじめに
この記事の対象読者はReactを学び始めの方を対象に書いています。
自身も学習中の身なので備忘録として、また、同じく学習されている方の力に少しでもなればと思います！

## Stateとは
簡単にですがStateについて記述しておきます。
```react
const[count, setCount] = useState(0);
```
Reactでは上記のようにStateを定義することができます。
上記例ではcount変数とsetCount関数が定義されており、Stateの記述方法として配列内の左側に更新される変数、右側にその変数を更新する関数（自動生成）が定義できます。この時の関数名は基本的には変数にsetをつけたものを定義する様にしましょう！
(0)の部分はこのStateの初期値を表しています。(1)という風にすれば、count変数の初期値は０になります。

## 学習中によくあるカウントアップStateその１
React学習しているとよく下記のようなサンプルがあります。
```react
import {useState} from "react";

export default function CountUp(){
  const [count, setCount] = useState(0);
  setCount(count + 1)
};
```
CountUp関数ないでuseStateでcount変数とsetCount関数作成し、
そのStateの変数にプラス１をするというシンプルなものです。

## 学習中によくあるカウントアップStateその２
それなりに学習が進むと下記のようなStateの更新方法いきなり出てこないでしょうか？
```react
import {useState} from "react";

export default function CountUp(){
  const [count, setCount] = useState(0);
  setCount((prevCount) => prevCount + 1);
};
```
初学者にとっていきなり見慣れない形出ると混乱しますよね、、、
上記コードではsetCount関数の引数に(prevCount) => prevCount + 1という関数を渡しているという構図です。
先ほど見せた更新方法の方が単純で分かりやすいと思いますが、この2つの更新方法の違いとはなんでしょうか？

## ２つの更新方法の違い
先ほどお見せしたStateの更新方法の違いとしては

- 最新の現在のStateを参照する
- 更新前のStateを参照する

上記のような違いがあります。
1番目の方法であれば現在のStateに対して変更を加えていくことができます。他の部分で変更があった際もその変更後に変更を加える形になります。
2番目の方法であれば、Stateがどこから更新されるかわからないので、更新される前のStateに変化を加えるのであれば２番目の更新方法です。また、２番目のprevCountはcount変数の更新前という意味でprevという引数で受け取ります。

これでさらにReactの学習が捗るのではないでしょうか！

## おわりに

最後まで見ていただきありがとうございました🙇
まだまだ学習中の身なので不備あるかもございませんので、その際はコメントよろしくお願い致します🙇

また今回の記事を備忘録として残そうと思った学習教材リンク貼っておきますのでよかったらご覧ください！
[今回の記事内容についての学習教材](https://www.techpit.jp/courses/194)
【Java】パッケージの使い方ガイド | 初心者向けチュートリアル

# はじめに
この記事では、Javaのパッケージについて初心者向けに解説します。パッケージは関連するクラスやインターフェースをまとめるための仕組みであり、プログラムのモジュール化や名前空間の管理に役立ちます。以下では、パッケージの基本的な使い方と、代表的な使用例を紹介します。

## パッケージの基本的な使い方
Javaでは、`package`キーワードを使用してパッケージを宣言します。
パッケージ宣言はソースファイルの先頭に記述される必要があります。
以下にパッケージの宣言例を示します。

```java
package com.example.mypackage;
```
パッケージ名は一意であることが推奨されます。
通常、逆DNS形式（ドメイン名を逆さにしたもの）を使ってパッケージ名を付けることが一般的です。

## 代表的な使用例
### java.utilパッケージのScannerクラス
java.utilパッケージには、ユーザーからの入力を受け取るための便利なクラスが含まれています。具体的には、コマンドラインやファイルからのテキスト入力を簡単に処理するための便利なツールです。
```java
//java.utilパッケージ、つまりフォルダからScannerクラス、
//つまりファイルをインポートします。
import java.util.Scanner;


//　これから任意の名称のオリジナルクラスを作成します
public class ScannerExample {
    // 実際の処理の内容を記述していきます
    // publicなので他のクラスから呼び出して使用できます。
    public static void main(String[] args) {
        
        // スキャナーというクラスはインスタンス化しなければ実行できません
        // System.inを引数で与えることでキーボードからの入力を読み取ることができます
        Scanner scanner = new Scanner(System.in);
        System.out.print("名前を入力してください: ");
        //scanner.nextLine()メソッドはユーザーが入力した文字列を取得します
        String name = scanner.nextLine();
        System.out.println("こんにちは、" + name + "さん！");
    }
}

```
上記のコードでは、Scannerクラスを使ってユーザーからの入力を受け取り、それを表示する処理を行っています。実行結果は以下のようになります。

```makefile
名前を入力してください: John
こんにちは、Johnさん！
```


## まとめ

パッケージとは、ファイルを整理、管理するためのフォルダのようなものになります
クラスをフォルダ分けすることで、たとえクラス名が重複してもフォルダが異なればインポートのアドレスが異なるため名前の衝突を回避することができるので名前空間の提供も行っています
オンプレミスのWindows ServerをAzureにバックアップする方法

### はじめに

Microsoft Azure Recovery Services (MARS) エージェントを使ってオンプレミスのWindows ServerのバックアップをAzureに取得する手順を確認していきます。
今回は環境がなかったのでAzure VMをオンプレミスのWindows Serverと見立ててエージェントを入れ、バックアップを取得していきます。

### Recovery Serviceエージェントをダウンロードする

コンテナーダッシュボードからバックアップを選択
![Backup1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/c008fe83-cb24-73fe-fbe9-590b9e625b22.png)

以下を選択。
ワークロードの場所：オンプレミス
バックアップするもの：ファイルとフォルダー、システム状態
![Backup2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/c99b6110-42d9-a813-9246-49da3ac12ede.png)

エージェント、コンテナの資格情報をダウンロード
![Backup3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/c227aebc-41da-6798-d15c-a57580ce46c3.png)

### エージェントをインストールする

インストーラを起動し、インストールとキャッシュフォルダの場所を選択
![Backup4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/b5a07044-7a3c-b73d-c9ff-e03a85573943.png)

プロキシ設定
![Backup5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/86dcb677-ba68-66d9-11d8-753eb4cf5e3e.png)

Microsoft Update
![Backup6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/9aef6b48-8a88-3830-6775-8cdf9b331adf.png)

インストール
![Backup7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/b1697189-e3c4-f511-9894-e379b78a2489.png)

コンテナ認証
エージェントと共にダウンロードしたコンテナ資格情報を選択
![Backup8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/4868cd92-582c-4b8d-1d4e-07dce4aea92d.png)

暗号化
![Backup10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/95f84daf-9a8e-c8df-f879-508cb827d241.png)
パスフレーズはサーバー自身ではなく、Azure Key Vaultなど外部に保存しておいた方がよいです。

完了
![Backup11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/d9b59be8-f92e-0abf-76e1-5dbe08d93f4f.png)
パスフレーズはこの後ローカルから削除し、Azure Key Vaultに登録しました。

### バックアップとデータ保持を構成する

バックアップをスケジュール
![Backup12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/2c117fc4-edd3-1128-0e84-940cd43180a3.png)

システム状態とバックアップしたいファイルまたはフォルダを選択
![Backup13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/9b5183b4-4fba-f69a-1350-44246f400f82.png)

バックアップスケジュールの選択
![Backup14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/60c37e0b-f6f6-1d2c-15a9-cd9852e7b088.png)

保持ポリシーの選択
![Backup15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/de7e7246-22f8-d117-1591-8e64c177288e.png)

初回バックアップの種類
![Backup16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/a95bfc52-ebc3-593f-1e85-37985fc01bb5.png)

### オンデマンドバックアップ

今すぐバックアップを選択
![Backup17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/36b9f934-eef0-cbba-bfc0-b1e02f09a7f6.png)
スケジュールバックアップを設定した後でないと表示されなかった？ように見える。

バックアップアイテム、保持期間を選択してバックアップを開始
![Backup18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/72fcc3b6-f2ff-b55d-e793-cb79e9a6ecce.png)

バックアップステータスをAzure上で確認
![Backup19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/815a5331-e574-5a83-05ed-8d6a10f37b0d.png)
データサイエンスのための微分積分 第17回 関数の連続性

:::note info
本記事は数学講座[2.16関数の連続性](https://www.matongxue.com/lessons/590/parts/956)を勉強して投稿したメモです。詳細は元の素晴らしい講座のページをチェックしてください。
:::

# 連続の定義

**定義：**
関数$y=f(x)$が$x_0$の局所に定義あり、且つ：
$\Delta x=x-x_0,\quad \Delta y=f(x_0+\Delta x)-f(x_0)$

もし：

$\lim_{\Delta x\to 0}\Delta y=\lim_{\Delta x\to 0}\left[f(x_0+\Delta x)-f(x_0)\right]=0$

であれば、関数$f(x)$が$x_0$点で**連続（Continuous）**。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/cd5efd36-b6b0-816b-469e-b2d1cc040a92.png)

また、
**以下の定義でも成立します。**

関数$y=f(x)$が$x_0$の局所に定義あり、且つ：
$\lim_{x\to x_0}f(x)=f(x_0)$
であれば、関数$f(x)$が$x_0$点で**連続（Continuous）**。

**連続**
![連続のコピー.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/128dff74-daf0-a01f-d053-cd3357da58b7.gif)

**連続ではない**
![連続ではない.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/df128556-24b8-3135-f368-e47cdfa1590d.gif)

# 左連続、右連続

- $\displaystyle\lim_{x\to x_0^-}f(x)=f(x_0)$、関数$f(x)$が$x_0$点で左連続です。
- $\displaystyle\lim_{x\to x_0^+}f(x)=f(x_0)$、関数$f(x)$が$x_0$点で右連続です。

左連続、且つ右連続が、関数連続の充分必要条件です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/4c993497-9a37-e93b-3b2f-fbfd8a825dea.png)

# 連続関数

**定義：**
区間内の全ての点で連続であれば、**区間内の連続関数**と呼びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/e1945340-a5ee-cb36-a414-1864328abb1e.png)


# 参考

https://math-fun.net/20210803/17016/
VSCode 内部のコマンドラインはVSCode自体を再起動しないとPATHが更新されない

タイトルの通りなんだけどこれで軽く30分ほどハマった。

やろうとしたことは
①Tensorflowを使おうとして、最新のCUDAをインストール
②最新のCUDAじゃ動かないことに気が付いて古いCUDAをインストール
③あれれ～？動かないぞ～？
④最新のCUDAをアンインストール
⑤エラー受け取る
~~~
import tensorflow as tf
2023-06-03 15:21:01.713053: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'cudart64_110.dll'; dlerror: cudart64_110.dll not found
2023-06-03 15:21:01.713295: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.
~~~
⑥ちゃんとPATHは通ってるしおかしいなぁ一体どういうことだ！！！(VSCode内でcmdを再起動したりする)

というわけです。
空の配列問題にて「true一択の回答以外は良くないプログラマである」と言い切って本当に良いのか、をなんとなく考えてみる

# 素晴らしき元ネタ
https://twitter.com/fumieval/status/1663161595009314819

```
「配列のすべての要素が条件を満たすならtrueを返す」関数を定義するとき、空の配列を渡したらfalseを返すかtrueを返すかが、良いプログラマかどうかの一つの境目だ
```

# 筆者のスタンス
true一択派も、仕様による派もどちらの主張も間違いとは言い切れないし、この回答を持って一概に「良くないプログラマ」であるとか、センスの有無を見出すのはちょっと言いすぎだし言葉が強すぎるかなぁ……
もっとHRT(謙虚、尊敬、信頼)意識していこうぜ……

ただし、falseに揃えるのはちょっとアンチパターンだろうとは思う。[^1]

# 注意
すべての主張を見たわけでもないので、認識の偏りや独自解釈などが含まれているかもしれません。
あくまで、「筆者はほんとに**なんとなく**考えたんだなぁ」ぐらいの優しい気持ちで見ていただけると幸いです。

# true一択派の主張を考える
実はtrue一択派も主張が別れている部分があって、
1. 仕様云々でなく、単純に「配列のすべての要素が条件を満たすならtrueを返す」という要件の関数を作れってことでしょ？派
2. どの仕様でも、trueにすべきでしょ。派

がいるっぽい。

ぶっちゃけ、元のツイートを見ると「どっちとも読めるのでなんとも……」といった感じ。
1. (単純に)「配列のすべての要素が条件を満たすならtrueを返す」(という要件の)関数
2. 「配列のすべての要素が条件を満たすならtrueを返す」(というフォーマットで書かれた要件の)関数

みたいな感じだろうか。

### 1番の主張を考える
単純に「配列のすべての要素が条件を満たすならtrueを返す」という要件の関数であれば、異論なくtrueで良いと思う。
まぁ正直いうとこれに関しては、感覚的に「これならtrueで書くなぁ……」ってぐらいのふわっとした感じなので、理由は説明しづらいところ。
頑張って言語化すると「0個の要素を確認して0回判定がtrueとなっているからすべての要素が条件を満たしとる言えるな」ぐらいの認識。[^2]

### 2番の主張を考える
いろんな要件を考えてみたけど、思いつく限りではどれもtrueがしっくり来る。
それ以外の場合でも、基本的に関数ごとに書き方・考え方が統一されていないのは問題を引き起こす元なので、例外的にfalseとするような形で実装するのは避けたほうが良いと思う。
正直なところ処理的にはfalseが都合が良い場合でも、trueで返す形に設計を見直したほうが良い気がしてる。

# 仕様による派の主張を考える
この派閥であっても、多くの人は **「(単純に)「配列のすべての要素が条件を満たすならtrueを返す」(という要件の)関数」** を実装する場合、trueにするのではないかなと思う。
なのでこの派閥の主張は、true一択派の「どの仕様でも、trueにすべきでしょ。派」と対比して考えた方が良さそうだ。

この派閥の主張について端的に言うと「いや、そう言ってもfalseの方が良いパターンは存在するんじゃない？」に近いのではと思う。

この考えはわからんでもない。
ここまで色々な要件を考えては見たが無限に存在する要件のうちの数例を見ただけであり、例外がないとも言いきれない。[^3]
そもそも「falseの方が良いパターンが存在しないこと」を証明するのはまさしく悪魔の証明だ。無理である。

# まとめ
各主張はそれぞれの視点で一定の正当性があるんじゃないかなと。
まぁ「ほとんどの場合はtrueに倒したほうがいいよ～」ぐらいのふわっとした感じでとどめておいて、もし仮にfalseとしたい場合は特殊な例として対処する感じがちょうどいいところな気がしてる。
とりあえずコメントとかドキュメントに残しておけばトラブルは少なそう。

今回ここまで話が大きくなってしまったのは、
-  **「配列のすべての要素が条件を満たすならtrueを返す」関数**というやや解釈が分かれてしまう記載
- 「良いプログラマかどうかの一つの境目」というちょっと強めの言い回し

が元なのかなと思う。

誰だって「お前はプログラマの資質がない！」みたいに言われたらムッとするし腹も立つだろう。
とはいえ、元ツイートを批判する気もあまりなくて、議題としてはなかなかそそられる内容だし議論も(傍から見てて)なかなか面白かったと思う。

今回のように議論を呼ぶプログラミング系のツイートは結構好きなので、たまにはこういうのも良いなぁと思いました。まる。[^4]


[^1]: すまねぇ、false派の主張そもそもあんま見かけんかったし、筆者も基本的にはtrueのほうが良いと思ってるからどうしようもなかった……
[^2]: 良いコーディングをしようとしたとき「経験的・感覚的にこう書いたほうが気持ちいいなぁ」ぐらいの感じで考えがちなので、言語化しづらいんよね。
[^3]: 「一粒の砂に世界を見、一輪の野の花に天を見る」とは言うけど、流石に今回に当てはめるのはちょっと厳しいだろう。
[^4]: とはいえ、今回の議論に関しては白熱しすぎてて今回の記事も書くか少し迷うぐらいには怖かったので、強すぎる主張はちょっと控えて欲しみはある。
【Paiza問題集】条件分岐メニュー/0が含まれていないか判定

# Paiza問題集

## 条件分岐メニュー/0が含まれていないか判定

### Step01 単純な条件分岐
```Python:step01
"""
単純な条件分岐
https://paiza.jp/works/mondai/conditions_branch/conditions_branch__simple_step1

問題
文字列Sが与えられます
Sがpaizaと一致する場合はYESを、一致しない場合はNOを出力してください
"""

print("YES" if input() == "paiza" else "NO")
```

### Step02 数値の分岐
```Python:Step02
"""
数値の分岐
https://paiza.jp/works/mondai/conditions_branch/conditions_branch__simple_step2

問題
整数Nが与えられます
Nが100以下の場合はYESを、そうではない場合はNOを出力してください
"""

print("YES" if int(input()) <= 100 else "NO")
```

### Step03 数値演算結果で分岐
```Python:step03
"""
数値演算結果で分岐
https://paiza.jp/works/mondai/conditions_branch/conditions_branch__simple_step3

問題
整数A,B,Cが与えられます
式A×B≦Cが成立している場合はYESを、そうではない場合はNOを出力してください
"""

A, B, C = map(int, (input().split()))

print("YES" if A*B<=C else "NO")
```

### Step04 ゼロ以外
```Python:Step04
"""
ゼロ以外
https://paiza.jp/works/mondai/conditions_branch/conditions_branch__simple_step4

問題
整数 N が与えられます
Nが0ではない場合はYESを、0である場合はNOを出力してください
"""

print("YES" if int(input()) != 0 else "NO")
```

### Final問題 0が含まれていないか判定
```Python:Final問題
"""
0が含まれていないか判定
https://paiza.jp/works/mondai/conditions_branch/conditions_branch__simple_boss

問題
長さNの数列Aが与えられます
Aの中に0が含まれていない場合はYESを、0が含まれている場合はNOを出力してください
"""

N = int(input())
A = [int(input()) for i in range(N)]

print("YES" if 0 not in A else "NO")
```
Mulesoft API-led connectivityについて

# はじめに
Mulesoft API-led connectivityとは、Mulesoftが推奨する、システムを統合するアーキテクチャの一種です。

この記事では、Mulesoft API-led connectivityと他の統合アーキテクチャを比較して、利点を紹介していきます。

# 伝統的な統合アーキテクチャとの比較

## 伝統的な統合アーキテクチャ
- Point-to-Point
- Hub and Spoke
- Enterprise Service Bus, ESB

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343120/9527231d-f896-00ca-1703-e6efc8ab419d.png)
出典：[Enterprise Service Bus (ESB) and SAP](https://rsol08.wordpress.com/2008/05/16/esb-and-sap/)

- **ポイントツーポイント（Point-to-Point）統合：** これは最も基本的な統合方法で、直接に一つのシステムと他のシステムを結びつけます。この方法はシンプルで理解しやすいですが、システムの数が増えるとその複雑性は指数関数的に増加します。
- **ハブ・アンド・スポーク（Hub and Spoke）型統合：** この方法では中心となる「ハブ」を導入し、全てのシステムをこの「ハブ」に接続します。これにより、システム間の接続数は大幅に減少しますが、この「ハブ」がボトルネックとなり、もし問題が発生すると全てのシステムに影響を及ぼす可能性があります。
- **エンタープライズサービスバス（Enterprise Service Bus, ESB）：** これはより複雑な統合方法で、共有メッセージ伝送層を提供し、全てのシステムをこの層に接続します。ESBはシステム間の通信に公共のメッセージ形式とプロトコルを使用することを可能にし、これにより統合を大幅に簡素化します。しかし、特に大規模な企業環境では、ESBは非常に複雑で重くなる可能性があります。

MuleSoftのAPI-led connectivityアーキテクチャは、エンタープライズサービスバス（ESB）と似ている面があります。

## API-led connectivityアーキテクチャ

### 3層構造

- Experience API
- Process API
- System API
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343120/7be8a8a7-1c0e-1637-9c54-dbee1508f88f.png)

- **Experience API:** この層は最終的なユーザーインターフェイスやチャネル（ウェブサイト、モバイルアプリ、POSシステムなど）にデータを提供します。体験APIは特定のユーザーエクスペリエンスに最適化されたデータとサービスを提供します。つまり、この層は「データを表示」します。
- **Process API:** この層はシステム層から提供されるデータを組織のビジネスプロセスに合わせて加工します。プロセスAPIは複数のシステムAPIを組み合わせて、より高度な操作を可能にします。この層はビジネスロジックを実装し、「データを整理」します。
- **System API:** この層は組織内の各種システムとサービス（データベース、ERPシステム、CRMシステムなど）に直接接続します。システムAPIはこれらのシステムからデータを取得し、それを他のAPIまたはサービスがアクセスできる形式に変換します。基本的に、この層はデータを「取り出す」役割を果たします。

### 利点

MuleSoftのAPI-led connectivityアーキテクチャは、それは現代のデジタルビジネスの高速なペースに適応するための、より柔軟で軽量な統合アーキテクチャを提供しています。

APIの再利用、標準化、セキュリティ向上、新たなビジネスチャンスへの迅速な対応など、API-led connectivityの多くの利点を可能にします。

# おわりに
最後までお読みいただき、本当にありがとうございました。
Mulesoftに関する、すこし理解できましたら幸いです。気になる点があったらお知らせください。
ProxmoxでIPv6を無効化する

現時点ではとくにIPv6は不要なので無効化します。
# ステータス確認
IPv6が有効なことを確認します。
```
ip addr 
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/d1f618a5-e199-4a2a-e3f0-71820a80f545.png)

# コンフィグ追記
```/etc/sysctl.conf
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/b77e7797-59e3-a5b9-8e2c-1009a4631765.png)

# 再起動、ステータス確認
IPv6が無効なことを確認します。
```
ip addr 
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/a8f90720-225f-a378-b249-6ab7c5200260.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/962376ea-ed1a-368f-fbf6-047ad814a257.png)

# 参考にさせていただいたサイト
RaspberryPiのIPv6を無効化する
https://uepon.hatenadiary.com/entry/2023/04/26/055714
データサイエンスのための微分積分 第16回 無限小の比較

:::note info
本記事は数学講座[2.15無限小の比較](https://www.matongxue.com/lessons/588/parts/947)を勉強して投稿したメモです。詳細は元の素晴らしい講座のページをチェックしてください。
:::

# よくある無限小

- $\sin x\sim x$
- $\tan x\sim x$
- $\arcsin x\sim x$
- $\arctan x\sim x$
- $\ln(1+x)\sim x$
- $e^x-1\sim x$
- $(1+x)^\alpha-1\sim \alpha x$
- $1-\cos x \sim \frac{1}{2} x^{2}$



# 無限小の比較

**定義（無限小の比較）：**
$\alpha と \beta $が同一の独立変数の変化過程であり、対応する局所領域で $\alpha \neq 0 $が成り立つ場合、次のように定義します：

（1）$\displaystyle\lim \frac{\beta}{\alpha}=0 $のとき、$\beta$ は $\alpha$ より**高次の無限小**と言います（Infinitesimal of higher order）、$\beta=o(\alpha)$ と表記します。

（2）$\displaystyle\lim \frac{\beta}{\alpha}=\infty $のとき、$\beta は \alpha $より**低次の無限小**と言います（Infinitesimal of lower order）。

（3）$\displaystyle\lim \frac{\beta}{\alpha}=c \neq 0 $のとき、$\beta と \alpha$ は**同次の無限小**と言います（Infinitesimal of same order）。

（4）$\displaystyle\lim \frac{\beta}{\alpha^k}=c \neq 0, k > 0$ のとき、$\beta は \alpha$ の **k 次の無限小**と言います（Infinitesimal of order k）。

（5）$\displaystyle\lim \frac{\beta}{\alpha}=1 $のとき、$\beta と \alpha$ は**等価な無限小**と言います（Equivalent infinitesimal）、$\alpha \sim \beta $と表記します。

上記は**無限小の比較** の定義です。

**定理：** 
$\alpha$与 $\beta$为が等価無限小の条件が：
$\beta-\alpha=o(\alpha)\iff\beta\sim\alpha$

証明：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/4a0ff3df-ca9c-1013-0316-42c9a5226066.png)


# 等価無限小の置き換え

**定理:**
$\alpha\sim \alpha_1$，$\beta\sim \beta_1$，且つ$\displaystyle \lim_{}\frac{\alpha_1}{\beta_1}$存在であれば、$\displaystyle \lim_{}\frac{\alpha}{\beta}=\displaystyle \lim_{}\frac{\alpha_1}{\beta_1}$があります。

証明：
```math
\displaystyle \lim_{}\frac{\alpha}{\beta}=\displaystyle \lim_{}(\frac{\alpha}{\alpha_1}\cdot \frac{\alpha_1}{\beta_1} \cdot \frac{\beta_1}{\beta})=\displaystyle \lim_{}\frac{\alpha_1}{\beta_1}
 ```

# 等価無限小の例題

**例1:**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/8bef7ba9-b3a4-e941-793d-3f6cc5ad7c00.png)


**例2:**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/0ecc7d90-7d61-b75c-16c1-831e0fb412be.png)


**例3:**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/48387636-9686-7fe0-da74-7840849b51ac.png)

正しい方法は**挟み撃ち**定理の応用です：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/df9dba30-2876-aec3-011b-f5765eeb81db.png)

# 練習

**練習１:**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/fde948bc-9046-3d55-8c9e-18c2d71a749a.png)

**練習2:**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/6910dbd6-bbb6-f5a9-1c18-3a86d40d1fe8.png)


**練習3:**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/9669e934-18c6-8155-5758-bfdb1968a174.png)
ProxmoxでLinuxVM用にゲストエージェントをインストールする

# 経緯
ネストしたゲストProxmoxに対してインストールします。現状では未インストール状態。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/b88876b6-ec63-bed8-fa4d-9a5a170ece37.png)

VMオプションではデフォルトで有効になっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/394f7fba-1b91-4fbc-8483-8a03c6accebd.png)


# パッケージインストール
Debianに適したインストールコマンドを実行します。
```
apt-get install qemu-guest-agent
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/d91c803d-f0c5-e23e-168a-0de3098e23b1.png)

# 確認
再起動してIPが表示されることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/e57f6a29-0c43-60fd-4678-04fc6569cde3.png)

# 参考にさせていただいたサイト
Qemu-guest-agent
https://pve.proxmox.com/wiki/Qemu-guest-agent
【ChatGPT無】にとって、翻訳も言語変換も同じ（JavaScript→Python他）


　どうも、カーブミラーです。

　前回の
[【ChatGPT＋JavaScript】関数を作成したら、どうする？](https://qiita.com/kabumira/items/6cfc9678b24ebc9bdd2b)
　で、
　　**コーディングルールプロンプト**と
　　　**仕様書プロンプト**を
　　　　提示しました。

　今回は、
　　そのコードを言語変換します。

　「言語変換って、なに？」と
　　思われた方も多いかな？

　　ようするに
　　　プログラミング言語Ａから
　　　　プログラミング言語Ｂに
　　　　　変換することです。

　　そう、翻訳です！


　とりあえず、
　　サンプルコードを
　　　用意しました。
　ChatGPTに指示して
　　作ってもらったものです。

　このくらいのコード、
　　自分でも、書けるんだからね！
　　　面倒なだけなんだからね！

```JavaScript:サンプルコード
/**
 * 文字列を指定された回数分連結して返す関数
 * @param {string} prm_str - 連結する文字列
 * @param {number} prm_count - 連結回数
 * @returns {string} - 連結された文字列
 */
function concatenateString(prm_str, prm_count) {
  // 引数の妥当性をチェック
  if (typeof prm_str !== 'string' || typeof prm_count !== 'number') {
    return ''; // 引数が適切でない場合は空文字列を返す
  }

  if (prm_count < 1 || prm_count > 10) {
    return ''; // 回数が範囲外の場合も空文字列を返す
  }

  let wk_result = ''; // 連結結果の文字列

  for (let lp_i = 0; lp_i < prm_count; lp_i++) {
    wk_result += prm_str; // 文字列を連結
  }

  return wk_result;
}
```

　では、
「**上記のコードをJavaScriptからPythonに変換してください。**」
　と入力します。

```Python:変換後のPythonコード
def concatenate_string(prm_str, prm_count):
    """
    文字列を指定された回数分連結して返す関数
    :param prm_str: 連結する文字列
    :param prm_count: 連結回数
    :return: 連結された文字列
    """
    # 引数の妥当性をチェック
    if not isinstance(prm_str, str) or not isinstance(prm_count, int):
        return ''  # 引数が適切でない場合は空文字列を返す

    if prm_count < 1 or prm_count > 10:
        return ''  # 回数が範囲外の場合も空文字列を返す

    wk_result = ''  # 連結結果の文字列

    for _ in range(prm_count):
        wk_result += prm_str  # 文字列を連結

    return wk_result
```

　どうやら、
　　Python化の際に、
　　　関数名が変更されたようですね。
　　関数のコメントも
　　　Pythonスタイルに変更されたし。

　それから、ChatGPTさんから
>JavaScriptとPythonでは、文法や組み込み関数などの細かい違いがありますので、コードを変換する際には注意が必要です。変換後のPythonコードが正常に動作するか確認してください。

　と言われました。
　　まぁ、そのとおりですけどね。

　ちなみに、
　　Pythonだけではなく、
　　　Pascal
　　　VBScript
　　　VBA
　　　FORTRAN
　　　Rust
　　　Go
　　までイケました。
　　　たぶん、ほかにもイケる！

　　もちろん、
　　　動作確認していません。
　　　　ごめんなさい。

　それから、
　　遊んでいて、
　　　ひとつ思い付いたのが
　　　「**疑似言語（日本語）**」です。
　　　　“（日本語）”と付けたのは、
　　　　　英語での出力をしてきたから。

```Text:疑似言語
関数 concatenateString(文字列 prm_str, 数値 prm_count) -> 文字列
  // 引数の妥当性をチェック
  もし prm_str の型が文字列でない または prm_count の型が数値でない場合:
    空文字列を返す

  もし prm_count が 1 未満 または 10 を超える場合:
    空文字列を返す

  文字列 wk_result を空文字列で初期化する

  ループ lp_i を 0 から prm_count 未満まで繰り返す:
    wk_result に prm_str を連結する

  wk_result を返す
```

　できた。
***
　まぁ、言語変換なんて、
　　どこまで需要があるのか
　　　わかりませんけど。

　ですが、
　　Ａという言語を理解している人が、
　　新たなＢという言語を学ぶ上では、
　　　こうした言語変換は、
　　　　有効でしょう。

　　ChatGPTさんは、言葉を扱うＡＩ。
　　翻訳も言語変換も同じなんですね。
静力学と材料力学 発展例題1.16 p11「材料力学演習(20221021)」をsympyでやってみた。 

# オリジナル
発展例題1.16 p11
http://zairikiweb.starfree.jp/zai_enshuh/zai_enshuh_ver.3.3.pdf#page=16

「材料力学演習(20221021)一括(ver.3.3)」を勉強したい。＞sympy
https://qiita.com/mrrclb48z/items/c3274daf5f7a99cfe027#%E4%BD%9C%E6%A5%AD%E4%B8%AD%E7%A7%81%E3%81%AE%E8%A7%A3%E7%AD%94sympy

# sympyで
「def myBibun」が怪しいです。アドバイスいただけると助かります。
```python
from sympy import *
N,dN,dx,q,g,A,E,N0,x,L,P,e=symbols('N dN dx q g A E N0 x L P e',real=True)
a,b                       =symbols('a b'                       ,real=True)
def myBibun(f,dN,dx):
   return solve(f,dN)[0]/dx
myF=Eq(N+dN/dx*dx-N+q*g*A*dx,0)
Nx =integrate(myBibun(myF.lhs,dN,dx),x)+N0
Nx =Nx.subs({N0:solve(Eq(Nx.subs({x:L}),P),N0)[0]})
ex =Nx/(A*E).subs({x:e}).expand()
SGx=integrate(ex,x).expand()
print("#",SGx.subs({x:L}))
# L**2*g*q/(2*E) + L*P/(A*E)
```
①私の環境は,pycharmです。
②よく聞くのは、Jupyterです。
③web上で、上記のソースを「SymPy Live shell」に、コピー貼り付けでもできました。
黒背景の右上に、マウスを移動すると、コピーマークが発生します。
???　タブレット環境で、コピー貼り付けが実行できませんでした。???

https://live.sympy.org/

# Mathematicaで
勉強中

# 作図
勉強中
Leetcode #28. Find the Index of the First Occurrence in a String

# Problem
String Matchingに関する問題です。
> Given two strings needle and haystack, return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack

この問題では、haystack (干し草の山）と呼ばれる文字列の中から、needle(縫い針)と呼ばれる文字列が含まれるかどうかを判定します。参考までに、A needle in a haystackはイディオムで、広大な干し草の山の中からneedle縫い針を探すことから、「至難の業」「針の穴に糸を通すよう」といった意味になります。

InputとOutputの例は次になります。
```
Input: haystack = "sadbutsad", needle = "sad"
Output: 0
Explanation: "sad" occurs at index 0 and 6.
The first occurrence is at index 0, so we return 0.
```

https://leetcode.com/problems/find-the-index-of-the-first-occurrence-in-a-string


## Approach 1 
Naïveな方法として、下記のような回答を考えました。

```python
class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        for i in range(len(haystack) - len(needle)+1):
            if haystack[i:i+len(needle)] == needle:
                return i
        return -1
```
繰り返しの回数に気をつけてください。例えば、haystack="abcde"(5文字), needle="xyz" (3文字)の場合、繰り返す必要がある回数は3回になります。この３回というのは、「haystackの文字数 5 - needleの文字数 3 + 1 」となります。

この解法では、計算量は下記の様になります。

- Time complexity: O(NM)
Nはhaystackの長さ、Mはneedleの長さとしています。

- Space complexity: O(M)
haystack[i:i+len(needle)]という箇所で、Pythonのスライシング処理を用いているためです。
面接官によっては、Space complexityでより効率性を求める解法に誘導するかもしれません。その場合は、下記のApproach 2のように対応します。

## Approach 2
Approach 1のスライシングの代わりに、一文字ずつ比較をして確認をします。


```python
class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        for i in range(len(haystack) - len(needle)+1):
            for j in range(len(needle)):
                if haystack[i+j]  != needle[j]:
                    # 内側のループからbreak
                    break 
                
                if j == (len(needle) -1):
                    return i
        return -1
```
この解法では、Time complexityはApproach #1と同じくO(NM)ですが、Space complexity はスライシングを使っていないのでO(1)になっています。

## Reference
Rabin-Karp Algorithm 等のアルゴリズムについては、別の機会にします。
ProxmoxでIPアドレスとホスト名を変更する

# 経緯
ホストProxmox上でネストしたProxmox（VM107）を作成しましたが、これをクローン（VM108）するとIPとホスト名がかぶりますので変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/4c56bc7f-fc89-b5ac-88f0-d6604c707fc8.png)


# NICコンフィグ変更
IPを適宜変更します。
```/etc/network/interfaces.
address 192.168.100.12/24
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/e525b019-977d-572c-ef19-174e718af74a.png)

# ホスト名変更
任意の名前に変更します。
```/etc/hostname.
pve3
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/84150c1c-2522-6266-a5e0-0769bffcf08c.png)

```/etc/hosts.
192.168.100.12 pve3.test pve3
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/0914c676-9b72-61c6-1d69-21f052b87c77.png)

# 再起動
再起動してアクセスを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/2c6f29e2-0056-6410-7f60-3293bddeb17e.png)



# 参考にさせていただいたサイト
Changing Proxmox IP from CLI
https://www.youtube.com/watch?v=3JR5XPkab-c

How to Change the IP Address of Proxmox VE
https://www.wundertech.net/how-to-change-the-ip-address-of-proxmox-ve/

Proxmoxでホスト名またはノード名を変更する
https://qiita.com/honahuku/items/7335158659cfb1b4580f
ansibleでfirewalld停止と無効化

firewalldを停止して無効化してみました。

```
cat firewalld.disable.yml
---
- hosts: all
  become: yes
  tasks:
    - name: Start and enable firewalld
      service:
        name: firewalld
        state: stopped
        enabled: no
```

```
ansible-playbook -i inventory.ini firewalld.disable.yml
```



次もただの真似です。

https://nwengblog.com/ansible-service/
Leetcode #27. Remove Element



## Problem
> Given an integer array nums and an integer val, remove all occurrences of val in nums in-place. The order of the elements may be changed. Then return the number of elements in nums which are not equal to val.

この問題は、指定された値と等しくない要素のみを持つように配列を変更し、そのような要素の数を返すことを求めています。
InputとOutputの例は次になります。
```
Input: nums = [0,1,2,2,3,0,4,2], val = 2
Output: 5, nums = [0,1,4,0,3,_,_,_]
```
Outputのnums配列については、最初の5つの要素が正しければ何でもよく、順番も関係ありません。そのため、[0,0,1,3,4]としたり[0,1,4,0,3,X,X,X]としてもpassします。

Trickyな点としては、配列操作をin-placeに実行するという制約です。つまり、既存の配列のみを使い、追加の配列を作成してはいけないということです。
https://leetcode.com/problems/remove-element/description/

## Key Idea
配列を2つのポインタを使います。
１つ目のポインタは、fast-runnerとして、配列を走査するために利用します。

In placeにnumsというリストを変更するため、
Outputとして、numsというリストをin-placeに操作して、左からk個の要素全てがvalではないように並び替える必要があります。
ここで「どこまで並び替えたか」を管理するのに2つ目のポインタを使います。(slow-runner)
言い換えると、このポインタより左の要素は、全てvalではない値で統一されているという仕切りになります。

簡単に手順を書くと下記のようになります。ここではfast-runnerをreader, slow-runnderをwriterという名称にしています。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99549/f9c33ae2-8e3d-7a3a-fac3-dfce9cba5f31.jpeg" width="500">

## Approach 1 
上記のアイデアは、下記の様にかけます。
```Python
class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        k = 0 
        writer = 0
        for reader in range(len(nums)):
            if nums[reader] != val:
                nums[writer] = nums[reader]
                k += 1
                writer += 1

        return k
```

ここで、kとwriterは実質同じ挙動になっていることがわかります。そのため、writerというポインタをなくして、kを活用することができます。

## Approach 1'
kとwriterという２つの変数が冗長であるため、一つにまとめることができます。
```Python
class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        k = 0 
        for reader in range(len(nums)):
            if nums[reader] != val:
                nums[k] = nums[reader]
                k += 1

        return k
```

計算量は下記の様になります。

1. Time Complexity： O(n)

ここで、nは配列numsの要素数です。これは、アルゴリズムが配列の各要素を一度だけ走査するためです。

2. Space Complexity： O(1)
入力のサイズに関わらず、使用するメモリ量は一定です。


## Reference
- https://www.youtube.com/watch?v=Pcd1ii9P9ZI
NextJSをDockerコンテナ上で起動する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/2a743d80-2df7-44e3-0af6-3933a469fb36.png)


# Dockerコンテナを使ってNextJsアプリケーションを起動してみます。

# Create a new Next.js app using create-next-app

```terminal:terminal

    mkdir nextjs-docker
    cd nextjs-docker

    npx create-next-app@latest .
```

# Create a Dockerfile and .dockerignore file

```terminal:terminal

    touch Dockerfile
    touch .dockerignore

```

# Directory structure

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/8fdadc29-56e0-4470-c236-10c609a21d44.png)


# Write the Dockeefile

```Dockerfile:Dockerfile
    FROM node:20.2.0-alpine
    
    WORKDIR /usr/src/app
    
    COPY . /usr/src/app/
    
    RUN npm install --production
    
    RUN npm run build
    
    EXPOSE 3000
    
    CMD ["npm", "start"]
    
```

# Write the .dockerignore

```Dockerfile:.dockerignore
    node_modules
```

# Build the Docker image

```terminal:terminal
    docker build -t nextjs-docker:1.0 .
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/a60f0713-9551-d692-f0fd-55e07ca96ae0.png)


# Run the Docker image

```terminal:terminal
    docker run -it -d --rm -p 3000:3000 --name next-app nextjs-docker:1.0
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/55fcce8e-1387-090a-c2de-4b6f9a474647.png)


# Open your favorite browser and navigate to http://localhost:3000 you get the nextjs page

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/099eca4f-8b09-1d3c-bbe5-1fb95695fb5c.png)


# Remove this Container
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/fc74e14e-809c-cb99-6a49-62f6ee80413d.png)

###  You can craete a next app on the Docker container. :tada:
ansibleでselinuxを無効してOS再起動

selinux無効化とOS再起動まで成功しました。


```
# cat selinux_disable.yml
---
- hosts: all
  tasks:
  - name: Disable SELinux
    ansible.posix.selinux: state=disabled
    become: true

  - name: Reboot
    ansible.builtin.reboot: reboot_timeout=60
    become: true
```

```
ansible-playbook -i inventory.ini selinux_disable.yml
```

以下のサイトをまねしただけ
https://tex2e.github.io/blog/infrastructure/ansible-selinux
ストワで始めるLua 第九回 アクティブソナー

https://www.nicovideo.jp/watch/sm42301211

https://www.nicovideo.jp/watch/sm42301191


```lua:activve sonar

--Initialize
pi=math.pi
pi2=pi*2
dt=1/60
waterSoundSpeed=1480*dt
range=property.getNumber('range')

behindAngle=math.rad(3) --Backward angle not visible.

activeData={}
pingTick=0
isPing=false

function onTick()

	isPingPush=input.getBool(19)
	
	if isPingPush and isPing==false then
		isPing=true
		activeData={}
		pingTick=0
	end

	if isPing then
		--Sonar data input
		for i=0,15 do
			if input.getBool(i+1) then
				local x,y
				x=input.getNumber(i*2+1)*pi2
				y=input.getNumber(i*2+2)*pi2
				if pi-behindAngle >= x and -pi+behindAngle <= x then
					table.insert(activeData,{distance=(pingTick*waterSoundSpeed)/2,bearing=x,elevation=y})
				end
			end
		end
		
		pingTick=pingTick+1
	end

	if (pingTick*waterSoundSpeed)/2 >range then
		isPing=false
	end
	output.setBool(1,isPing)
end

function onDraw()
	local w,h,cw,ch,radius
	--resolution
	w=screen.getWidth()
	h=screen.getHeight()
	--center
	cw=w/2
	ch=h/2
	--display sonars circle radius
	radius=h/2-3
	
	--drawing echo
	screen.setColor(0,255,0,128)
	for i=1,#activeData do
		local echoX,echoY
		echoX=cw+(activeData[i].distance/range)*radius*math.sin(activeData[i].bearing)
		echoY=ch-(activeData[i].distance/range)*radius*math.cos(activeData[i].bearing)
		screen.drawCircleF(echoX,echoY,2)
	end
	
	--drawing circle
	screen.setColor(0,255,0)
	screen.drawCircle(cw,ch,radius)
	screen.drawText(0,0,string.format("%.0f",range))
end
```
Optunaを用いたハイパーパラメーターチューニングの実践

こんにちは！この記事では、機械学習のモデルを最適化するためのハイパーパラメータチューニングにOptunaを使用する方法について説明します。

## Optunaとは？

Optunaは、Pythonで書かれた機械学習のハイパーパラメータチューニングを自動化するためのフレームワークです。Optunaは非常にフレキシブルで、各種の機械学習ライブラリ（例えば、scikit-learn、TensorFlow、PyTorchなど）のハイパーパラメータを最適化するために利用できます。

## ライブラリのインストール

まずは必要なライブラリをインストールします：

```python
!pip install optuna scikit-learn
```
## Optunaの基本的な使い方
Optunaの使用法を説明するために、scikit-learnのSVC（サポートベクターマシン）を使用します。
```python
import optuna
from sklearn.datasets import load_digits
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score

# データセットをロードします
digits = load_digits()
X = digits.data
y = digits.target

def objective(trial):
    # SVCのハイパーパラメータの候補範囲を設定します
    C = trial.suggest_loguniform('C', 1e-10, 1e10)
    gamma = trial.suggest_loguniform('gamma', 1e-10, 1e10)
    kernel = trial.suggest_categorical('kernel', ['linear', 'poly', 'rbf', 'sigmoid'])

    # モデルを設定します
    svm = SVC(C=C, gamma=gamma, kernel=kernel)

    # クロスバリデーションによるスコアを計算します
    score = cross_val_score(svm, X, y, n_jobs=-1, cv=3)
    accuracy = score.mean()

    return accuracy

study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=50)

# 最良のパラメータを出力します
print('Best parameters: ', study.best_params)
```
この例では、SVCの3つのハイパーパラメータ（C, gamma, kernel）について、それぞれの候補範囲を設定し、最適なハイパーパラメータの組み合わせを探索しています。

## まとめ
Optunaは、機械学習モデルのハイパーパラメータチューニングを容易に行うことができる強力なツールです。さまざまなモデルとライブラリに対応しているため、モデルの性能を向上させるための重要なツールとなります。

これからもOptunaを使って、機械学習のモデルを最適化し、高性能なモデルを作成しましょう！
Pythonで実践するマルチラベル分類のStratified K-Fold交差検証：ステップバイステップガイド

## 1. はじめに
データの分割方法は、機械学習モデルの性能を評価する際に大きな影響を与えます。この記事では、マルチラベル分類問題においてよく使用される分割方法の1つ、Multilabel Stratified K-Fold Cross Validationについて詳しく解説します。

## 2. K-Fold Cross Validationとは？
K-Fold Cross Validationは、データをK個の「フォールド」に均等に分割し、1つのフォールドをテストデータとし、残りのフォールドを訓練データとしてモデルを訓練し、その性能を評価します。このプロセスをK回繰り返し、それぞれの評価結果の平均をとることで、モデルの性能をより正確に評価することができます。

## 3. Stratified K-Fold Cross Validationとは？
Stratified K-Fold Cross Validationは、K-Fold Cross Validationの一種で、各フォールドが全体の目標変数の分布をなるべく保つようにデータを分割します。つまり、各クラスの比率が全体と同じになるようにします。これは、クラスの不均衡があるデータセットに対して特に有用です。

## 4. Multilabel Stratified K-Fold Cross Validationとは？
マルチラベル分類問題では、各インスタンスが複数のラベルを持つ可能性があります。そのため、Stratified K-Foldを直接使用すると、各フォールドでの各ラベルの比率を保つことができません。この問題を解決するために、Multilabel Stratified K-Fold Cross Validationが使用されます。この方法では、各フォールドが全体の各ラベルの分布をなるべく保つようにデータを分割します。

## 5. Pythonでの実装
sklearnのStratifiedKFoldを使用する代わりに、skmultilearn.model_selection.IterativeStratificationを使用して、マルチラベル分類の問題に対するStratified K-Foldを実装することができます。
```
from skmultilearn.model_selection import IterativeStratification
import numpy as np
import pandas as pd
from sklearn.datasets import make_multilabel_classification

# 例として、マルチラベルデータセットを生成
X, y = make_multilabel_classification(n_samples=1000, n_features=20, n_classes=5)

# n_splitsは分割数、ここでは5とする
n_splits = 5
k_fold = IterativeStratification(n_splits=n_splits, order=2)

for train_index, test_index in k_fold.split(X, y):
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]

    # ここでモデルの訓練と評価を行う
    # ...
```
## 6. まとめ
この記事では、マルチラベル分類問題におけるMultilabel Stratified K-Fold Cross Validationの概要とPythonでの実装方法について解説しました。これを活用することで、マルチラベル分類の問題に対するモデルの性能評価をより正確に行うことができます。
「ChatGPTに個人情報を送らないように気をつける」を自動化してみる（プロンプトの匿名化処理）

ChatGPT、使っていいよっていう組織は増えてきたが、プロンプトに個人情報や機密情報は含めないでね、というルールになっているところが多い。

# とはいえうっかりもある
ということで、エンジニアなら自動化しよう！と、OpenAIに送信する前にローカルや信頼できるサーバーで隠すべき情報を隠し（匿名化）たうえで、送信する、ということが出来ないか考えた。

![ja_demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5080/d0c287a8-fda7-5811-decc-7ca46ca13fa1.gif)

# 方式を考えた
とりあえず、個人情報を隠すということを目標にした。
ChatGPTに送るのは文章なので、正規表現などでは対応しきれないだろうと考えた（メールアドレスや電話番号などは対応できそうだが、名前や住所は難しそう）

## 使用ライブラリ
いろいろ情報を探していると、Presidioというデータ保護や匿名化のためのライブラリを見つけた。
https://github.com/microsoft/presidio

Presidioに含まれる、Presidio analyzerとPresidio anonymizerというモジュールを利用することにした。
Presidio analyzerは個人情報の検知をしてくれる。spaCyを使った自然言語処理による検知が可能。
Presidio anonymizerはPresidio analyzerが出した結果に基づいて、匿名化処理を行ってくれる。

このライブラリを使うだけでOKかな、と思ったのだが、処理結果をプロンプトとして使用するには少し不便な点があった。

## プロンプトとして適切になるよう出力の調整

### 同じものは同じと分かるように
プロンプトとして使用する場合、同じ情報は同じであることが分かった方が適切な回答を得やすいと考える。

例えば、以下のような文章について、

> 「**山田太郎**は来週誕生日です。**山田太郎**の友人である**山田花子**はプレゼントをあげようと考えています。**山田花子**が**山田太郎**に渡すプレゼントとして適したものを提案してください。」

> 「**人名**は来週誕生日です。**人名**の友人である**人名**はプレゼントをあげようと考えています。**人名**が**人名**に渡すプレゼントとして適したものを提案してください。」

となるより

> 「**人名_A**は来週誕生日です。**人名_A**の友人である**人名_B**はプレゼントをあげようと考えています。**人名_B**が**人名_A**に渡すプレゼントとして適したものを提案してください。」

となった方が、適切な匿名化であると考えた。

Presidio anonymizerのいくつかある匿名化のオプションで上記に近いのは、ハッシュで置き換えるものであった。

ハッシュで置き換えた場合、以下のようになる。
「**6b0e1c8cc616be88a16bef09ef113a91a3ecceb0f157bae276e200624932912f**は来週誕生日です。**6b0e1c8cc616be88a16bef09ef113a91a3ecceb0f157bae276e200624932912f**の友人である**dbb7bf97673bebd709723021f12c31104866677277fbf93838d409ac4c680d55**はプレゼントをあげようと考えています。**dbb7bf97673bebd709723021f12c31104866677277fbf93838d409ac4c680d55**が**6b0e1c8cc616be88a16bef09ef113a91a3ecceb0f157bae276e200624932912f**に渡すプレゼントとして適したものを提案してください。」

これだとかなり読みにくいし、もう一つ問題がある。

### 何を匿名化したかは分かっていい

「**山田太郎**（ **090-0000-0000** ）は来週誕生日です」という文章をハッシュで置き換えると、
「**6b0e1c8cc616be88a16bef09ef113a91a3ecceb0f157bae276e200624932912f**（ **019ed474a1e51cc4d93c1f034478ab1440ac1871c8dc3e56b300275b94d2dc7d** ）は来週誕生日です」
になってしまい、もともと何が書かれていたのか分からない文章になってしまった。

### 結果

ということで、Presidio anonymizerの出力をさらに加工し、以下のような出力になるように調整した。

原文：
> 「**山田太郎**（ **090-0000-0000** ）は来週誕生日です。**山田太郎**の友人である**山田花子**はプレゼントをあげようと考えています。**山田花子**が**山田太郎**に渡すプレゼントとして適したものを提案してください。」

匿名化後：
> 「**人名_A**（ **電話番号_A** ）は来週誕生日です。**人名_A**の友人である**人名_B**はプレゼントをあげようと考えています。**人名_B**が**人名_A**に渡すプレゼントとして適したものを提案してください。」

## UI
Chromeの拡張にして、ChatGPTの画面に入力された文章を匿名化するようにするとか、既にいくつか存在するOSSのGUI開発プロジェクトのプラグインのような形で作ることも考えたが、とりあえずCLIで動くようにした。

# コードはこちら

https://github.com/akazah/prompt-anonymizer/blob/main/README_ja.md

# 感想
とりあえず、出来るかなと思ったことができた。
もう少し難しいことしないといけないかと思ったが、そんなにたくさんの量のコード書かずに実現できた。
感覚を現時点の状況にアップデートし続けるためにも、改めてコードを常時書くようにしようと思った。

あと、タイトルに「ChatGPTに個人情報を送らないように」と書いたが、今のコードでは、OpenAIのChat Completion APIに送っている。
いずれもGPT-3.5やGPT-4を使って応答を返してくるが、異なるものだ。
いくつかの企業が、Chat Completion APIを使ってChatGPTに似たインターフェースのサービスを提供し始めているが、そういう形であれば、今回のような匿名化の処理も挟みやすい。
一方、ChatGPT自体を使うときにプロンプトを匿名化したい、ブラウザ拡張のような形にならざるを得ない。匿名化処理はローカルで行うのが良いと思うが、ブラウザ拡張で今回の処理と同じことができるだろうか、、あるいは別の方式があるだろうか、、など考えている。
Out-Of-Fold (OOF) による機械学習モデルの評価

Out-Of-Fold (OOF) の実装は、一般的にはScikit-LearnのK-Foldクロスバリデーションを用いて行います。以下に、単純な分類器を用いたOOFのPythonによる実装の例を示します。
```
from sklearn.model_selection import KFold
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
import numpy as np
```
# Out-Of-Fold (OOF) による機械学習モデルの評価

## 1. OOFとは？

Out-Of-Fold (OOF)とは、クロスバリデーションの一部で、特にK-foldクロスバリデーションの際に用いられる概念です。データセットをK個の部分集合（フォールド）に分け、K-1個のフォールドを訓練データとし、残り1個のフォールドをテストデータとして利用します。この手法を全てのフォールドに対して繰り返し、その結果得られた予測値の平均を計算します。

このようにすることで、モデルの未見のデータに対する予測性能をより正確に評価することができます。

## 2. OOFのPythonによる実装

以下に、RandomForest分類器を用いたOOFのPythonによる実装の例を示します。

```python
from sklearn.model_selection import KFold
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
import numpy as np

# サンプルデータセットの生成
num_samples = 100
num_features = 10
X = np.random.rand(num_samples, num_features)
y = np.random.randint(0, 2, size=num_samples)  # バイナリクラスラベル

# K-Fold設定
n_splits = 5
kf = KFold(n_splits=n_splits, shuffle=True, random_state=42)

# OOF予測値を格納する配列
oof_predictions = np.zeros(num_samples)

# 分類器の設定
clf = RandomForestClassifier(random_state=42)

# クロスバリデーション実行
for train_index, test_index in kf.split(X):
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    
    # モデル学習
    clf.fit(X_train, y_train)
    
    # OOF予測値の保存
    oof_predictions[test_index] = clf.predict(X_test)

# OOFスコア（この場合はaccuracy）を計算
oof_score = accuracy_score(y, oof_predictions)
print(f'OOF Score: {oof_score}')
```

## 3. OOFの利点
OOFは、モデルの一般化性能をより正確に評価することができます。これは、全体のデータセットを使用してモデルを訓練し、そのモデルを使用して全体のデータセットに対する予測を行う代わりに、各フォールドをテストデータとすることで、モデルが未見のデータに対してどの程度適合するかを確認することができるためです。

また、OOFスコアはモデルの過学習を防ぐため、また異なるモデルのパフォーマンスを比較するためにもよく用いられます。
機械学習の予測モデルでのポストプロセス手法

こんにちは、今回は機械学習の予測モデルにおける「ポストプロセス」について説明します。ポストプロセスとは、モデルが出力した予測結果を後処理する手法の一つです。特に、特定のクラスへの予測確率を調整する際に用いられます。

## ポストプロセスの一例

以下に、ポストプロセスを適用する簡単な例を示します。ここでは、特定のクラス（クラス1）への予測確率を増強することを目指します。

```python
import numpy as np

# 仮の予測確率
preds = np.array([0.1, 0.4, 0.35, 0.7])

# ブースティング係数
boost = 4.7

# オッズを計算しブーストする
odds = boost * preds / (1 - preds)

# オッズを確率に戻す
preds_boosted = odds / (1 + odds)
```
この例では、まず予測確率（preds）をオッズに変換し、ブースティング係数（boost）を掛けています。その後、ブーストされたオッズを再び確率に戻しています。結果として、クラス1に対する予測確率が強化（ブースト）されます。

## なぜポストプロセスを行うのか？
ポストプロセスは、モデルの出力を直接調整することで、特定のクラスの予測精度を向上させるのに役立ちます。たとえば、不均衡なデータセット（一部のクラスのサンプル数が他のクラスに比べて少ない）でモデルを訓練する際、少数クラスの予測精度が低下することがあります。このような場合、ポストプロセスを適用することで、少数クラスの予測精度を向上させることが可能となります。

## 注意点
ポストプロセスを適用する際には、ブースティング係数（boost）を適切に設定することが重要です。この値はモデルやデータによって異なります。最適な値を見つけるためには、様々な値を試し、クロスバリデーションやテストセットによる評価を行うことが必要です。

## まとめ
ポストプロセスは、予測モデルの結果を微調整する効果的な手法です。特定のクラスへの予測確率を増強したい場合などに有用です。ただし、ブースティング係数の設定には注意が必要です。最適な値はモデルやデータにより異なるため、様々な値を試してみることをお勧めします。