OmniAICreator/Qiita-1.07M huggingface dataset:
DM機能のURL設計について

こんにちは！Yuyaです。
現在、Xのクローンアプリを開発しています。
DM機能の実装でレビューをいただき、RESTfulなURL設計についてご指摘をいただいたのでアウトプットしていきます。

# レビュー前のURLについて
以下がレビュー前のコードです。

```config/urls.py
from django.urls import include, path

urlpatterns = [
    ...
    path('message/', include('apps.chats.urls')),
    ...
]
```

```chats/urls.py
from django.urls import path
from .views import RoomUserListView, MessageView, CreateMessageView

app_name = 'chats'

urlpatterns = [
    path('', RoomUserListView.as_view(), name="message_list"),
    path('<int:user1_id>-<int:user2_id>/', MessageView.as_view(), name="message"),
    path('<int:user1_id>-<int:user2_id>/create/', CreateMessageView.as_view(), name="message_create"),
]
```
## なぜこのようなURL設計にしたのか
- XのDM機能が `/messages/<user1_id> - <user2_id>`となっていたから
- RESTfulなURL設計を考えていなかったから
- URLで`送信者-受信者`とした方が直感的にわかりやすいと考えたから

# レビュー内容
>自分の`user_id`は`session`から撮れば良いので、相手の`user_id`のみパスパラメータで取得するのが良い。パスに関しては、`users/:user_id/messages`のようにするのがよいですね。

**めちゃくちゃ引っかかった**部分がありました。
それはパスに関しての文章です。

私の考えとしてはレビューをいただいてからも以下の考えは変わりませんでした。
- `/message`：メッセージ一覧
- `/message/<user1_id> - <user2_id>`：任意のユーザーとのメッセージ一覧

`message`から始まっているのに、なぜ`users`が次に来るのかわからず
流石にこれはレビュワーの方がタイポ？考えが間違っているのではないかと思ったので、同じ課題を取り組んでいる方に相談をしました。

# HC生と技術的な相談をして
結論、私のURL設計がRESTfulではないということが明らかになりました。
具体的には5つの問題が発生します。

### 曖昧性
- user1が自分でuser2が相手なのか不明
- URLだけ見て誰の視点かわからない
- 同じ会話に対して複数のURLが存在する可能性

### 権限チェックの複雑化
- user1, user2どちらがログインユーザーなのかチェック
- 相手ユーザーのIDを特定

### 非直感的なURL構造
```python
/message/123-456/create/  # 何を作成するのか不明確
```

### セキュリティ面での問題
```python
# URLから他人の会話を推測可能
/message/100-101/  # ユーザー100と101の会話
/message/100-102/  # ユーザー100と102の会話
/message/101-102/  # ユーザー101と102の会話（推測可能）
```

### 動詞を使用している
```python
# messageは動詞
path('message/', include('apps.chats.urls')),

# createは動詞
path('<int:user1_id>-<int:user2_id>/create/', CreateMessageView.as_view(), name="message_create"),
```

### 単数形vs複数形の非統一
- RESTfulでは複数形が標準
- 一覧取得なのか個別取得なのか区別できない

# 改善後
レビューワーの方からのご指摘を受けて、RESTfulなURLを意識したURLは以下のようになりました！
```config/urls.py
from django.urls import include, path

urlpatterns = [
    ...
    path('messages/', include('apps.chats.urls')), #messagesと複数形に変更
    ...
]
```
```chats/urls.py
from django.urls import path
from .views import RoomUserListView, MessageView

app_name = 'chats'

urlpatterns = [
    path('', RoomUserListView.as_view(), name="message_list"),
    
    # # GET, POST
    path('users/<int:receiver_id>/messages', MessageView.as_view(), name="message"),
]
```

# RESTful URL設計時のチェックポイント
- [ ] 名詞を使用している（動詞を避けている）
- [ ] 複数形を使用している
- [ ] 階層構造でリソースの関係を表現している
- [ ] HTTPメソッドでアクションを表現している
- [ ] 一貫性のある命名規則を使用している
- [ ] URLから技術的詳細を隠している
- [ ] 略語を避けて明確な名前を使用している
Arduino IDEを使った、M5Stack書き込みエラー修正

# はじめに
自分自身のメモのために書いてます。
一応公開するので、誰かの役に立つと嬉しいです。
雑なのは許してください。

# エラー内容
Arduino IDEを使用してM5Stackに書き込みを行いたい。
コンパイルは成功するが、書き込みが上手くいかない。
永遠にuploading errorが出る。

## エラーコード
```
usage: esptool [-h]
               [--chip {auto,esp8266,esp32,esp32s2,esp32s3beta2,esp32s3,esp32c3,esp32c6beta,esp32h2beta1,esp32h2beta2,esp32c2,esp32c6,esp32h2}]
               [--port PORT] [--baud BAUD]
               [--before {default_reset,usb_reset,no_reset,no_reset_no_sync}]
               [--after {hard_reset,soft_reset,no_reset,no_reset_stub}]
               [--no-stub] [--trace] [--override-vddsdio [{1.8V,1.9V,OFF}]]
               [--connect-attempts CONNECT_ATTEMPTS]
               {load_ram,dump_mem,read_mem,write_mem,write_flash,run,image_info,make_image,elf2image,read_mac,chip_id,flash_id,read_flash_status,write_flash_status,read_flash,verify_flash,erase_flash,erase_region,merge_bin,get_security_info,version}
               ...
esptool: error: argument operation: invalid choice: '{upload.flags}' (choose from 'load_ram', 'dump_mem', 'read_mem', 'write_mem', 'write_flash', 'run', 'image_info', 'make_image', 'elf2image', 'read_mac', 'chip_id', 'flash_id', 'read_flash_status', 'write_flash_status', 'read_flash', 'verify_flash', 'erase_flash', 'erase_region', 'merge_bin', 'get_security_info', 'version')
Failed uploading: uploading error: exit status 2
```
## デバイスやその他情報
デバイスマネージャーより、ポートは「USB-Enhanced-SERIAL CH9102
（COM3）」

M5Stackを接続すると、LilyGo T-Displayが自動選択された。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624480/c7c71db8-0d56-459c-a57d-335e150953d5.png)


# 対処法１（失敗）
https://mag.switch-science.com/2021/11/01/m5stack-v2-6-changes/
M5Stackのv2.6でCH9102Fドライバーの更新が必要らしい
CH9102Fのドライバを入れたが、できない。
https://docs.m5stack.com/en/download
USB Driver & Open source LibraryのCH9102_VCP_SER_Windows実行


# 対処法２（成功）
設定を変えてみる。以下のサイトにある手順を１つ１つこなしていく。
https://ameblo.jp/bongbongbong73/entry-12881301336.html

うまくいった！ボードを「esp32 dev module」にしたら成功。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624480/f4b08223-c145-4424-8f97-26452acc6564.png)

検索ワード「usb-enhanced-serial ch9102 アップデート」
エラー修正に２週間かかった。やっとできてよかった。
Livewire 2→3へのアップデートでどハマりしたので記録

# アップデート
公式ドキュメント通り
```
sail composer require livewire/livewire "^3.0"
```
として
```
sail artisan livewire:upgrade
```
とする。この時の選択肢は全てデフォルトで回答。

これで満を持して元プロジェクトのlivewireの動作を確認しようとしたが、全然動かない。チュートリアルにある一番シンプルなカウンターすら動かない。色々試行錯誤しているとconsoleに
```
Livewire: The published Livewire assets are out of date
 See: https://livewire.laravel.com/docs/installation#publishing-livewires-frontend-assets
 ```
 というwarningが出ているのに気づいたので
 ```
 sail artisan livewire:publish --assets
 ```
 としてみたら``public/vendor/livewire``以下に色々なファイルが自動生成され、結果的に動いた。でもドキュメントを見てみると、assetをpublishするやり方は標準じゃないとのこと。なんで動かないのか理解するのに丸一日かかった。

 # 解決策

よく見たら、アップデートする前から``public/vendor/livewire``というフォルダがあって、それがLivewire 2ベースなのが問題だった。そもそもなんでこんなものがあるのかよくわからないが、何かのタイミングで作ったんだろう。これがあるのがいけないので
```
rm -rf public/vendor/livewire
```
とした。Alpineが重複するので``resources/js/app.js``の中身からAlpineの記載を削除して、
```
npm uninstall alpinejs
```
としたら動いた。

# Alpineだけを使いたい場合
Livewireを使うページでは自動的にAlpineがバンドルされるが、そうでないページでAlpine単独で使いたい場合は
```
<html>
<head>
    ...
    @livewireStyles
</head>
<body>
    ...
    @livewireScripts
</body>
</html>
```
のようにしないといけない。公式ページにちゃんと書いてあった。
C#によるPDFをHTMLへの変換

もしC#でPDFファイルをHTMLに変換する無料のソリューションを探しているなら、[**Free Spire.PDF for .NET**](https://www.e-iceblue.com/Introduce/free-pdf-component.html)は軽量でありながら強力なライブラリで、その仕事を完遂します。有料版と比較するとページ制限がありますが、小規模プロジェクトやテストには最適な出発点です。このブログでは、Free Spire.PDF for .NETライブラリを使用して**PDFをHTMLに効率的に変換**する方法を解説します。

## Free Spire.PDF とは？
[Free Spire.PDF for .NET](https://www.e-iceblue.com/Introduce/free-pdf-component.html) は、Spire.PDF のコミュニティ版であり、基本的な PDF 処理機能を提供します。主な特長は以下の通り：
■ **主な機能**
* 無料利用可：個人用途・商用用途ともに料金をかけません。
* シンプルな API：C#/.NET プロジェクトへ簡単に統合できます。
* 基本的な変換機能：PDF を HTML、画像、またはテキストに変換可能（制限あり）。

■ **制限事項**
* 1 つの PDF ファイルあたり最大 10 ページまで処理可能。
* 変換時には最初の 3 ページまでのみ対応。
* 定期的な保守更新が行われていません。


## C# で PDF を HTML に変換する手順ガイド

#### ステップ 1: Free Spire.PDF をインストールする  
C# プロジェクトに Free Spire.PDF の NuGet パッケージを追加します：  
* NuGet パッケージ マネージャーを使用する方法：  
```
PM> Install-Package FreeSpire.PDF 
```
* または、以下のリンクからダウンロードし、手動で DLL をインポートする方法：

https://www.e-iceblue.com/Download/download-pdf-for-net-free.html


#### ステップ 2: PDF を HTML に変換する  
以下は、Free Spire.PDF を使用して PDF ファイルを HTML に変換する基本的なコード例です：
```csharp
using Spire.Pdf;

namespace ConvertPdfToHtml
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // PDF文書を読み込む
            PdfDocument pdf = new PdfDocument();
            pdf.LoadFromFile("抹茶.pdf");

            // PDFをHTML形式に保存する
            pdf.SaveToFile("PdftoHtml.html", FileFormat.HTML);
            pdf.Close();
        }
    }
}
```

![ConvertPDFtoHTML.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/17d95984-8ffa-4bea-9684-f3ca7a12631a.png)


## 変換オプションをカスタマイズする
変換時には、必要に応じて変換オプションを設定することもできます。この場合、**`PdfConvertOptions`** クラスの **`SetPdfToHtmlOptions`** メメソッドを使用します。
このメソッドは次のパラメーターを含みます。
* **`useEmbeddedSvg`**: SVG を埋め込め込むかどうか。
* **`useEmbeddedImg`**: 画像を埋めめ込むかどうか。useEmbeddedSvgが「False」に設定されている場合にのみ適用されます。
* **`maxPageOneFile`**: 1つのHTMLファイルに対する最大ページ数。useEmbeddedSvgが「False」に設定されている場合にのみ適用されます。
* **`useHighQualityEmbeddedSvg`**: 生成されたファイル内で高品質の埋めめ込み SVG を使用するかどうか。useEmbeddedSvgが「True」に設定されている場合にのみ適用されます。

以下のコードスニペットは、変換オプションを設定して、生成される HTML 内に画像を埋め込み、かつ HTML ファイルごとに 1 ページに制限する例です。
```csharp
HTML file PdfConvertOptions pdfToHtmlOptions = pdf.ConvertOptions; 
pdfToHtmlOptions.SetPdfToHtmlOptions(false, true, 1, false);
```
* * *
このガイドに沿って操作することで、Spire.PDF の機能を活用して静的な PDF を動的で Web に適した HTML コンテンツに変換することができます。SaaS ツールを開発している場合でも、クライアントの Web サイトを強化する場合でも、このライブラリは時間と労力を節約します。

**:closed_book: すぐに試してみますか？**
* [詳細なコード例についてはドキュメントを参照してください。](https://www.e-iceblue.com/Tutorials/Spire.PDF/Spire.PDF-Program-Guide/Spire.PDF-Program-Guide-Content.html)  
* [質問があれば、フォーラムで自由に投稿してください。](https://www.e-iceblue.com/forum/spire-pdf-f7.html)
基礎のBool, String, Int のデータ型の簡単にまとめてみた  Swift言語（初心者の向け🔰）

swift初心者向けに、Bool, String, Int の基礎的な内容をわかりやすくまとめた記事を作ってみました👇

1. Bool（ブール型）
使い道： 「はい」か「いいえ」のように、**真（true）か偽（false）**の2つの値しか持たないデータ型。


よく使う場面： 条件分岐（if文など）でよく使われます。

![Screenshot 2025-05-27 at 16.03.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3977742/dbb98494-f96c-4a35-b826-10ca8f2ee054.png)



-----

2.String（文字列型）
使い道： 文字や文章を扱うデータ型。

ポイント： + で文字列をつなげたり、文字数を数えることもできます。

let greeting = "こんにちは"
let name = "Takeshi"
let message = greeting + "、" + name + "さん！"

print(message) // 出力: こんにちは、Takeshiさん！
print(message.count)    // 出力: 13

![Screenshot 2025-05-27 at 16.23.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3977742/7e12eddf-edfb-4262-b3a9-bd1540d5c0e9.png)



-----
3.Int（整数型）
使い道： 整数（小数点のない数字）を扱うデータ型。

![Screenshot 2025-05-27 at 16.15.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3977742/3df1d0f7-e837-4d7a-855b-d95641569c06.png)


----
まとめ

- Bool

内容：true / false の2つの値を持つ

例：let isLogin = true

- String

内容：文字列を扱う

例："Hello"

- Int

  内容：整数を扱う  
  例：let score = 100


 基礎のBool, String, Int のデータ型の簡単にまとめてみました！
 
 ぜひ参考にしてください🙌
Geant4のインストール

# Geant4のインストール
以前書いた記事を更新する。
https://qiita.com/niikura/items/6e34ae5d4bcb74a38669
今回は、v11.3.2をMacBook Air (M2 2022) にインストールする。

## 準備

あらかじめ入れておく必要があるのは、qtとcmake。他にもあるかも。qtは最新はqt@6だがqt@5を入れておかないとコンパイルできなかった。
```zsh
brew install cmake qt@5
... (中略) ...
If you need to have qt@5 first in your PATH, run:
  echo 'export PATH="/opt/homebrew/opt/qt@5/bin:$PATH"' >> ~/.zshrc

For compilers to find qt@5 you may need to set:
  export LDFLAGS="-L/opt/homebrew/opt/qt@5/lib"
  export CPPFLAGS="-I/opt/homebrew/opt/qt@5/include"
```
書かれているように```.zshrc```に追記する。以前書いた記事とはhomebrewの場所が変わっているので注意。
```.zshrc
export PATH="/opt/homebrew/opt/qt@5/bin:$PATH"
export LDFLAGS="-L/opt/homebrew/opt/qt@5/lib"
export CPPFLAGS="-I/opt/homebrew/opt/qt@5/include"
export PKG_CONFIG_PATH="/opt/homebrew/opt/qt@5/lib/pkgconfig"
```
Geant4の最新版をダウンロードする。
https://geant4.web.cern.ch/download/11.3.2.html

## インストール

解凍して、buildおよびinstallするディレクトリを作る。
```zsh
tar zxvf geant4-v11.3.2.tar.gz
mkdir geant4-v11.3.2-build
mkdir geant4-v11.3.2-install
cd geant4-v11.3.2-build
```

あとはcmakeして、make, make installするだけ。
```zsh
cmake \
-DCMAKE_INSTALL_PREFIX=/opt/geant4/geant4-v11.3.2-install \
-DGEANT4_USE_QT=ON \
-DGEANT4_INSTALL_DATA=ON \
../geant4-v11.3.2/
```
```zsh
make -j8
make install
```
これでインストールできる。

## 確認
まずは環境設定。zshrcに下記を追記。
```.zshrc
export CMAKE_INSTALL_PREFIX=/opt/geant4/geant4-v11.3.2-install
alias geant4='source $CMAKE_INSTALL_PREFIX/bin/geant4.sh;cd ~/g4work/'
```
作業ディレクトリを作って移動。
```zsh
mkdir g4work
source $CMAKE_INSTALL_PREFIX/bin/geant4.sh
cd g4work
```
サンプルをコピーする。
```zsh
cp -r /opt/geant4/geant4-v11.3.2-install/share/Geant4/examples/basic/B1 .
mkdir B1-build
cd B1-build
```
コンパイルして実行する。
```
cmake ../B1
make
./exampleB1
```
これで下記のようなウィンドウが表示されたら成功。
![スクリーンショット 2025-05-27 16.16.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225701/4f9bedf2-99e1-4137-8be7-da5f7761a337.png)

## 参考
https://qiita.com/oXyut/items/3962eff8f660856e7acd
Microsoft 365 インストール方法

✅ 手順概要
① ダウンロード用構成ファイルの作成
download.xml という名前で次のように保存します：

```download.xml
<Configuration>
  <Add SourcePath="C:\OfficeDL" DownloadPath="C:\OfficeDL" OfficeClientEdition="64" Channel="Current" Version="17328.20794">
    <Product ID="O365ProPlusRetail">
      <Language ID="ja-jp" />
    </Product>
  </Add>
  <Display Level="None" AcceptEULA="TRUE" />
</Configuration>
```
🔍 補足：

SourcePath および DownloadPath に Office を保存するフォルダ（例：C:\OfficeDL）を指定します。

Version は 2408 に該当するビルド番号（例：17328.20794）を指定します。
https://learn.microsoft.com/ja-jp/officeupdates/update-history-microsoft365-apps-by-date

② ダウンロード実行
コマンドプロンプトを 管理者として実行し、以下のコマンドを入力：

```cmd
cd C:\ODT
setup.exe /download download.xml
```
完了すると C:\OfficeDL に Office ファイル群がダウンロードされます。

③ インストール用構成ファイルの作成
install.xml という名前で次のように保存します：

```install.xml
<Configuration>
  <Add SourcePath="C:\OfficeDL" OfficeClientEdition="64" Channel="Current" Version="16.0.17726.20126">
    <Product ID="O365ProPlusRetail">
      <Language ID="ja-jp" />
    </Product>
  </Add>
  <Display Level="None" AcceptEULA="TRUE" />
  <Property Name="AUTOACTIVATE" Value="1" />
</Configuration>
```
📌 SourcePath を 先ほどダウンロードしたフォルダにします。

④ インストール実行
同様にコマンドプロンプトで以下を実行：

```cmd
cd C:\ODT
setup.exe /configure install.xml
```
これにより、ダウンロード済みの Office がインストールされます。
欠損値の対処方法まとめ

# ■はじめに

Excelではハンドリングしきれないボリュームのデータをいじる際、NaN/nullの処理を正しく理解してキッチリ前処理しておかないと大惨事を起こし切腹不可避となる。分母とする列がNaNまみれだったりとか、DataFrameどうしをマージする時とか。
自分用の備忘録として、Python、pandasでの使用頻度が高い対処方法をまとめておく。

# ■df.dropna()
みんな大好きなやつ。
NaN/nullデータがいるrowを消す。

```python
df.dropna(axis=1)  # NaNを含む列を削除
df.dropna(subset=['col1', 'col2'])  # 特定の列にNAがある行だけ削除
```

# ■df.fillna(value)
NaN/nullデータに値(0)とかを代入する。

# ■ skipna=
## skipna=False

```python
# 例

df['new_col'] = df[['x', 'y']].min(axis=1, skipna=False)
```
やっていること：
・dfから'x', 'y'の二列を取り出す。
・axis=1：行方向に最小値を計算する（各行で 'x' と 'y' のどちらが小さいかを比較）
・skipna=False：NaNがある場合は無視せず、NaNを含む行の結果もNaNにする
・最小値の計算結果をdf の 'new_col' という新しい列に代入する

```python
[5.0, NaN, NaN]
```
みたいになる。

## skipna = True 
```python
# 例

df['new_col'] = df[['x', 'y']].min(axis=1, skipna=True)
```
sikipna部分だけ置き換えると、こんな感じの出力になる。
```
[5.0, 20.0, 30.0]
```

# ■ isna() / notna()
特定のセルがNAかどうかを判定するやつ。
```python
df[df['col'].isna()]      # 'col' がNAの行を抽出
df[df['col'].notna()]     # 'col' がNAでない行を抽出
```

# ■ combine_first()
2つのDataFrameを比較して、NAを埋める。
```python
df['col'] = df['col1'].combine_first(df['col2'])
# col1がNAならcol2の値で埋める
```

# ■ where() / mask()
私はほぼやらないけど、条件に応じてNAを代入したいとき。
```python
df['col'] = df['col'].where(df['col'] > 0)  # 0以下の値をNAにする
df['col'] = df['col'].mask(df['col'] <= 0)  # 同じ
```

# ■感想
メーカーや工場だけでなく、データ加工屋もヒヤリハット、KY(危険予知)等やるべきだと思う。
【Python】CORSエラー等のバグは循環importかも【Flask】

 超初歩的なミスですが、関連情報が見つからないので共有しておきます。

## TL;DR
循環参照ダメ、絶対(CORS, Flaskに限らず)
linterを入れよう

## やりたかっとこと・エラー
- フロント Next.js  (※今回フロント側は一切関係ないです)
- バックエンド Flask
で、Next側からFlask側のAPIを叩きたいが、flask runで動かすとCORSエラー。
 本番環境では動作するが、dev環境ではエラーになる。



## そもCORSとは？
Cross Origin Resource Sharing(オリジン間リソース共有)。
通常はオリジン(ドメインやポート)が異なる外部サーバーからのリクエストは弾かれるが、CORSを設定することで選択的にリクエストを通すことが可能。
Flaskにおいては、flask_corsモジュールでCORS機能が提供されています。

## ダメだったプログラム
簡素化しています。

```:ディレクトリ
app
├── api
│   ├── routes.py
│   └── services.py
├── __init__.py
└── config.py
```

```Python:/app/__init__.py
from app import create_app
from flask_cors import CORS

app = Flask(__name__)

CORS(app, origins=[
    FRONT_URI,
    FROT_DEV_URI
], supports_credentials=True)


if __name__ == '__main__':
    app.run(debug=True)
```


```Python:/app/api/routes.py
from . import api

@api.route("/news-summary", methods=["GET"])
def get_news_summary():
    return hogehoge()
```

```Python:/app/api/__init__.py
from flask import Blueprint

api = Blueprint('api', __name__)

from . import routes
```

## 原因
　はい、**循環参照**です。
　気づいたときはもうアホかと思いましたが、routes.pyと__init__.pyで相互にimportしているせいでおかしくなっていました。

```Python:/app/api/routes.py
from . import api
```

```Python:/app/api/__init__.py
from . import routes
```

　本番環境の場合とdev環境のCORS以外の機能は正常に動いていたので、余計に解決が遅れました。





<details><summary>参考: ChatGPTによる説明「Pythonにおいて循環importは未定義動作ですか？」</summary>

ChatGPT:
Pythonにおいて循環インポート（circular import）は**未定義動作（undefined behavior）**とは言いませんが、意図しないエラーやバグを引き起こす可能性があるため注意が必要な動作です。

循環インポートとは？
例えば、以下のようにモジュールAとBが互いにインポートし合っている状態です：

```Python
# module_a.py
from module_b import func_b
def func_a():
    print("A")
    func_b()

# module_b.py
from module_a import func_a
def func_b():
    print("B")
    func_a()

```
Pythonの挙動（仕様上の動作）
Pythonのインポートは実行時に行われ、モジュールは最初にインポートされた時点で一度だけ評価（=実行）されます。

循環インポートがあると、片方のモジュールの定義がまだ終わっていない状態でもう片方から参照されることがあり、その結果、AttributeError や ImportError が発生することがあります。

これは 未定義動作（undefined behavior） ではなく、Pythonの明示的な仕様の中で起こる定義済みの挙動ですが、開発者の意図と食い違いやすく、バグの温床になります。

対処方法
循環インポートが問題になる場合、以下のような対処が推奨されます：

インポートの位置を関数内に移動する：

```Python
def func_a():
    from module_b import func_b
    print("A")
    func_b()
```
依存関係を見直し、設計を分離・整理する：

共通の機能を別モジュールに切り出すなど。

遅延インポート（lazy import）や型ヒントのための if TYPE_CHECKING を使う：

```Python
from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from module_b import SomeClass
```

結論
Pythonにおける循環インポートは「未定義動作」ではなく、「仕様上は定義されているが、予期しないエラーを引き起こすリスクが高いため、避けるべき構造」です。コード設計や依存関係の整理を通じて、循環参照を避けることが推奨されます。









</details>


## 解決法
　\_\_init\_\_.pyに切り分ける意味があまりない分量に感じたので、routes.pyに統合したら動きました。

```Python:/app/api/routes.py
api = Blueprint('api', __name__)

@api.route("/news-summary", methods=["GET"])
def get_news_summary():
    return hogehoge()
```

　たぶんもっとベターな構成はありますがとりあえず。
　あと同じことを絶対に今後もやらかすので、戒めのためlinter(flake8)を導入しました。

## 所感
　そもそも循環importでエラーが起きないことを知らなかったので、Pythonが嫌いな理由が一つ増えそう(でも好き)でしたが、linterがあるので耐えです。
　何につけてもネットの記事を丸コピするのはよくないですね。
【Android】OpenCV4.11.0導入エラー対策

# 概要

AndroidアプリにOpenCV4.11.0を導入した際のエラー対策について解説。

# 導入方法

下記の記事を参照。

https://qiita.com/Khiroka/items/59d35f92963b31e1b633

https://qiita.com/kazu09/items/5812e24cfe2b21db9b03

# エラー内容

下記ビルドエラーが発生。

```
error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering
File being compiled: 
XXX/[プロジェクト名]/opencv/java/src/org/opencv/core/MatAt.kt
```

# 対策方法

下記の2通り。

- Kotlinのバージョン調整
- `MatAt.kt`修正

詳しくは[こちら](https://note.com/naka_inc/n/n90f6a1694c3e)。

https://note.com/naka_inc/n/n90f6a1694c3e
TopicのNew ボタンがない



+ [Enhance Agentforce to Act on Data with Conversational Language](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000PYpjJ)

:::note 
 If you disable it, the New button will be displayed. 

Ensure your assistant isn’t active, it should show an Activate button.
If it shows a Deactivate button, click Deactivate. 
:::

+ [Can someone help me? I am on the Coarl Cloud Resort Playground and I got to a point that I cant move forward on.](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000PZGA00AP)

+ [Not able to add New button while adding custom action in standard topic in agent studio](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000TiSXN)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/3a4e6f34-b90e-47c9-80a1-c011fda5e56d.png)

:::note
Try clicking the save button

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/9ce582e4-4a02-40a6-800f-0a6eb7e37ce5.png)
:::

+ [agentforce agent: no "new" button in topic's detail page.](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000SWh4L)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/2d5ea868-0e1c-48bb-8821-d9acffc73efc.png)

:::note
Click on the Topic Settings tab, scroll down and click on the Save button. 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/9384b1ea-c4d9-4d69-ae70-f46a09f6968d.png)
:::

new versionボタンの時もあるかも

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/387e1649-2333-4caa-bc03-68f65236384e.png)
「今の会社にいても伸びない」不安にどう向き合うか — 30代、“成長してる実感がない”ときに試したいアクション5選

1. 「過去の自分」と比較して成長を見直す
昇進しない、評価されない、仕事がルーチン化していると感じるとき、つい同僚や周囲と自分を比較しがちですが、比べるべきは“過去の自分”です。
先月や昨年の自分と比べて、どんな小さな変化や成長があったかを振り返ることで、成長実感を得やすくなります。

2. 自己分析とスキルの棚卸しを行う
今の仕事が自分の価値観やスキルと合っているかを見直し、これまで培ったスキルや経験を一度書き出して整理しましょう。
棚卸しによって「自分の強み」「これから伸ばしたいスキル」が明確になり、今後のキャリア設計や学び直しの指針になります。

3. 具体的なキャリアゴールを設定する
「このままでいいのか」と感じるときは、短期・中期・長期のキャリアゴールを設定し、そこから逆算して必要なアクションを考えることが重要です。
ゴールが明確になると、日々の業務にも意義や目的が生まれ、モチベーション向上につながります。

4. 副業・学び直しで新たな刺激を得る
現職だけで成長を感じられない場合は、副業やオンライン講座で新しい分野に挑戦し、スキルアップや視野拡大を図るのも有効です。
副業やリスキリングは、セルフマネジメント力や時間の使い方を見直すきっかけにもなります。

5. 人間関係や働き方を再構築する
信頼できる同僚や外部のコミュニティと交流し、新しい視点や刺激を得ることも大切です。
また、マネジメント職や現場スペシャリストなど、自分の志向に合った働き方を模索し直すことで、停滞感や閉塞感を打破できます。
laravel 【 __invoke 】について

## 1. __invoke メソッドとは
invoke？ と聞けばあの曲が脳内再生されるのは、私だけではないはず…。
（SEEDファンにはたまらないやつですね）
![seed.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842139/e412dcc3-c2b8-458b-9b22-90af6cd02b0d.jpeg)
…と余談はさておき。

### 「invoke」の意味
「invoke」は英語で「呼び出す」という意味。
PHPでは` __invoke() `という名前の 特殊メソッド（マジックメソッド） を定義することで、
クラスのインスタンスを「関数のように」呼び出す ことができるようになります。

###  Laravelでの主な用途
Laravelでは、__invoke は主に以下のような場面で使われます
✅ シングルアクションコントローラ
→ 1つの処理だけを担当する簡潔なコントローラを作りたいとき
✅ サービスクラスの関数的活用
→ 再利用可能な処理を、関数のようにスッキリ書きたいとき
✅ 処理をクラス単位に分けて、テストや責務の分離をしたいとき

## 2. 使用例：サービスクラスとしての活用
以下は、`UpdateStatusService` というサービスクラスを作成し、
`yController` および `zController` の中で共通の更新処理として再利用している例です。

🔧 サービスクラス：UpdateStatusService
```
<?php

namespace App\Services;

use App\Model\Xxxxx;

class UpdateStatusService
{
    /**
     * ステータスを更新する
     */
    public function __invoke(Xxxxx $xxxxx, string $status): void
    {
        $xxxxx->update([
            'status' => $status,
        ]);
    }
}
```
このように __invoke メソッドを定義することで、
このクラスは「関数」のように $updateStatusService($xxxxx, $status) と呼び出せるようになります。


🧩 yControllerでの使用例
```
public function updateStatus(Request $request, UpdateStatusService $updateStatusService): JsonResponse
{
    // ※権限チェックなどの処理は割愛

    // ステータス更新処理をサービスクラスに委譲
    $updateStatusService($lesson, $request->status);

    return response()->json([
        'result' => true,
    ]);
}
```

🧩 zControllerでの使用例
```
public function updateStatus(Request $request, UpdateStatusService $updateStatusService): JsonResponse
{
    // ※権限チェックなどの処理は割愛

    // 同様にサービスクラスを呼び出してステータス更新
    $updateStatusService($lesson, $request->status);

    return response()->json([
        'result' => true,
    ]);
}
```

## 3. __invoke を使うメリット
メリット	説明
✅ 関数のように呼び出せる	$service($data) のようなスッキリした記述になる
✅ 責務の分離	コントローラの肥大化を防ぎ、1クラス1責任にできる
✅ テストしやすい	ロジックが独立しているため、ユニットテストも簡単
✅ Laravelの依存注入と相性◎	自動でコンストラクタやサービスを注入してくれる

## 4. まとめ
`__invoke()` は、関数のようにクラスを呼び出せる「ちょっと便利な魔法」です。

サービスクラスや単一処理のコントローラ、バリデーションなど、Laravelのコードを
より読みやすく、テストしやすく、再利用性の高い形にできる 強力な仕組みです。
新卒・第二新卒が抱えるモヤモヤ の正体 5選

「“何者かにならなきゃ”という焦りの正体」
1. 周囲との比較による自己否定感
→ SNSや同期、先輩の活躍が目に入りやすく、「自分はまだ何も成し遂げていない」と感じ、焦りが生まれやすい。
→ 他人と比較して「自分も早く“何者か”にならなきゃ」とプレッシャーを感じる。
2. キャリアの正解が見えない不安
→ 「このままでいいのか」「今の仕事が本当に自分に合っているのか」など、将来への漠然とした不安が強い。
→ 正解のない時代に、自分だけのキャリア軸を持てず迷いやすい。
3. “肩書き”や“成果”への過剰なこだわり
→  役職や資格、目に見える成果で自分の価値を証明しなければ…という思い込みが強くなりがち。
→ 「エンジニアとして何かを作り上げなきゃ」「有名企業に入らなきゃ」など、肩書き依存に陥ることも。
4. 情報過多による選択肢の迷い
→ インターネットやSNSで多様なキャリアパスや成功事例に触れすぎて、「自分は何を選べばいいのか」分からなくなる。
→ 何も選ばないことへの焦りと、選びきれない自分への自己嫌悪が生まれやすい。
5. “今”を否定してしまう自己評価の低さ
→ 「今の自分はまだ“何者”でもない」と思い込み、日々の小さな成長や経験を認められない。
→ 小さな成功や日常の努力を積み重ねることの価値を見失いがち。
VScode：slim記法のコードが黒字問題を解消

こんにちは、ぱきらと申します。
プログラミングスクール『RUNTEQ』を卒業したばかりの初学者です。
　
Ruby on Rails を学んでいて **slim 記法** に触れることがあったのですが

<font color="red">

- **VScodeを見てみると、コードが全て黒字！！！！😂　読みにくい！！！😂**
    [![Image from Gyazo](https://i.gyazo.com/7f9900ce679424e1e2ad20a9d1350352.png)](https://gyazo.com/7f9900ce679424e1e2ad20a9d1350352)

- **コードに色をつけて読みやすくしたい！！！！👇みたいに！**
    [![Image from Gyazo](https://i.gyazo.com/4bbd1df2e05effa6fae2c3d500de5170.png)](https://gyazo.com/4bbd1df2e05effa6fae2c3d500de5170)

</font>

今回は、**VScodeの拡張機能を使ったことがない人**でも分かりやすく
**コードに色をつけ読みやすくする方法**を書きます。

<font color="green">

- 補足  
    コードの一部分をその分類ごとに異なる色やフォントで表示するエディタの機能は
    **シンタックスハイライト**と呼ばれます
</font>

https://ja.wikipedia.org/wiki/シンタックスハイライト
____
# 解決方法
### 1. **VScodeの一番下、`Go Live`の左隣に`プレーンテキスト`**（`言語モードの選択`）**という選択肢がありますね**
[![Image from Gyazo](https://i.gyazo.com/7b3b67ea2c54535abc3ec8c3a9ec629f.png)](https://gyazo.com/7b3b67ea2c54535abc3ec8c3a9ec629f)

### 2. `プレーンテキスト`（`言語モードの選択`）をクリック、`自動検出`をクリックしてみましょう
[![Image from Gyazo](https://i.gyazo.com/39b85bd8f3c973a002b1b04d1d45893f.png)](https://gyazo.com/39b85bd8f3c973a002b1b04d1d45893f)

### 3. slimに対応した拡張機能などがあれば、この時点でコードに色がつき、言語モードも`slim`と表記されますが
<font color="red">

**されない方は次の４.へ！！** 
</font>

[![Image from Gyazo](https://i.gyazo.com/f5112413380fc63e46510d6821c6d353.png)](https://gyazo.com/f5112413380fc63e46510d6821c6d353)

### 4. **拡張機能をインストールしてみましょう！！**

https://marketplace.visualstudio.com/items?itemName=sianglim.slim

👆のリンクからインストール！
[![Image from Gyazo](https://i.gyazo.com/cd672bb16931a88f4201262b60460346.png)](https://gyazo.com/cd672bb16931a88f4201262b60460346)

または  
**VScodeの一番左の上から５番目`拡張機能`をクリックし、`slim`と検索し、インストール！**
[![Image from Gyazo](https://i.gyazo.com/0b75267cca0696c20e604794d5673ffa.png)](https://gyazo.com/0b75267cca0696c20e604794d5673ffa)

### 5. インストールが完了したら、VScodeの一番下、`Go Live`の左隣の`言語モードの選択`をクリック！
### 6. `自動検出`または`slim`と検索

|`自動検出`をする| `slim`と検索 |
|:---|:---|
|<img src="https://gyazo.com/74a0573f4f6c52a09b1c7035e771b6ee.png" alt="Image from Gyazo" width="500"/>|<img src="https://gyazo.com/1768a4d23ee20020c7b015db8684b74c.png" alt="Image from Gyazo" width="500"/>|

### 7. **クリックするとコードに色味が！！完成！！🥳**
[![Image from Gyazo](https://i.gyazo.com/c8552ab4b49f4e0e33379fdc7355db97.png)](https://gyazo.com/c8552ab4b49f4e0e33379fdc7355db97)
______

# 終わり
今回は、**VScodeの拡張機能を使ったことがない人**でも分かりやすく
**コードに色をつけ読みやすくする方法**を書きました。
　
VScodeの拡張機能は、他にもたっっくさん便利なものがあります！
ググるといくらでもまとめ記事は出てくるので、オススメです💃

https://envader.plus/article/526#VSCode%E3%81%AE%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD%E3%81%A8%E3%81%AF

https://qiita.com/search?q=VScode+拡張機能

読んでいただき、ありがとうございました！
🛴ループ処理まとめ🔁❶ ー for文

## for文

- シンプルな繰り返し処理に適した記法である
- Rubyでは`.each`メソッドの利用が主流
> *「Rubyにもfor文はあります。ですが、ほとんどのRubyプログラマはfor文は使いません。筆者も長年Rubyを使っていますが、for文を書いたことは一度もありません。Rubyの場合は（中略）配列自身に対して「繰り返せ」という命令を送ります。ここで登場するのがeachメソッドです。」*
> **出典**：伊藤淳一『プロを目指す人のためのRuby入門［改訂2版］ 言語仕様からテスト駆動開発・デバッグ技法まで』技術評論社, 2021年12月2日. ISBN: 978-4-297-12437-3

#### 特徴
- 古典的かつ直感的な構文である
- 明示性を重視する反面、Rubyらしさには欠ける

#### 記法
```ruby
for 変数 in コレクション do
  処理内容
end
```
- コレクション：Range、配列、ハッシュ、Enumerableをincludeしたオブジェクトである
- doは省略可能
#### 実例
```ruby
for i in 1..5 do
  puts i
end
# => 1
#    2
#    3
#    4
#    5
```
- `i`
　　- ループ内で利用する変数＝ループ変数
　　- コレクションの要素を順次`i`に代入し格納する
- `コレクション`
　　- 範囲オブジェクト、配列、ハッシュ、Enumerableモジュールなどのオブジェクトのこと
- `do`
　　- 省略可能
---
### eachメソッドとの比較
| 比較項目 | for文               | eachメソッド                 |
| ---- | ------------------ | ------------------------ |
| 記法   | `for 変数 in コレクション` | `コレクション.each do｜ 変数 ｜ … end` |
| スコープ | ループ変数が外部スコープにも残る   | ブロック内ローカル変数として限定される      |    |         |
| 推奨度  | 利用頻度が低く、レガシーな記法である | モダンかつ安全性の高い書き方として広く採用される |    |         |

---
### まとめてみて
- レガシーでオールドでオブソリートなら割り切って覚えなくていいかな・・・
- 必要な時があったら、調べて書ければいいレベルかもしれない。
【クローズドベータ参加者募集】簡単にタスク管理できるAIサービスを作ってみた

## 開発した経緯
私がこのサービスを開発したきっかけは主に以下の2つ

### 1.　開発においてクライアントからの要望をタスクに落とし込むという作業が必ず発生しているが、その箇所をAIでサポートでき、本来仕事の時間を削減して家族や愛する人と暮らす時間を増やせるのではないかと思った。
### 2. 私は長い文章を読むのが苦手。なのでクライアントとミーティングして記録したものの中からタスクを抽出するのもすごい苦手で多大な労力と時間を使い、疲れてしまうのでAIを導入して開発に集中したいと思った。　 


## このサービスの特徴
#### 1. 生成AIを用いて文章からタスクを自動生成できる
ドキュメントなどをコピペしてタスク作成
![スクリーンショット 2025-05-27 14.45.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581660/3f63263f-e23e-4175-9153-a87413d80083.png)

#### 2. シンプルなUI・簡単に操作ができる

![スクリーンショット 2025-03-27 1.25.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581660/c1b38902-b36a-4d13-a382-866549b79b0e.png)

#### 3. Jiraから導入が簡単
JiraAPI経由で今のプロジェクトのデータを一括インポート
![スクリーンショット 2025-05-27 14.38.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581660/b9cba6bc-f055-4250-bc54-05cea85b7f8e.png)


## このサービスに込めた思い
IT企業はブラックになりやすく、また開発に携わっている方々はストレスが溜まりやすくメンタルヘルス的にもよろしくない環境になりやすい。でも、もし今よりさらに時間に余裕ができるようになれば、自分の好きなことをできる時間をとることができるようになれば、愛する人を過ごす時間が増えれば、そのストレスを少しでも減らせるかもしれない。また、開発業務における些細なミスや解釈違いなども起こりにくなり、楽しく開発ができる環境を一つでも多く作っていきたい。


## ここまで読んでくれた方へ
拙い文章で大変申し訳ないのですが、ここまで読んでいただき感謝申し上げます。
もし、クローズドベータの参加にご興味ありましたら、以下のURLよりWaiting listに登録していただければ幸いです。(限定30アカウントです。 超えた場合は申し訳ないのですが参加ができなくなる場合もございます)

https://top.sophina.biz/
Terraform - module 内にある resouce を import するコマンドの例

# 問題

module内のresouceをimportしようとすると 

```
terraform import <resource>名.<defaultなどの名前> <importする対象の指定>
```

エラーが起こる

terraform import 'module.<module名>.<resource>名.<defaultなどの名前>' `importするresourceの対象`

```
Before importing this resource, please create its configuration in the root module. For example:
```

module 配下は import 出来ないのかと思っていたが、実はできるようだ

# 対策

以下のように実行すれば良い

```
terraform import 'module.<module名>.<resource>名.<defaultなどの名前>'  <importする対象の指定>
```
メモ

```csharp
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;

class CsvSplitter
{
    static void Main(string[] args)
    {
        string inputPath = "input.csv";
        string output1 = "output1.csv";
        string output2 = "output2.csv";
        string output3 = "output3.csv";

        // 列番号は0始まり
        int[] file1Cols = { 0, 1, 2, 7, 9 };
        int[] file2Cols = { 3, 6 };
        int[] file3Cols = { 4, 5, 8 };

        // 変換処理の対象列（全体の列番号）
        HashSet<int> transform1Cols = new HashSet<int> { 2, 3 };
        HashSet<int> transform2Cols = new HashSet<int> { 0, 8 };

        using var reader = new StreamReader(inputPath);
        using var writer1 = new StreamWriter(output1);
        using var writer2 = new StreamWriter(output2);
        using var writer3 = new StreamWriter(output3);

        while (!reader.EndOfStream)
        {
            var line = reader.ReadLine();
            if (string.IsNullOrWhiteSpace(line)) continue;

            var columns = line.Split(',');

            string Transform(int index, string value)
            {
                if (transform1Cols.Contains(index))
                    return Transform1(value);
                if (transform2Cols.Contains(index))
                    return Transform2(value);
                return value;
            }

            // 書き込み
            writer1.WriteLine(string.Join(",", file1Cols.Select(i => Transform(i, columns[i]))));
            writer2.WriteLine(string.Join(",", file2Cols.Select(i => Transform(i, columns[i]))));
            writer3.WriteLine(string.Join(",", file3Cols.Select(i => Transform(i, columns[i]))));
        }
    }

    static string Transform1(string value)
    {
        // 変換処理1（例：文字列反転）
        return new string(value.Reverse().ToArray());
    }

    static string Transform2(string value)
    {
        // 変換処理2（例：大文字化）
        return value.ToUpper();
    }
}
```
【ラビットチャレンジ】実装演習レポート⑤深層学習day2-2

<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-mml-chtml.min.js">
</script>
<script type="text/x-mathjax-config">
 MathJax.Hub.Config({
 tex2jax: {
 inlineMath: [['$', '$'] ],
 displayMath: [ ['$$','$$'], ["\\[","\\]"] ]
 }
 });
</script>

# 概要
E資格受験のための認定講座「ラビットチャレンジ」の実装演習レポート、深層学習day2編です。
確認テストと実装演習は省略しています。情報の網羅性は低いですがご理解ください。
外部資料からの内容は※をつけています。
※１：「ゼロから作るDeep Learning」

# Section4 畳み込みニューラルネットワークの概念
* CNN
  * 次元間で繋がりのあるデータを扱える
* LeNet
  * 初めてのCNN
  * サブサンプリング層で要素を間引き、全結合層を経て出力
  * シグモイド関数
* 畳み込み層（Convolutionレイヤ）
  * 空間情報も学習できる層
  * 画像であれば縦横チャンネルの3次元データをそのまま学習して次に伝える
  * 全結合層では形状を無視して１次元データとして処理される
  * フィルターとバイアスの演算を出力
  * 入出力データを特徴マップという
* プーリング層
  * 重み（フィルター）なし
  * チャンネル数変化なし（チャンネルごとに独立して計算される）
  * 入力データの小さなズレに対してロバスト※１
  * MaxPooling
  * AvgPooling
* im2col（image to column）
  * 畳み込み演算の効率化テクニック
  * 行列の積に変換することで計算処理を高速化できる
  * フィルターの適用領域を一列に展開するイメージ※１
  * 重複した値が行列に含まれ、メモリ使用量増加

# Section5 最新のCNN
* AlexNet
  * ブームの火付け役ネットワーク
  * 従来同様に畳み込み層とプーリング層を重ね、全結合層を経由して出力
  * ReLUを用いる※１
  * LRN層で局所的正規化※１
  * 全結合層の出力にDropoutを使用
    * 過学習を抑制
  * Flatten
    * ブロックを分解して数を並べる
  * GlobalMaxPooling
  * GlobalAvgPooling
    * ブロックをスライスして一番大きいもの(平均)を並べる
    * 特徴量を的確に表現できる
    * 効率よくサイズ縮小できる

# フレームワーク演習 正則化/最適化
* 正規化レイヤー
  * データの正規化
  * レイヤー間を流れるデータの分布を平均０、分散１にする
  * Batch正規化
    * 同一チャネルのサンプル個数が正規化の単位
    * ミニバッチのサイズが大きく取れないと効果が薄い
  * Layer正規化
    * 各サンプル（全pixel）が正規化の単位
    * ミニバッチの数に依存しない
  * Instance正規化
    * 各サンプルの各チャネルが正規化の単位
【ラビットチャレンジ】実装演習レポート④深層学習day2

<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-mml-chtml.min.js">
</script>
<script type="text/x-mathjax-config">
 MathJax.Hub.Config({
 tex2jax: {
 inlineMath: [['$', '$'] ],
 displayMath: [ ['$$','$$'], ["\\[","\\]"] ]
 }
 });
</script>

# 概要
E資格受験のための認定講座「ラビットチャレンジ」の実装演習レポート、深層学習day2編です。
確認テストと実装演習は省略しています。情報の網羅性は低いですがご理解ください。
外部資料からの内容は※をつけています。
※１：「ゼロから作るDeep Learning」

# Section1 勾配消失問題
* 勾配消失問題
   * 誤差逆伝播法が進んでいくにつれて勾配が緩やかになり、勾配降下法によるパラメータの変化が小さく、最適値に収束しない現象
   * シグモイド関数は大きな値では出力の変化が微小のため問題を起こす可能性がある
   * ReLU関数で回避できる
* アクティベーション分布※１
  * 重みのスケールによって、シグモイド関数などによる勾配消失は起きやすくなる
  （初期値の標準偏差を大きくすると勾配消失しやすく、小さくすると複数のニューロンがほぼ同じ値を出力することになる）
  * アクティベーションの偏りは「表現力の制限」
* Xavierの初期値
  * 前層からn個のノードの接続がある場合、$1/\sqrt n$の標準偏差を持つガウス分布を初期値として使う※１
  * 重みの要素を$\sqrt n$で割ればよい
  * 活性化関数がS字のとき使うといい※１
* Heの初期値
  * 重みの要素に$\sqrt{\frac{n}{2}}$をかければよい
  * 活性化関数がReLUのとき使う
* バッチ正規化
  * ミニバッチ単位で入力値のデータの偏りを抑制する手法
  * 活性化関数前後に入れる
  * 初期値にそれほど依存しない※１
  * 効果は、極端なデータを調整することで過学習を防ぐことや、学習率を高く設定してトレーニングのスピードが向上したりできること。

# Section2 学習率最適化手法
* Momentum
  $$
  V_t = \mu V_{t-1} - \epsilon\nabla E 
  $$
  $$
  w^{(t+1)} = w^{(t)} + V_t
  $$
  * 大域的最適解となる
  * 谷間についてから最適値までが早い（ジグザグを軽減）
* AdaGrad
  $$
  h_t = h_{t-1} + (\nabla E)^2
  $$
  $$
  w^{(t+1)} = w^{(t)} - \epsilon \frac{1}{\sqrt h_t + h_0}\nabla E
  $$
  * パラメータ要素ごとに学習スケールを調整
  * 大きく動いた要素は学習係数が小さくなる
  * 勾配の緩やかな斜面で最適値に近づける
  * 更新度合いが小さくなって鞍点問題を引き起こす可能性がある
* RMSProp
  $$
  h_t = \alpha h_{t-1}+(1-\alpha)(\nabla E)^2
  $$
  $$
  w^{(t+1)} = w^{(t)} - \epsilon \frac{1}{\sqrt h_t + h_0}\nabla E
  $$
  * 過去の勾配を忘れて新しい勾配の情報を大きく反映して学習率を定義
  * ハイパーパラメータの調整が必要な場合が少ない
* Adam
  * MomentumとRMSPropのメリットを融合
* SGDはシンプルだが探索経路が非効率（ジグザグ）になりやすい※１
* すべての問題で優れた手法は今のところない※１
  * 多くの研究ではSGDが使われる
  * 最近ではAdamが好まれている
🛴ループ処理まとめ🔁

# Ruby の反復処理まとめ ― 繰り返し処理を使いこなしたい

プログラミングでよく使う「同じ処理をくり返す」手法――Ruby では多彩な文法やメソッドが用意されています。  
「配列の全要素を一気に操作したい」「決まった回数だけ繰り返したい」「ある条件を満たすまで続けたい」など、目的に応じて使い分けましょう。

---

## 反復処理とは
- **同じ処理を繰り返し実行する**ための手段  
- 配列要素の一括操作、固定回数の繰り返し、条件達成までの継続処理などに使う  
- **利点**：コードがスッキリまとまる・同じ処理を一元管理できる  
- **注意点**：ループ内でカウンタ更新や条件変更を忘れると無限ループに…

---

## 主な反復手法一覧
1. `for` 文  
2. `each` メソッド  
3. `times` メソッド  
4. `upto` / `downto` / `step`  
5. `while` / `until`  
6. `Enumerable` モジュールの各種メソッド（`map`, `select`, `find` など）  

---
## 1. `for` 文
- シンプルで直感的な繰り返し構文  
- でも Ruby ではほとんど `each` が主流  
- 書き方  
```ruby
  for elem in [1, 2, 3]
    puts elem
  end
```
- ブロック外でも変数が生きてしまうので、予期せぬ挙動に注意
---
## 2. `.each` メソッド
- 配列・ハッシュ・範囲オブジェクトなど、Enumerableを順に処理
- ブロック引数はローカル変数扱い（スコープ汚染しない）
　（スコープ：変数や定数の有効範囲）
- 戻り値は元のコレクション自身
```ruby
arr = [1, 2, 3]
arr.each do |n|
  puts n * 2
end
# => 2, 4, 6
p arr
# => [1, 2, 3]
```
---
## 3. `.times` メソッド
- 整数限定で「0 から n-1 まで」を繰り返す  
- 返り値はレシーバの整数  
- ブロック省略時は `Enumerator` を返す  
```ruby
3.times do |i|
  puts i
end
# => 0, 1, 2
```
---
## 4. `.upto` メソッド
- 数値オブジェクトから指定した上限値まで、**昇順**で繰り返すメソッド
```ruby
m.upto(n) do |i|
# mからnまで、**昇順**でブロックを回す
```
---
## 5. `.downto` メソッド
- `.upto` メソッドに対して、降順で繰り返すメソッド
```ruby
m.downto(n) do |i|
```
---
## 6. `.step` メソッド
- Range版、Numeric版を指定し、開始値から増分ずつ足していき、値が上限値を超えない範囲でブロックを繰り返すメソッド
- Range版：`(開始値..上限値).step(増分) do |n|〜end`
```ruby
(1..9).step(2) do |n|
  puts n
end

# 出力結果
1, 3, 5, 7, 9
```
- Numeric版：`開始値.step(上限値, 増分) do |n|〜end`
```ruby
1.step(9, 2) do |n|
  puts n
end

# 出力結果
1, 3, 5, 7, 9
```
---
## 7. while文
- 条件式が`true`の間、繰り返し処理を実行する制御構文
- ①条件式を評価→②`true`なら処理内容実行→③処理終了後、条件式を再評価→④`false`になった時点でループ終了
##### 基本的な例
```ruby
i = 1
while i <= 5 do
  puts i
  i += 1
end

# 実行結果
1
2
3
4
5
```
　　- `i += 1`の役割
　　　　- `i += 1`　＝　`i = i+1`
　　　　- `i = 1`の場合
　　　　　　- `i`は常に１のまま → 条件がずっと`true` → 無限ループ
　　　　- `i += 1`の意味
　　　　　　- `puts i`を実行後、次の繰り返し処理のために`i = i+1`が必要
##### `break`で即時終了
```ruby
i = 1
while i <= 5
  break if i == 3    # i が 3 になったらループを抜ける
  puts i
  i += 1
end

# 実行結果
1　# 👈puts iで表示 → 次の2を表示するためにi+=1が必要
2
```
##### `next`で次の処理へスキップ
```ruby
i = 0
while i < 5
  i += 1
  next if i == 3     # i が 3 のときだけ出力をスキップ
  puts i
end

# 実行結果
1
2
4
5
```
##### `redo`で同じ処理を再実行
```ruby
i = 0
while i < 2
  i += 1
  puts i
  redo if i == 1
end

# 実行結果
1
2
```
---
## 7. until文
- 条件式が`false`の間、繰り返し処理を実行する制御構文＝**while文の逆**
---
## 8. Enumerableモジュールのメソッド
- コレクションオブジェクトを繰り返し処理可能にする共通機能を提供するモジュール
- `.each` メソッドを実装したクラスに、`includeすることで利用可能
【ラビットチャレンジ】実装演習レポート③深層学習day1

<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-mml-chtml.min.js">
</script>
<script type="text/x-mathjax-config">
 MathJax.Hub.Config({
 tex2jax: {
 inlineMath: [['$', '$'] ],
 displayMath: [ ['$$','$$'], ["\\[","\\]"] ]
 }
 });
</script>

# 概要
E資格受験のための認定講座「ラビットチャレンジ」の実装演習レポート、深層学習day1編です。
確認テストと実装演習は省略しています。情報の網羅性は低いですがご理解ください。
外部資料からの内容は※をつけています。
※１：「ゼロから作るDeep Learning」

# Section1 入力層〜中間層
* 入力層には様々な情報を重みを用いて入力する
* 一次関数でいうと、重みは傾き、バイアスは切片の役割
  （傾きと切片が決まると関数はひとつに定まる）
* 中間層で情報を変換し、次の層へ伝播
* 何層にも重なるのがニューラルネットワーク
* パーセプトロン※１
  * 信号の入出力をするアルゴリズムであり、ニューラルネットワークの考え方のもとといえる
  * バイアスと重みを導入
  * 多層化することで非線形領域まで表現でき、理論上コンピュータを実現できる
  
# Section2 活性化関数
* 次の層への出力の大きさを決める非線形関数
* 入力の伝播の強弱を調節
* ReLU関数
* ステップ関数
  * 1 or 0 の階段関数
  * 線形分離可能なもののみ学習可
* シグモイド（ロジスティック）関数
  * 0~1の信号のなめらかな強弱
  * 勾配消失問題
* ReLU関数
  * 0 or $x$
  * 勾配消失問題の回避
  * スパース化
  * いま最も使われている
  * numpyではmaximum(0,x)で実装可能※１
* 線形関数を用いてはならない※１
  * 層を深くする意味がなくなる
  * 例：$h(x)=cx$として$y=h(h(h(x)))$と３層にした場合は$y=c^3x$と隠れ層なしで表現できてしまう

# Section3 出力層
* 誤差関数
  * モデルが予測した出力と訓練データとの誤差を数値化
  * 平均二乗誤差
  * クロスエントロピー誤差
* 活性化関数
  * 中間層と利用する関数が違う
  * 信号の大きさ（比率）はそのまま変換
  * 分類の場合、出力層の出力は0~1で総和が1※１
      * 出力を確率として解釈できる
  * 恒等関数
  * シグモイド関数
  * ソフトマックス関数
  $$
      y = \frac{e^{a_k}}{\sum_{i=1}^{k}e^{a_i}}
       $$
    * 出力の各ニューロンは全入力信号からの影響を受ける※１
    * 指数関数によるオーバーフロー対策で$exp(a-c)$とできる
  （c:入力信号の最大値）※１
    * 出力が一番大きいニューロンに対応するクラスを認識結果とするため出力層にて省略可能※１

||回帰|二値分類|多クラス分類|
|-|-|-|-|
|活性化関数|恒等写像|シグモイド関数|ソフトマックス関数|
|誤差関数|二乗誤差|交差エントロピー|交差エントロピー|

# Section4 勾配降下法
* 勾配降下法
  * 学習率（ε）が大きすぎると発散
  * 小すぎると収束に時間がかかる
  $$
  {w_{t+1}} = {w_t} - ε\frac{\partial E}{\partial {w}}
  $$
* 確率的勾配降下法（SGD）
  * ランダムに抽出したサンプルの誤差
  * 計算コスト軽減
  * 局所極小解に収束するリスク軽減
  * オンライン学習が可能
* ミニバッチ勾配降下法
  * ランダムに分割したデータの集合（ミニバッチ）に属するサンプルの平均誤差
  * SGDのメリットを保って計算資源を有効活用できる
      * CPUのスレッド並列化
      * GPUのSIMD並列化
* 数値微分
  * 順伝播の計算を繰り返す必要があり負荷が大きい
* 鞍点※１
  * 勾配が０の、局所的な極小値
* プラトー※１
  * 学習が進まない停滞期
  * 複雑な関数では、勾配が指す方向は最小でない場合がほとんど

# Section5 誤差逆伝播法
* 各パラメータの微分値を解析的に計算する手法
* 出力層側から順に微分して前の層へ伝播
* 最終的な誤差から逆算することで不要な再帰的計算を避けて微分を算出できる
SES企業の監視オペレーターからクラウド設計構築まで、1年で成り上がるために実施したこと

SES企業の監視オペレーターという、エンジニアの中でもキャリアの最初の登竜門的なポジションから、1年でAWSの設計・構築まで任せてもらえるようになるまでにやったことをまとめます。

当時の自分のスペックは以下の通り：

理系大学卒だが教員志望だったため、インフラもクラウドも無知

技術経験はほぼなし

監視オペレーターとしての実務経験からスタート

そんな自分でも、1年本気で取り組んだことで、以下のようなことができるようになりました。

・AWS上でサイトを構築し、設計の実務経験を得る

・Pythonによる自動化スクリプトの作成

・SAPレベルのクラウド知識の習得

・インフラ知識としてLPIC/CCNAも習得

・技術だけでなく、営業交渉や現場での信頼獲得も重視

1. クラウドの知識をつけた（AWS資格取得）

AWSについては、書籍学習＋模擬試験の繰り返しで合格しました。
取得した資格：

・[(模擬問題付き)徹底攻略 AWS認定 クラウドプラクティショナー教科書 第2版［CLF-C02］対応)](https://amzn.to/3HbFpHm)

・[(模擬問題付き)徹底攻略 AWS認定 ソリューションアーキテクト − アソシエイト教科書 第3版［SAA-C03］対応)](https://amzn.to/4jm1DDU)

・[AWS認定資格試験テキスト＆問題集　AWS認定ソリューションアーキテクト - プロフェッショナル　改訂第2版 (ＡＷＳ認定資格試験テキスト)](https://amzn.to/4dvQrTI)

試験は受験料が高いですが、未経験スタートの自分には自信を付ける意味でもかなり有用でした。もちろん資格がすべてではないですが、「初学者が信頼を得る手段」としては今でもアリだと思っています。

２. サーバーやネットワークの基礎知識を習得

クラウドといえども、ベースにあるのはサーバーやネットワークの技術です。特にLinuxやTCP/IPの知識は、トラブルシュート時に非常に役立ちます。

学習に使った書籍：

・[徹底攻略 LPIC レベル1教科書＆問題集［Version 5.0］対応](https://amzn.to/4joN6au)

・[(模擬問題、スマホ問題集付き)徹底攻略Cisco CCNA問題集[200-301 CCNA]対応](https://amzn.to/4kBwWvu)

これらは資格を取ることが目的というより、「インフラの全体像を把握する」ための材料として活用しました。

３. 実際にAWSを触って個人開発してみた

知識だけではすぐに忘れてしまうので、とにかく手を動かして構築してみることを重視しました。

実際にやったこと：

・EC2・S3・RDS・Route53・IAM など主要なサービスを使ってWebサイト構築

・CloudFormationによるリソースの自動化にも軽くトライ

学習のついでに作った成果物をQiitaにアウトプットしたところ、ちょっとずつ見てもらえるようになったのも嬉しかったです。

４. Pythonを学習して自動化の土台を作る

今後はIaC（Infrastructure as Code）や自動化の方向にも進みたかったので、Pythonにチャレンジ。

学習に使ったのは以下：

・[シリコンバレー一流プログラマーが教える Pythonプロフェッショナル大全](https://amzn.to/3SpFGsB)

最初はスクレイピングやログ整理の簡単なスクリプトから始めて、徐々にAWS SDK（boto3）を使ってEC2操作などにも挑戦していきました。

５. 営業にガチで交渉した

どんなにスキルを身につけても、チャンスをもらえなければ意味がない。

そこで営業には定期的に以下を伝えていました：

・資格・スキルの進捗状況

・将来やりたいこと（クラウド設計に関わりたい）

・「今ならどんな現場でも吸収する覚悟がある」と熱意を伝える

営業と信頼関係を作っておくと、空きが出たときに声をかけてもらえる確率が高まります。

６. 現場で評価を得るために「技術以外の力」も大事にした

最後に意識したのは「現場でどう評価されるか」。特に、以下を実施：

・積極的なコミュニケーション（報連相、雑談含めて）

・作業手順のドキュメント化

・業務改善の提案

最初の頃は「教員志望だったくせにエンジニアなんて…」と思ってましたが、教育と同じように相手目線での説明や理解促進は大きな武器になると気づいてから、むしろ強みにできました。

最後に

クラウドエンジニアとして1年でステップアップするには、技術だけでなく、行動力と交渉力、そして信頼の積み上げが必要です。

スキルや資格は目的ではなく「武器」なので、どのタイミングでどう使うかがポイントになります。

これからチャレンジする方の参考になれば嬉しいです。
Linux実務で `/dev/sda` を触ってはいけない理由と、安全なディスク操作の基本

## はじめに

Linuxでディスク操作の学習をしていると、よく目にする `/dev/sda`。  
この名前、よく見かけるけど実際に何のためのものかわからなかったのでまとめてみました。

結論から言うと、**実務で `/dev/sda` を操作するのはかなり危険です。**  
この記事では、その理由と、ディスク操作を安全に行うための基本的な考え方をまとめます。



## `/dev/sda` とは何か？

Linuxでは、ストレージデバイスは `/dev/sdX`（例：`/dev/sda`, `/dev/sdb`）のように名前が付けられます。  
その中でも `/dev/sda` は、**最初に認識されたディスク**です。

多くのケースでは、この `/dev/sda` に **Linuxの本体（OS）や設定ファイル、ブート情報などが格納されています。**

### `/dev/sda` に含まれがちなもの

- `/`（ルートファイルシステム）
- `/boot`（カーネルやGRUB）
- `/etc`（設定ファイル）
- `/usr`（プログラムやライブラリ）
- `/var`（ログやキャッシュ）
- `/home`（ユーザーデータ） ※分離されていることもあり

つまり、**Linuxが動作するための大事な「心臓部」が詰まっている場所**です。



## もし `/dev/sda` をうっかりフォーマットすると…

たとえば、以下のようなコマンドを実行してしまうとどうなるでしょうか？

```bash
sudo mkfs.ext4 /dev/sda
```

これは /dev/sda に 新しいファイルシステムを上書きする（＝初期化する） コマンドです。
この操作をしてしまうと、以下のような重大な影響があります。

- ブート領域やカーネル、OS本体がすべて消える

- システムが起動できなくなる

- 大事なデータもすべて失われる

➡ **つまり、OSが「文鎮化」します。**
※「OSの文鎮化（ぶんちんか）」とは、OSが起動不能になり、使い物にならなくなった状態



## /dev/sda は毎回同じディスクなのか？
実は /dev/sda という名前は、**起動時にカーネルが認識した順番で決まるため、接続状況によって変わることがあります。**

たとえば…

- ある日は `/dev/sda` がOSディスク、`/dev/sdb` がデータディスク

- 別の日は逆に `/dev/sdb` がOSディスクになっている

というように、デバイス名は環境やタイミングによって変動する可能性があります。

### 名前で判断するのは危険 ###
「`/dev/sdb` だからデータディスクだろう」と思ってフォーマットしたら、実はそれがシステムディスクだった…
という事故も、実務では本当に起こるらしいです。

### 安全なディスク管理の基本 ###
以下の方法を組み合わせることで、ディスク操作の安全性が大幅に向上します。

#### `lsblk` で構成を視覚的に確認
```bash
lsblk
```
どのディスクにどんなパーティションがあり、どこにマウントされているかが一覧で表示されます。

#### `blkid` でUUIDを確認
```bash
sudo blkid
```
各パーティションのUUID（ユニークな識別子）を確認できます。
UUIDを使えば、デバイス名が変わっても安全に識別できます。

#### `/etc/fstab` はUUIDで書くのが鉄則
```fstab
UUID=abcd-1234-5678-efgh /mnt/data ext4 defaults 0 2
```
デバイス名ではなくUUIDでマウント設定を書くことで、起動順の変化によるトラブルを防げます。

#### ラベルを付けるのも有効
```bash
sudo e2label /dev/sdb1 DATA_DISK
```
lsblk -f でラベルを確認できるようになり、視認性が向上します。

## 実務での判断基準：「触っていいディスク」「触っちゃダメなディスク」
| デバイス名        | 内容                                | 操作の可否        |
|------------------|-------------------------------------|-------------------|
| /dev/sda         | OSが入っていることが多い            | × 触らない        |
| /dev/sdb, /dev/sdc | 追加のデータディスクなど            | ○ 事前確認の上で可 |
| /dev/nvme0n1     | NVMe SSD（OS or データ用途）        | △ 要調査          |
| /dev/xvdf（AWS） | EBS追加ボリュームなど               | ○ よく使う対象     |


# 安全なディスク操作のチェックリスト

1. `lsblk` コマンドでディスク構成を確認する  

2. `df -h` コマンドで使用中のマウントポイントを確認する  

3. `mount` や `blkid` コマンドで UUID・ファイルシステムの種類を確認する  

4. 対象が「**追加ディスク**」であることを明確に確認する  

5. `/etc/fstab` では UUID またはラベルで記述する  
<br>

## まとめ

- `/dev/sda` は多くのケースで「OSの本体」が入っている**超重要なディスク**
- 名前は**起動順で変わることがあり**、名前だけで判断するのは危険
- ディスク操作時は **UUIDやラベルで正確に識別**し、安全な手順で作業する
- 実務では、**システムディスクには手を出さないのが原則**



## おわりに

ディスク操作は、インフラエンジニアにとってとても**強力かつ危険な操作**のひとつです。  
ちょっとした確認不足が、**システム停止やデータ消失**といった大きなトラブルにつながることもあります。

だからこそ、  
**「触っていいもの」と「触ってはいけないもの」** をしっかり見分ける目を養うことが大切だと感じました。

この記事が、  
「**安全なディスク管理の考え方**」を身につける一助になれば幸いです。
【ChatGPT活用術】「前にやったあの処理…また説明？」をなくす方法

# ChatGPTと長いやり取りするのが面倒…。すぐ忘れるんだよねぇ…。

## はじめに

ChatGPTを活用して複雑なドキュメント作成や仕様書作成を進めている方にとって、  
次のような課題を感じたことはないでしょうか？

- 前回のやり取りの意図を再現できない  
- データや条件を少し変えただけで、また一から説明する必要がある  

そして思う…
> 「あのとき出したロジック、AIにまた説明するの無理ゲー…」

  
そこで、ChatGPTを **「長期的なテーマを取り組む相手」** とするための工夫として、**対話の内容をPythonスクリプトという「実行可能なログ」として残す**方法を取り入れました。

ヒントになったのは以下の記事です。

@dvcampanula さま記事

https://qiita.com/dvcampanula/items/b09679277e13a13b1531

---

## どんな課題をAIと取り組んだのか？

私が取り組んでいたのは、**複数のExcel定義書から特定チェック定義のみを抽出し、マッピング表を生成する処理**です。

具体的には以下のような要求でした：

- 定義書は毎回異なり、2列/3列/不定形の構造が混在する  
- 読み込むべきテーブルは「3列連続で構成され、左列がフェーズ名ではじまる」構造に限定したい  
- 商談／発注といったドキュメント種別ごとにシートを分けて出力したい  
- 出力内容には、出典ファイルやチェック種別の識別も残したい  

---

## ChatGPTとの対話がどうスクリプト化されたか

この一連の要件を、何度もChatGPTとやり取りしながら以下のように進めました：

1. **初期仕様を整理**  
　Excel定義書の実物を読み込ませ、AI側に構造とパターンを把握させました。

2. **構造認識の調整**  
　「列名による判定ではなく、列構造と中身で判定するべき」という指摘をAIに行い、ロジックを修正させました。

 ```
  ↑ここまでがプロンプトで指示してロジック構築と成果物確認をするフェーズ（ChatGPT内）
```


```
 ↓ここからがプロンプトを長期的に保管するためのスクリプト化作業
```

3. **スクリプト化・修正**  
　せっかくなので、再利用できるように多少のUIを付けたり(ファイル入出力・選択チェックボックス)しながらスクリプトの修正に取り組んでいきます。

4. **出力結果の妥当性確認**  
　「選んでいないシートが含まれている」「タブ名が適切に反映されていない」などの実行結果の差異を指摘し、原因を突き止めて修正。

5. **生成物の完成**  
　選択チェック種別に応じて「商談用」「発注用」に分けてシート出力されるExcelファイルが生成できるようになりました。

---

## 再現性の担保＝「実行可能な対話ログ」

このやり取りで改めて感じたのは、**AIとの会話はすぐに失われるが、スクリプトは残る**という事実です。

一度構築されたPythonスクリプトを「最終成果物」ではなく「ロジック込みのログ」として扱えば、

- データ構造が変わったとき  
- 追加要件が発生したとき  
- 別の担当者が引き継ぐとき  

にも、**ChatGPTにスクリプトを再入力するだけで会話の続きを始められます**。  
つまり、**「再現性ある長期対話の土台」として、コードが対話の橋渡しになる**というわけです。

---

## まとめ：AIと長期対話するためにコードを残すという発想

ChatGPTのメモリはまだまだ貧弱であることと、メモリ内の文言を全く同じ解釈する保証が保たれていません。

だからこそ、**思考と構造をコード化しておく**ことが、AI活用における持続性を担保します。

- プロンプトで設計した処理をスクリプトにする  
- 実行して結果を検証する  
- ズレやバグをフィードバックして修正する  
- スクリプトを「会話の記憶」として保存しておく  

この流れを繰り返すことで、ChatGPTとのやり取りは「その場限り」ではなく、  
**再現可能な長期プロジェクト**として運用することが可能になります。

---

## おわりに

もし皆さんが「ChatGPTは便利だけど、すごく苦労したやり取りを残しておきたい」と感じているなら、**コード化によって意図と構造を残す**という視点を取り入れてみてください。
署名付きURLで安全にファイルを共有する仕組み

## はじめに

画像やファイルを一部のユーザーだけに共有したい場合、単純にURLを共有するだけではセキュリティ上のリスクがある。たとえば、URLの一部を改ざんすることで他人の画像にアクセスできてしまう可能性がある。

この記事では、署名付きURLを使って安全にファイルを共有する仕組みと、その原理について学んだことを整理する。

## 問題となるシナリオ

以下のようなURLでファイル共有を行うとする。

```
/share/files/jpg?user=4335&file=dog
```

このURLを知っている人は誰でもファイルにアクセスできるが、問題はURLの一部、たとえば `user=4335` を他の値に書き換えることで、他のユーザーのファイルにアクセスできてしまう点。

## 署名付きURLを使う

この問題を解決するために、改ざんを検出できる「署名」を使う。

署名とは、共有する情報（たとえば `user`, `file`, `expires` など）をもとに、秘密鍵を使って生成したハッシュ値のこと。署名をURLに追加することで、そのURLが改ざんされていないかどうかを検証できるようになる。

### 署名付きURLの構成例

```
/share/files/jpg?user=4335&file=dog&expires=1700000000&signature=abc123...
```


## URLを生成する処理の例

```php
public function getSignedURL(array $queryParameters): string
{
    $url = $this->getBaseURL();
    $queryString = http_build_query($queryParameters);
    $signature = hash_hmac('sha256', $url . '?' . $queryString, $this->getSecretKey());

    return sprintf("%s?%s&signature=%s", $url, $queryString, $signature);
}
```

## URLを検証する処理の例

```php
public function isSignedURLValid(string $url): bool
{
    $parsedUrl = parse_url($url);
    if (!isset($parsedUrl['query'])) return false;

    parse_str($parsedUrl['query'], $queryParams);
    if (!isset($queryParams['signature'])) return false;

    $signature = $queryParams['signature'];
    unset($queryParams['signature']);

    $queryString = http_build_query($queryParams);
    $urlWithoutSignature = $parsedUrl['scheme'] . '://' . $parsedUrl['host'] . $parsedUrl['path'] . '?' . $queryString;

    $expectedSignature = hash_hmac('sha256', $urlWithoutSignature, $this->getSecretKey());

    return hash_equals($expectedSignature, $signature);
}
```

## なぜ署名付きURLが有効なのか？

* 改ざんされた場合にアクセスを拒否できる
* 有効期限を設けて一時的な共有リンクにできる
* サーバーだけが秘密鍵を持っているため、第三者は正しい署名を生成できない

## まとめ

署名付きURLの仕組みを理解することができた。
これを応用してメールアドレス認証も学んでいく。
CloudShellでLambdaで必要なモジュールをZip化する

# 背景
構築の一環でLambdaへZip化したファイルをアップロードする必要があった。

# 前提
Python 3.13

# 手順
①AWSへログイン
②「CloudShell」で検索する
③以下を実行する
※一文ずつ流してください！
```
# 必要パッケージのインストール
sudo yum install -y gcc zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel xz xz-devel libffi-devel wget make

# pyenv インストール
curl https://pyenv.run | bash

# pyenv 環境変数設定
echo -e '\n# pyenv' >> ~/.bashrc
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init --path)"' >> ~/.bashrc
echo 'eval "$(pyenv init -)"' >> ~/.bashrc
source ~/.bashrc

# Python 3.13 インストール（時間がかかります）
pyenv install 3.13.0
pyenv global 3.13.0

# 3.13になればOK
python3 --version
```
④作業ディレクトリを配置する
```
mkdir ~/lambda_build
cd ~/lambda_build
```
⑤lambda_function.pyをアップロードする
右上の「アクション」から「アップロードする」を押下。
lambda_function.pyを追加。

⑥パッケージをインストール
```
mkdir -p package
pip install --upgrade pip
#インポートしたいモジュールを追加
pip install --target ./package aaaa bbbb
```
⑦Zip化する
```
cp lambda_function.py ./package/
cd package
zip -r9 ../lambda-deploy.zip .
cd ..
```
⑧Zipファイルをダウンロード
現在のフォルダの位置を確認します。
```
pwd
```
右上の「アクション」から「ダウンロード」を押下。
下記ができているはずのため、パスを連携してダウンロードします。
```
/home/cloudshell-user/lambda_build/lambda-deploy.zip
```