OmniAICreator/Qiita-1.07M huggingface dataset:
初学者がデータ基盤の組み合わせについて考えてみた

# データ分析基盤
初学者レベルの段階で、どんなデータ分析基盤の組み合わせがあるのか、利点、欠点をまとめてみました。
というか、いろんなものがありすぎで目が点になりますね。初心者がしらべたものなので、間違い等あるかもしれません。個人学習メモです。

## 主な組み合わせとその特徴
Data Engineering Studyを最近視聴しているのでTROCCOにかたよっています。。。

### Google Cloud Storage + TROCCO + BigQuery + dbt + BI
- **利点**: BigQueryのサーバーレスアーキテクチャは、リソースプロビジョニングを自動で処理し、計算のスケーラビリティを設定する必要がなく、使用料によって料金がかかるので始めやすい。また、機械学習機能がしやすい。
- **欠点**: ローカル環境や他のクラウドプラットフォームでの利用が制限され、SQL知識が必要です。

### AWS S3 + TROCCO(AWS Glue) + BigQuery + dbt + BI
- **利点**: AWS S3とAWS Glueの統合により、ETLプロセスを簡単に自動化できます。
- **欠点**: 異なるクラウドプロバイダー間でのデータ転送が必要になり、追加の設定やコストが発生する。

### AWS S3 + TROCCO(AWS Glue) + Redshift + dbt + BI
- **利点**: Redshiftは列指向データベースを使用し、データ圧縮によりクエリパフォーマンスがよい。
- **欠点**: クラスタの設定や拡張に関する知識が必要であり、運用負荷が増加する。

### AWS S3 + TROCCO(AWS Glue) + Snowflake + dbt + BI
- **利点**: Snowflakeはマルチクラウド環境でのデータウェアハウス構築に適しており、柔軟なスケーリングができる。
- **欠点**: 複雑なデータ変換や分析のニーズに対応するために、ユーザーが直接クエリ処理の挙動を細かく制御することが困難になることがある。

## 初学者が疑問に思う点

### Q1: データレイクもDHW製品上に構築するのがいいか？
- **A1**: 構造化データはDWH製品上で管理することが推奨されますが、非構造化データ（画像・動画など）はCloud Storageなどのオブジェクトストレージに置くのが一般的です。

### Q2: データ分析のためにはどのETL/ELTツールが最適ですか？
- **A2**: TROCCOなのど、専用ELTツールを使用する場合の利点には、特化した機能やシンプルな統合プロセスが含まれますが、コストがかかることや特定のプラットフォームに依存する可能性が欠点です。一方、クラウドサービスを使ったELTでは、広範なクラウドエコシステムへのアクセスやスケーラビリティが利点となりますが、カスタマイズの柔軟性が制限される場合があります。選択は、プロジェクトのニーズ、コスト、使いやすさなどを総合的に考慮する必要があり。dbtはデータ変換のところですが、デファクトスタンダードになりつつあるとどこかで見ました。

（dbtについて）
dbt（Data Build Tool）は、SQLを使用してデータを変換し、データエンジニアリングのタスクをデータアナリストが容易に実行できるようにするツールで、SQL文を使ってデータウェアハウス内でデータの変換を行い、データ品質の自動テストを実施できること、また、バージョン管理などが利点。

### Q3: いろんな組み合わせがあり、初期と構成と将来的な構成って変更できる？
（最初はクイックスタートできるもの、ユーザーフレンドリーなものがいいけど、データ量が増えたり、接続ソースや、ユーザーが増えたりするので）
多くのデータ分析プラットフォームは、初期構成から将来的なニーズに合わせて構成を変更する柔軟性を提供しています。最初は使いやすく、迅速に開始できるツールを選択し、プロジェクトが成長してデータ量が増加したり、接続するデータソースやユーザーが増えたりした場合には、よりスケーラブルで高度な機能を持つサービスに移行することが可能です。この過程で、データパイプラインや分析の基盤を再構築することなく、効率的に拡張やカスタマイズが行えます。こんなことが書かれていたが、ツール自体をかえるのはそれなりに大変そう？

## まとめ

この記事では、データ分析基盤構築に関する主な組み合わせとそれぞれのツールの利点および欠点をまとめてみました。また、初学者（自分）が持った疑問に対する答えを書いてみました。

データ分析プロジェクトを成功させるためには、プロジェクトのニーズに最適なツールとサービスを選択し、それらを適切に組み合わせて使用することが重要になりそう。BigQuery、Redshift、Snowflakeなどのデータウェアハウスサービスの選択は、特定の要件や目標に基づいて検討する必要があります。個人的には最初はクイックスタートでトライして、そこから広げるのが良いと考えていますが途中で構成をガラッとかえるのはむつかしいかもしれません。
IPアドレスのクラスについて(恥。

インフラエンジニアに9年目に突入して、IPアドレスのクラスについて気づきがありました。
これまで、ネットワークもサーバも実務経験を積んできました。入社研修でIPアドレス計算等の基本的なITインフラについて学んでいてもしかするとその時に教えられていたのかもしれません。。

IPアドレスにはクラスAクラスEまであってクラスAからプレフィックスは/8,/16,/24であることは周知の事実で、各クラスのネットワーク範囲は下記とおりになっています。

| クラス | アドレス範囲 |
| :--- | :---: |
| クラスA | 0.0.0.0 ～ 127.255.255.255 |
| クラスB | 128.0.0.0 ～ 191.255.255.255 |
| クラスC | 192.0.0.0 ～ 223.255.255.255 |
| クラスD | 224.0.0.0 ～ 239.255.255.255 |
| クラスE | 240.0.0.0 ～ 255.255.255.255 |

Yahoo知恵袋に「なんでクラスAで127.255.255.255になるんですか？」「先頭の127ってなんですか？」という質問があった。私の中では、IPアドレスはこういうものということを偉い人が定義したのだからそいういうものだろうという考えが即座に浮かびました。回答欄にも案の定、私と同じ考えで「1+1=2がなぜ2になるのかをきいているようなもの」という回答ばかりでした。
私自身、なぜクラスAの先頭が127なのか疑問にすら思いませんでした。別に下記のようなクラスでも良いわけです。

| クラス | アドレス範囲 |
| :--- | :---: |
| クラスA | 0.0.0.0 ～ 255.255.255.0 |
| クラスB | 255.0.0.0 ～ 255.255.0.0 |
| クラスC | 255.255.0.0 ～ 255.0.0.0 |

※あれ、、なんかサブネットマスクみたいになってきた。。多分いろいろ問題ある

結論、なぜクラスAの先頭が127なのかは分からないけど、各クラスをみるとIPアドレスが左から1bitずつ増えていて規則性があったんだと気づきましたとさ
※規則性だけでなく数字の特性等も考慮された結果、定義されていはず

参考
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q11296281016?__ysp=SVDjgqLjg4njg6zjgrk%3D
レビュー中、レビューOKの時に自動的にラベルを付与するGithubアクション

最近作成したレビュー中、レビューOKの時に自動的にラベルを付与するGithubアクション。

## レビューがリクエストされた時にラベルを付与する

```yml
name: Add Label on Reviewers Assigned

on:
  pull_request:
    types: [review_requested]

jobs:
  add-label:
    runs-on: ubuntu-latest
    steps:
      - name: Add a label
        uses: actions/github-script@v5
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const pr = context.payload.pull_request;
            const labelToAdd = "レビュー中";
            await github.rest.issues.addLabels({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: pr.number,
              labels: [labelToAdd]
            });

```

## レビューがApproveされた時にラベルを付与し、任意のラベルを削除する

```yml
name: Approval Workflow

on:
  pull_request_review:
    types: [submitted]
permissions:
  contents: read
  pull-requests: write
jobs:
  build:
    if: github.event.review.state == 'approved'
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v2

      - name: Add LGTM label after approval
        uses: actions-ecosystem/action-add-labels@v1.1.0
        if: "!contains(github.event.pull_request.labels.*.name, 'LGTM')"
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          labels: 'LGTM'
      - name: Remove "レビュー中" label after approval
        uses: actions-ecosystem/action-remove-labels@v1
        if: "contains(github.event.pull_request.labels.*.name, 'レビュー中')"
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          labels: 'レビュー中'

```
世界一流エンジニアの思考法のレビュー‼️実体験とトップエンジニア(CTO)から学んだことをベースに解説

# はじめに
話題になっていた本のレビュー動画です。
じぶんはまだ経験の浅いジュニアエンジニアなので、一流エンジニアから何か吸収しようと思い、レビューを書いてみることにしました。駆け出しエンジニアの方は、ぜひ読んでみてください。


# どんな本
結論この本は***仕事の生産性を上げるための本***です。
マイクロソフトという世界トップ企業は仕事の生産性がとにかく高いです。
生産性が高いから世界トップエンジニアは、脳の構造が元々凄いのではなく、***思考の習慣が違う***みたいです。

ここにスポットを当てて説明されています。

# トップエンジニアの思考法
この本で書かれているのは、東大出身のCTOなどのトップエンジニアからもらったアドバイスとも重なります。
ぜひ1つでも吸収してください。￥

# いきなり試行錯誤して手を動かすのではなく、まずは仮説を立てる
よく駆け出しエンジニアはエラーが出た時に、いきなり手を動かしてしまいます。
しかし、***一流エンジニアはいきなり手を動かしません***。
ログを読んで、まずは***何が起きているかを仮説を立てることから始めます***。

```
情報を集める→→→→→いくつかの仮説を立てる→→→→→→その仮説を検証する行動を取る
```
の順番でエラーを解決していきます。もし***仮説が間違っていたら再度仮説を立てます***。

トップエンジニアは、いきなり手を動かすのではなく、社内のシステムなどの***理解に時間をかける***みたいです。

## 自分の体験(いきなり試行錯誤して手を動かすのではなく、まずは仮説を立てる)
自分は、エラーが出るとあれもこれもと色々手を動かしてエラーを解決しようとしていました。そんな時CTOの方から、以下のアドバイスをもらいました。

1.***まずは仮説を立てること***
2.***仮説を立てたならなぜその仮説を立てたのか根拠を持つこと***
3.***がむしゃらにコードは書かないこと***

これをいつも言われていました。ついエラーが出ると手を動かしてしまうのが駆け出しのあるあるですね。😂


## 仮説の立て方の記事
下の記事をぜひ読んでください。***問題の切り分け***について書かれています。

https://freelance.cat-algorithm.com/divide-problem/


# 少ない時間で成果を出す
よく日本だととにかく気合と根性でいっぱい勉強するぞーとかいっぱい働くぞーみたいなことを言われているが、***大事なのは少ない努力(無駄な努力を省く)で最大の成果を出すこと***です。
トップエンジニアはこれを大事にされているみたいです。
***優先順位をつけて、大事な1つのことに集中して、それ以外はやらないこと***が大切になってきます。

## 自分の体験談(少ない時間で成果を出す)
CTOの方からあることをアドバイスをもらいました。***まずはやらないことを決めよう‼︎***
みんなTodoリストを作る人は多いけど、Nottodoリスト(***やらないことリスト***)を作る人は
けっこう少ないです。よく一生懸命勉強しているのに、成績上がらない人とかであるあるなのは、
「***やらなくてもいい努力をしている人が圧倒的に多い***」とおっしゃていました。
自分も不要な勉強をしてしまい、エンジニアの転職活動を始める時期が半年遅れてしまいました😭。
20代の半年はかなり大きいです。💦

## 少ない時間で成果を出すための動画

この動画はエンジニアと関係ないですが、かなり的を得たことを言っています。

https://www.youtube.com/watch?app=desktop&v=exqG5aT5eNU

# 1日4時間は1つのことに集中するために時間を確保する
***マルチタスクはやらない方がいい***です。自分もタスクの進捗も遅くなりましたし、
学習効率も圧倒的に悪かったです。生産性が40%落ちてしまうみたいです。😱

なので、マイクロソフトのエンジニアは、他の人のチャットやスマホなど全てシャットアウトして
***1つの作業に全集中で、目の前のことに取り組み***ます。



## コードリーディングの方法つまりシステム理解
やり方は、コードを全部読むのではなく、インターフェースと構造を理解することからやります。自分はGAFAから正社員なって欲しいとお願いされるレベルの強強エンジニアから

「***まずはメイン機能を理解する。その後に自分のタスクに関連するとこだけ理解する***」
ということを教わりました。

https://zenn.dev/norihashimo/articles/62530fbc43cdb9

# この本のメインテーマは無駄を省くこと
本の内容のメインテーマは、***無駄を省いていって、力を入れるべきとこに全集中という印象***でした。
今日からでもできそうなことなので、取り組んでいってください。

追加で***エンジニアの仕事は経費削減をすることで、会社の利益に貢献***します。
技術だけでなく、このような経費削減にも力を入れるといいです。

https://read-engineer.com/2023/09/26/shoboi/

# 番外編(元GAFAのCTOの方がお話をされていること)
世界レベルのエンジニアは、プログラミングやフレームワークの知識だけでなく
***ITの基礎概念(基本情報の試験の内容)なども理解している人が多い***みたいです。
ex)
ネットワーク(TCPIP)、Linux、Webセキュリティなど

https://note.com/takkun_desu/n/nf8c7a7a3b73e#f54ba4b3-57dc-4324-b801-28dd6a3b559a

https://envader.plus/dashboard

https://note.com/takkun_desu/n/n7297b6ea03ff

# わかりやすいYoutube動画

https://www.youtube.com/watch?v=pMrORF_-nvo

https://www.youtube.com/watch?v=kxfxgZpbEIs

https://www.youtube.com/watch?v=xJbysfKP8N4


# 資料

https://www.amazon.co.jp/%E4%B8%96%E7%95%8C%E4%B8%80%E6%B5%81%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%AE%E6%80%9D%E8%80%83%E6%B3%95-%E7%89%9B%E5%B0%BE-%E5%89%9B/dp/4163917683
VSCodeのMarkdownプレビューをQiitaに近づけてみる

普段の技術メモをこのQiitaで書いていて
手元のVSCodeでも似た書式にしたいなと思ってたのでメモ

必要だったのは
- 「:::note info」での装飾
- 「#」の章立てを標準より見やすく

といった程度　CSSは10年触ってないので細かいことは考えない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/6ae705fc-0bf9-b37e-17ae-f17c5f48de2d.png)
ありがたいことに　こちらとほぼ同じ変更でできた　https://trap.jp/post/1791/
前回検索時にはなかったサイトの様子

## 拡張機能
定番の
- Markdown All in One
- Markdown Preview Enhanced
- Paste Image

を入れる。　装飾はMarkdown Preview Enhancedで

## Markdown Preview Enhanced: Extend Parseの変更
まずF1キーを押して「Markdown Preview Enhanced: Extend Parser」を選択。
開いた parser.jsを変更

```parser.js
({
  onWillParseMarkdown: async function(markdown) {

    markdown = markdown.replace(/:::note\swarn[\s\S]*?:::/gm, (note_warn) => {
      note_warn =
        '<div class="alert note-warn">\n' + note_warn.slice(12);
        note_warn = note_warn.slice(0, -3) + "</div>";
      return note_warn;
    });
    markdown = markdown.replace(/:::note\salert[\s\S]*?:::/gm, (note_alert) => {
      note_alert =
        '<div class="alert note-alert">\n' + note_alert.slice(32);
        note_alert = note_alert.slice(0, -3) + "</div>";
      return note_alert;
    });
    markdown = markdown.replace(/:::[\s\S]*?:::/gm, (note_info) => {
      note_info = 
      '<div class="alert alert-info">\n' + note_info.slice(3);
      note_info = note_info.slice(0, -3) + "</div>";
      return note_info;
    });

    return markdown;
  },

  onDidParseMarkdown: async function(html) {
    return html;
  },
})
```
## Markdown Preview Enhanced: Customize CSS の変更
F1キーを押して「Markdown Preview Enhanced: Customize CSS」を選択
```style.css
.markdown-preview.markdown-preview {
  // modify your style here
  // eg: background-color: blue;
  .alert-info  {
    color: #000000;
    background-color: #f0fae9;;
    border-color: #97a18f;
  }
  .note-warn {
    color: #000000;
    background-color: #fcf8e3;
    border-color: #faebcc;
  }
  .note-alert {
    color: #000000;
    background-color: #f2dede;
    border-color: #ebccd1;
  }


  font-size: 16px;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto,
    Helvetica Neue, Helvetica, Arial, sans-serif, Apple Color Emoji,
    Segoe UI Emoji, Segoe UI Symbol;

  strong {
    color: inherit;
  }
  h1 {
    color: inherit;
    padding-bottom: 0.3em;
    border-bottom: 1px solid #eee;
    font-size: 2em;
    font-weight: 600;
  }
  h2 {
    color: inherit;
    padding-bottom: 0.3em;
    border-bottom: 1px solid #eee;
    font-size: 1.5em;
  }
  h3 {
    color: inherit;
    font-size: 1.25em;
  }
  h4 {
    color: inherit;
    font-size: 1em;
  }
  code {
    font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
  }

}
```

あとは保存してプレビュー実行するだけ

### 追記メモ
pdf出力時の改ページしたい部分に
```<div style="page-break-before:always"></div>```
と入力
Railsの論理削除機能におけるバリデーションスキップとデータ取得時に論理削除分も含める方法

Railsでソフトデリート機能を実装する際に遭遇する可能性のある２つの課題とその解決方法について説明します。一つ目は、特定の操作でバリデーションをスキップする方法、もう一つは、`default_scope`を使用しているモデルでソフトデリートされたレコードを取得する方法です。


## 1. 特定の操作でバリデーションをスキップする

Railsでは、モデルのバリデーションが非常に強力で役立つ一方で、特定の条件下でバリデーションをスキップしたい場合があります。例えば、ソフトデリートの操作では、いくつかのバリデーションを適用したくないかもしれません。

```ruby
class Reservation < ApplicationRecord
  # バリデーション
  validates :is_approved, inclusion: { in: [true, false] }
  validate :unique_future_reservation_per_customer_and_company, unless: -> { @skip_validation }

  # ソフトデリートメソッド
  def soft_delete
    @skip_validation = true
    update(deleted_at: Time.current)
  end
end
```

この方法では、インスタンス変数 `@skip_validation` を使ってバリデーションの実行を制御します。この変数が `true` の場合、`unique_future_reservation_per_customer_and_company` バリデーションはスキップされます。

## 2. `default_scope` が適用されるモデルでソフトデリートされたレコードを取得する

Railsで `default_scope` を使用すると、そのモデルのすべてのクエリに自動的に適用されるため、特定の条件を除外することが難しくなることがあります。ソフトデリートされたレコードを取得するためには、`unscoped` メソッドを使用して `default_scope` を無視する必要があります。

```ruby
class Reservation < ApplicationRecord
  default_scope { where(deleted_at: nil) }
  
  # ソフトデリートされたレコードを取得するスコープ
  scope :deleted, -> { unscoped.where.not(deleted_at: nil) }
end
```

このスコープを使用すると、ソフトデリートされたレコードだけを簡単に取得できます。

```ruby
Reservation.deleted
```

### 考慮点

これらの技術を使用する際は、`@skip_validation` のようなインスタンス変数が他のメソッドやアクションに影響を与えないように注意する必要があります。また、`unscoped` を使用する場合は、他の必要なスコープが誤って削除されないように、その使用範囲を明確に限定することが重要です。


## 補足: `->`について
`->` は Ruby で **ラムダ (lambda)** を表す記法です。ラムダは無名関数または小さな関数オブジェクトを定義するために使用されます。Rails のコンテキストで使用されるとき、これは主にモデル内のバリデーションやスコープ定義で条件を指定するのに使われます。

### ラムダ式の基本

ラムダ式は、次のように書くことができます：

```ruby
-> { puts "Hello, world!" }
```

または、パラメータを取る場合は次のようになります：

```ruby
->(name) { puts "Hello, #{name}!" }
```

### Railsでの使用例

Rails のモデル内で `unless:` オプションとともにラムダを使う一般的な使用例は、特定の条件下でのみバリデーションを実行する場合です。例えば：

```ruby
validates :email, presence: true, unless: -> { self.name.blank? }
```

この例では、`unless` オプションにラムダが使用され、`name` 属性が空の場合にのみ `email` の存在チェックをスキップします。

### ラムダとプロック

ラムダは Ruby の **Proc** クラスのインスタンスの一種ですが、プロック（ブロックをオブジェクトとして扱うためのもの）といくつか異なる点があります：

- **リターンの振る舞い**: ラムダ内で `return` を呼び出すと、ラムダ自体から値が返されます。一方、プロック内で `return` を呼び出すと、そのプロックを含む外側のスコープ（メソッドなど）から制御が抜けます。
- **引数の厳格性**: ラムダは引数の数が正確でなければならず、指定した数と異なる引数を渡すとエラーになります。プロックはより柔軟で、余計な引数は無視され、不足している引数は `nil` で補われます。

これらの特性により、ラムダは特定の振る舞いを期待する小さな関数を定義する際に役立ち、コードの意図を明確に表現するのに適しています。
defold の `go.get_position()` みたいな関数はどこで定義されているのか

# tl;dr

`go.` で始まる関数は、ゲームエンジンのレイヤーに C++ で実装されており、C++ と lua を連携させる機能によって lua から叩けるようになっている。

# 背景

[defold のチュートリアル](https://github.com/defold/tutorial-astronaut) をやっていると、突然 `go.get_position()` のようなコードが現れ、

> The name `go` *does not refer* to the current game object. It is the name of the Lua module that contains all game object functions.

などとあっさり説明されるが、lua のことをよくわかっていないのも相まっていまいち腑に落ちない。

気になってチュートリアルの内容が頭に入ってこなくなってしまったので、深入りしない範囲で調べた。

# 調査

github の defold リポジトリを `get_position` で雑に検索すると、下記のコードがヒットする。ファイル名からしていかにもそれっぽい。ゲームエンジン自体のソースコードで、C++ で実装されているようだ。

https://github.com/defold/defold/blob/bb9db7214bb38b9cb86fa95cfc8d747fc09307f7/engine/gameobject/src/gameobject/gameobject_script.cpp#L1055 

よく見ると、検索にヒットしたのは doc コメントの部分で、関数自体は `Script_GetPosition` という名前だった。そこで今度はこの `Script_GetPosition` で検索すると、同ファイル内に `GO_methods` という連想配列のようなものがヒットする。

https://github.com/defold/defold/blob/bb9db7214bb38b9cb86fa95cfc8d747fc09307f7/engine/gameobject/src/gameobject/gameobject_script.cpp#L2321

最後にその `GO_methods` で検索すると、再び同ファイル内に `luaL_register(L, "go", GO_methods);` なるコードがヒットする。名前からしてそれっぽいが、`luaL_register` は C 言語の関数を lua へ連携するときに使う関数のようだ。第二引数が `"go"` なのもそれっぽい。

https://github.com/defold/defold/blob/bb9db7214bb38b9cb86fa95cfc8d747fc09307f7/engine/gameobject/src/gameobject/gameobject_script.cpp#L2361

# まとめ

`go.` で始まる関数の呼び出し経路がざっくりとわかったのでよかった。とりあえず「天から降ってきた関数」とでも思っておけばよさそうだ。
Railsにおける確認画面を経由したフォーム処理の実装とリフレッシュ問題の解決方法

## はじめに:
Railsでのフォーム処理において、ユーザー入力の確認画面を挟むことは一般的な要件です。しかし、この確認画面でのブラウザのリフレッシュ（F5）操作が引き起こす問題には注意が必要です。この記事では、予約システムにおいて`new`アクションから`create`アクションに至る過程で確認画面（`confirm`アクション）を設けた場合の具体的なエラーとその解決策を解説します。

## エラーの状況:
- **エラー内容**: `ActionController::ParameterMissing in ReservationsController#confirm`
- **発生条件**: 確認画面でブラウザをリフレッシュすると発生

## エラーの原因:
このエラーは、確認画面でリフレッシュ操作を行った際に、フォームから送信されたデータが無くなるために発生します。`params.require(:reservation)`が期待する`reservation`キーがパラメータに存在しないため、`ParameterMissing`エラーが引き起こされます。

## 解決策の概要:
解決策は、セッションを使用してフォームデータを一時保存することです。具体的には、ユーザーがフォームを送信した際にデータをセッションに保存し、確認画面で表示後もリフレッシュしてもデータを保持できるようにします。

## 詳細な解決策:

### Step 1: データのセッション保存
```ruby
def confirm
  # POSTリクエストから来た場合はセッションにフォームデータを保存
  if request.post?
    session[:reservation_params] = reservation_params
    @reservation = Reservation.new(session[:reservation_params])
  # セッションに保存されたフォームデータがある場合はそれを利用
  elsif session[:reservation_params]
    @reservation = Reservation.new(session[:reservation_params])
  # リフレッシュなどでセッションにデータがない場合は、予約IDから直接予約データを取得
  elsif params[:id] # edit経由時にconfirmでリフレッシュしてもでータ保持するのに使用
    @reservation = Reservation.find(params[:id])
    # ここでセッションに予約の属性を再設定するかもしれません
    session[:reservation_params] = @reservation.attributes.slice(*reservation_params.keys.map(&:to_s))
  # それ以外の場合はエラーメッセージとともに新規作成ページにリダイレクト
  else
    redirect_to new_reservation_path, alert: "予約データが見つかりません。"
    return
  end

  # フォームで使用するためのその他のインスタンス変数をセットする
  # 例: @company, @customer, @services など
  # ...
end
```

### Step 2: セッションのデータクリーンアップ
```ruby
def create
  @reservation = Reservation.new(reservation_params)
  if @reservation.save
    session.delete(:reservation_params)
    redirect_to @reservation, notice: 'Reservation was successfully created.'
  else
    render :new
  end
end
```

### Step 3: `reservation_params`メソッドの調整
```ruby
def reservation_params
  if params[:reservation]
    params.require(:reservation).permit(:id, ...)
  elsif session[:reservation_params]
    ActionController::Parameters.new(session[:reservation_params]).permit(:id, ...)
  end
end
```

## まとめ:
セッションを利用することで、確認画面を含むフォーム処理におけるユーザーエクスペリエンスを向上させ、リフレッシュ時の問題を解決することができます。この方法はRailsアプリケーションにおける確認画面の実装において有効なアプローチを提供します。
決定係数とは

# 決定係数とは
データに対する推定された**回帰式の当てはまりの良さ**（度合い）を表します。
分かりやすくいうと、値同士が本当に関係しあっているのかを数値化したものです。

例えば、「テストの成績の良さ」を予測したいとします。
この時「普段の勉強時間」は、「テストの成績の良さ」に関係してそうですよね
しかし「月に美容院に行く回数」はあまり関係なさそうです

以上のように予測したい値に対して、入力するパラメータが本当に関係あるかどうかを数値として表現したものが決定係数です

一般的には 0.2 ~ 0.9 あたりの数値を取ることが多いです。ただ、どの数値を閾値とするかは開発者によるため、絶対的な数値はありません。

また、**なるべく少ない変数で予測を行うことが大切で説明力を上げるのよりも優先すべき**とされています


## 決定係数の求め方

```math
R^2 = 1 - \frac{\text{Residual Variation}}{\text{Total Variation}}
```
以上が決定係数の公式です。

決定係数を求めるには、全変動（Total Variation）と回帰変動（Regression Variation）を用います

詳しくは以下の記事をご覧ください

https://qiita.com/yuramaru/items/9cd94ae8a602f8a9a12b

# 自由度修正済決定係数
決定係数の特徴として、**入力するパラメータが多ければ多いほど値が高くなってしまう**
という欠点があります

最初の例で言うと「テストの成績の良さ」とは全く関係のないパラメータが大量に存在すると、システム的には正しいものだと誤認されてしまうということです


nをサンプルサイズ（データセットの数）、pをモデル内の説明変数の数とすると以下の式で表せます
```math
R_{\text{adj}}^2 = 1 - \frac{\text{Residual Variation} / (n - p - 1)}{\text{Total Variation} / (n - 1)}
```

先ほど決定係数の式に新しく説明変数の数が加わりました。
こうすることで**説明変数が増えるたびに決定係数が下がるというペナルティ**の概念を組み込むことができ、パラメータの増加による決定係数の劣化を軽減することができます

# 参考文献

https://bellcurve.jp/statistics/course/9706.html

https://atmarkit.itmedia.co.jp/ait/articles/2108/25/news033.html

https://jp.mathworks.com/help/stats/coefficient-of-determination-r-squared_ja_JP.html

https://avilen.co.jp/personal/knowledge-article/bayesian-statistics/

https://manabitimes.jp/math/1004

https://best-biostatistics.com/correlation_regression/adjusted-r-square.html#i
UbuntuのリポジトリがVSコードで開けなくなった件に関して

こんにちは！　

だいぶ久しぶりの投稿になってしまいました、、、。

先日、普段使用していたパソコンが不具合を起こしてしまって、別のパソコンで作業していたものの、UbuntuのディレクトリがVScode で開けなくて開発がすすめられない状態になってしまい、対処法を探していたところ以下のような記事を見つけその方法で対応すると開くことができました。今回はこちの内容に関して記事に残していきたいと思います！

VScodeで編集していて、Ubuntuを用いて開発を行っていることを前提とした話になります！

### Ubuntuでのコマンド


```
 cd 編集したいコマンドファイル名
```

cdコマンドで編集したいファイルに移動します。そのディレクトリ下でこのコマンドを打ち込みます。

```
 git .
```

すると、VScodeが開かれ、編集することができます！

意外と簡単に解決することができました、、、。
Pythonで「条件に一致するファイルやディレクトリの一覧を取得する」の動作を確認してみた

# 概要

Pythonで「条件に一致するファイルやディレクトリの一覧を取得する」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/python/file/index14.html

# 実装

以下のファイルを作成しました。
```sample1.py
import glob

print(glob.glob('./test/*.txt'))
```

```sample2.py
import glob

print(glob.glob('./test/**/*.txt', recursive=True))
```

```sample3.py
import glob

for name in glob.iglob('./test/**/*.txt', recursive=True):
  print(name)
```

以下のコマンドを実行しました。
```
$ mkdir back
$ mkdir img
$ touch book.png
$ touch book.txt
$ touch cup.png
$ touch cup.txt
$ touch pen.png
$ touch pen.txt
$ mkdir test
$ mv back img book.* cup.* pen.* test
$ python3 sample1.py 
['./test/pen.txt', './test/book.txt', './test/cup.txt']
```
```
$ touch test/back/2018.txt
$ touch test/back/2019.txt
$ touch test/back/2020.txt
$ mkdir test/back/old
$ touch test/back/old/2017.txt
$ touch test/img/profile.png
$ touch test/img/room.png
$ python3 sample2.py
['./test/pen.txt', './test/book.txt', './test/cup.txt', './test/back/2020.txt', './test/back/2019.txt', './test/back/2018.txt', './test/back/old/2017.txt']
```

```
$ python3 sample3.py 
./test/pen.txt
./test/book.txt
./test/cup.txt
./test/back/2020.txt
./test/back/2019.txt
./test/back/2018.txt
./test/back/old/2017.txt
```

# まとめ

何かの役に立てばと。
全変動と回帰変動と残差変動

# はじめに

回帰分析について調べていると必ず決定係数という単語を目にすると思います。
そこで、本記事では決定係数と密接に関係している**全変動**と**回帰変動**と**残差変動**について説明してきます

# 前提

## 全変動（Total Variation）: TSS（Total Sum of Squares）

```math

\text{Total Variation} = \sum_{i=1}^{n} (y_i - \bar{y})^2

```

データがどれぐらい散っているのかを表す指標です。
また、この数値は回帰モデルとは全く関係がない値であり、生データのばらつきを表す指標です

例えば、テストの点数のデータを集めるとしましょう

##### サンプル1
![スクリーンショット 2024-04-18 9.53.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2839531/4a6135a1-9aa5-c4d5-fa69-7a2c9fd98d48.png)

##### サンプル2
![スクリーンショット 2024-04-18 9.53.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2839531/258fe710-764f-3836-4e26-a9cb0870cf3b.png)

以上2つのようなデータがとれた場合サンプル2の方が各データと平均の距離が近いことがわかります。
そのため、全変動もサンプル2の方が小さくなります



> ### 余談
> また、似たような概念として分散が存在します。
> 
> ```math
> \text{Variance} = \frac{1}{n} \sum_{i=1}^{n} (y_i - \bar{y})> ^2
> ```
> 
> こちらは全変動を n（データの数）で割っているため、変動の平均を求めることができます



## 回帰変動（Regression Variation）: SSR（Sum of Squares due to Regression）

```math

\text{Regression Variation} = \sum_{i=1}^{n} (\hat{y}_i - \bar{y})^2

```

回帰モデルを適用した時、実際のデータの平均とどれほどの差分が存在するかを表す指標です

## 残差変動（Residual Variation）: SSE（Sum of Squared Errors）

```math
\text{Residual Variation} = \sum_{i=1}^{n} (y_i - \hat{y}_i)^2
```



回帰モデルを適用した時、実際のデータとどれほどの差分が存在するかを表す指標です

「1日の勉強時間」から「テストの点数」を求めたいとします。
また、直線が回帰モデル、黒点が実際のデータ、赤線が回帰モデルと実際のデータの距離とします。
そうすると以下の図のようになりました

![Frame 6 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2839531/6d523b01-785c-2626-587b-73b5de0e63af.png)


残差変動とは、黒点（実際のデータ）と直線（回帰モデルで予測された値）の赤線（距離）の総和のことです

## 三つの値の関係性

三つの値には以下の関係があります

```
「全変動」＝「回帰変動」＋「残差変動」
```

# 参考文献

https://bellcurve.jp/statistics/course/9706.html

https://atmarkit.itmedia.co.jp/ait/articles/2108/25/news033.html

https://jp.mathworks.com/help/stats/coefficient-of-determination-r-squared_ja_JP.html

https://avilen.co.jp/personal/knowledge-article/bayesian-statistics/

https://manabitimes.jp/math/1004

https://best-biostatistics.com/correlation_regression/adjusted-r-square.html#i
今の開発組織でトライしたいことをまとめてみる

筆者は現在勤務先の研究所で次世代スーパーコンピュータ向けソフトウェアの開発に関わっています。主にAI向けOSS、TensorFlow, PyTorchのArmアーキテクチャプロセッサ向け移植やLLMの性能測定、改修などに取り組んでいます。よって、その業務内容と関連して今後(または現在進行形で)トライしたいことを記載しようと思います。

トライしたいことは、大きく挙げると以下の3点です。
* OSSへのコントリビューション
* OSSのソースコード理解
* DeepXDE, DeepSpeedへの挑戦

# OSSへのコントリビューション
業務でTensorFlowやPyTorchなどのOSSを利用しており、バグ修正によるコントリビューションなども行っています。今後も継続してOSSへのコントリビューション(バグ修正、ドキュメント整備等)を継続していきたいです。IssueをSubmitしてもすぐに修正されないということが頻繁に発生します。そういった時に修正コードをCommit出来る様に技術力の強化や内部構造の理解にも努めたいと思います。

# OSSのソースコード理解
上記のOSSへのコントリビューションを継続していくために、各OSSの内部構造の理解は不可欠だと感じています。幸い今の職場にTensorFlowの内部構造を長らく勉強されていた方がおられるので、その方から頂いたアドバイスや共有頂いた知見をもとにTensorFlow, PyTorch, Jaxの内部構造を解読していきたいと思っています。

# DeepSpeed, Horovodへの挑戦
昨今のLLMは一台のマシン(サーバー)上に載せたGPUで動かすにはあまりにもモデルのデータサイズが大き過ぎます。この肥大化を続けるLLMの実行に有効な手立てとしてモデルを圧縮させるという手も有りますが、いっそのことモデルを複数台のマシン上に分割して乗せた上で実行する、いわゆる分散実行という手法が有ります。それを実現するOSSとしてDeep SpeedとHorovodが有ります。Horovodは老舗でUberによって開発(現在はLFの所属)されました。Deep SpeedはMicrosoftによって開発され、昨今急激に成長しています。但し、PyTorchのみに対応しているため、TensorFlowを分散実行するためにはHorovod一択となります。これらのOSSをLLMのフレームワークに取り込んで複数台のサーバー上で実行出来る様に改良できればと思っています。

# DeepXDEへの挑戦
微分方程式を解くためのDeep Learningフレームワークが開発されました。それが、DeepXDEです。微分方程式は一部を除いて直接的に手計算で解くことは困難です。そんな微分方程式をNeural Networkの力を借りて解こうというコンセプトの様です。まだまだ登場したばかりで、ソースコードも熟れてはいないようです。コミットのチャンスも多々有りそうです。

# 2024/6/23追記：Amazonギフト券抽選に当選しました
この記事はFindy主催の記事投稿キャンペーンで投稿したのですが、そのキャンペーンは抽選で500人にAmazonギフト券が当たるというものでした。どうやら筆者はその抽選に当選したみたいで、ギフト券を頂きました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/321ef41e-5758-6b98-2b87-739aba1921f1.png)
Sentence-trasnformers tripletEvaluaterのversionUpに伴う修正

## 目的
* sentence-transformersとtripletlossを用いて学習を行うコードのversion upに伴う微修正

## 参考
https://www.ogis-ri.co.jp/otc/hiroba/technical/similar-document-search/part9.html

https://www.ogis-ri.co.jp/otc/hiroba/technical/similar-document-search/part18.html

## code
* 記載時のversionは `sentence-transformers 2.7.0`
* tripletなdatasetを使用しているのは参考の第9回の方なので，そちらのコードを調整する

### model load
```python
import transformers
transformers.BertTokenizer = transformers.BertJapaneseTokenizer

from sentence_transformers import SentenceTransformer
from sentence_transformers import models
from sentence_transformers.losses import TripletDistanceMetric, TripletLoss
from sentence_transformers.evaluation import TripletEvaluator
from sentence_transformers.readers import TripletReader
from sentence_transformers.datasets import SentencesDataset
from torch.utils.data import DataLoader

transformer = models.Transformers('cl-tohoku/bert-base-japanese-whole-word-masking')

pooling = models.Pooling(
    transformer.get_word_embedding_dimension(), 
    pooling_mode_mean_tokens=True, 
    pooling_mode_cls_token=False, 
    pooling_mode_max_tokens=False
)

model = SentenceTransformer(modules=[transformer, pooling])
```

`models.BERT => models.Transformers` に修正

### TripletEvaluatorの調整
```python
dev_data = SentencesDataset(triplet_reader.get_examples('triplet_dev.tsv'), model=model)
dev_dataloader = DataLoader(dev_data, shuffle=False, batch_size=BATCH_SIZE)
evaluator = TripletEvaluator(dev_dataloader)
```
`TripletEvaluato`rの引数にdataloaderを与えているが，ver 0.3.3あたりで`(anchor[List], positive[List], negative[List])` で与えるように修正されている．

そのため，anchor,positive,negativeのテキストデータをlistに入れなおす必要がある．
```python
from sentence_transformers.readers import TripletReader

anchor_list = []
positive_list = []
negative_list = []
# crate [each anchor, positive, negative] text List 
for example in triplet_reader.get_examples('triplet_dev.tsv')
    anchor_list.append(example.texts[0])
    positive_list.append(example.texts[1])
    negative_list.append(example.texts[2])
```

```python
dev_data = SentencesDataset(triplet_reader.get_examples('triplet_dev.tsv'), model=model)
dev_dataloader = DataLoader(dev_data, shuffle=False, batch_size=BATCH_SIZE)
evaluator = TripletEvaluator(anchor_list, positive_list, negative_list)
```
これで modelを学習できるようになる！

あんまり綺麗じゃない & いい方法他にもありそうなのですが，とりあえず動かすというだけならまぁこれでいいでしょう
dataLoaderを与える場合の方が綺麗な実装な気がするんですが，なんでListで与える形式になったんだろう?? 謎
深さ優先探索と幅優先探索でJSONの構造解析

外部のオープンデータを活用する上でWebAPIを活用することは多いと思います。特にその中ではJSONやXMLが多く、PythonでJSONやXMLを利用する際には辞書形式に直して活用します。
※なお、幅優先探索については深さ優先探索を作った後にChatGPTに教わって作りました
# 深さ優先探索の関数
第一引数は辞書データ、第二引数は文字列として初期値は何も入っていませんが、辞書に使う変数名を入れるとその後辞書をピンポイントで必要な所をコピーペーストする時に便利なので辞書に使う変数を第二引数に入れて関数を使うことをお勧めします。
```Python3
def depth(jsn, var=""):
    if isinstance(jsn, dict):
        for row in jsn:
            depth(jsn[row], var=var+"[\""+row+"\"]")
    elif isinstance(jsn, list) and jsn != []:
        for i in range(len(jsn)):
            depth(jsn[i], var=var+"["+str(i)+"]")
    else:
        print(var+"="+str(jsn))
        pass
```
ここで、辞書データを扱う場合は変数型が「辞書」「リスト」の時にキーとキーを記録した文字列を使って更に深く解析をしていき、それとは違う変数型の場合には記録したキーを出力するようにします。

# 幅優先探索(参考：生成AI)
第一引数と第二引数の仕様は深さ優先探索と同じになります。
```Python3
from collections import deque
def width(jsn, var=""):
    queue = deque([(jsn, var)])
    while queue:
        node, var = queue.popleft()
        if isinstance(node, dict):
            for key in node:
                queue.append((node[key], var+"[\""+key+"\"]"))
        elif isinstance(node, list) and node != []:
            for i in range(len(node)):
                queue.append((node[i], var+"["+str(i)+"]"))
        else:
            print(var+"="+str(node))
            pass
```
ではここからは関数を実装した上での使い方の一例です。
```Python3
import json
import requests

def depth(jsn, var=""):
    if isinstance(jsn, dict):
        for row in jsn:
            depth(jsn[row], var=var+"[\""+row+"\"]")
    elif isinstance(jsn, list) and jsn != []:
        for i in range(len(jsn)):
            depth(jsn[i], var=var+"["+str(i)+"]")
    else:
        print(var+"="+str(jsn))
        pass

url = "https://hoge.com/data.json" #ここにJSONのあるURLを入れる
res = requests.get(url)
data = json.loads(res.text)
depth(data, "data") #深さ優先探索
print()
```
一例として<a href="https://www.jma.go.jp/bosai/forecast/data/forecast/130000.json">こちらのページ</a>を解析した場合についてを紹介します。
```
data[0]["publishingOffice"]=気象庁
data[0]["reportDatetime"]=2024-04-17T17:00:00+09:00
data[0]["timeSeries"][0]["timeDefines"][0]=2024-04-17T17:00:00+09:00
data[0]["timeSeries"][0]["timeDefines"][1]=2024-04-18T00:00:00+09:00
data[0]["timeSeries"][0]["timeDefines"][2]=2024-04-19T00:00:00+09:00
data[0]["timeSeries"][0]["areas"][0]["area"]["name"]=東京地方
data[0]["timeSeries"][0]["areas"][0]["area"]["code"]=130010
data[0]["timeSeries"][0]["areas"][0]["weatherCodes"][0]=200
data[0]["timeSeries"][0]["areas"][0]["weatherCodes"][1]=212
data[0]["timeSeries"][0]["areas"][0]["weatherCodes"][2]=101
<中略>
data[1]["precipAverage"]["areas"][0]["min"]=11.5
data[1]["precipAverage"]["areas"][0]["max"]=30.9
data[1]["precipAverage"]["areas"][1]["area"]["name"]=八丈島
data[1]["precipAverage"]["areas"][1]["area"]["code"]=44263
data[1]["precipAverage"]["areas"][1]["min"]=28.3
data[1]["precipAverage"]["areas"][1]["max"]=58.3
data[1]["precipAverage"]["areas"][2]["area"]["name"]=父島
data[1]["precipAverage"]["areas"][2]["area"]["code"]=44301
data[1]["precipAverage"]["areas"][2]["min"]=7.6
data[1]["precipAverage"]["areas"][2]["max"]=28.1
```

これによって数値や文字列に至るまでのキーが分かるようになります。
また所感ですが、JSONからデータベースか何かを作る際には深さ優先探索で出力してみると解析が早くなるような気がします。
初心者向けPower BIを使った売上データ可視化

本日は、マイクロソフトのデータ可視化ツールPower BIを使った売上データ分析のプロジェクトをご紹介いたします。このプロジェクトでは、企業の売上実績データを効果的に視覚化し、経営陣や営業部門が素早く分析できるようなダッシュボードを少々簡単に構築しました。

![截屏2024-04-15 03.49.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535759/499487cd-617b-7d5a-f4de-56f0ea508a6b.png)


#### プロジェクトの手順と内容は以下の通り

- データソースの接続と統合 まずはデータソースとなるERP、CRM、その他業務システムからデータを取得し、Power Queryを使ってデータの変換、クリーニングを行いました。

- データモデリングとDAXによる計算フィールド作成 次にPower Pivotを使って、売上データのデータモデルを構築しました。DAXという式言語を使って、売上金額、利益率、前年比などの計算フィールドを作成しています。

- レポートおよびダッシュボード作成 構築したデータモデルをベースに、様々な視覚化オブジェクト(棒グラフ、円グラフ、カードなど)を配置し、売上状況が一目でわかるレポートとダッシュボードを作成しました。

- デザインと機能性の調整 最後に、視覚効果が高く、かつ利用者にとって分かりやすいレポート・ダッシュボードになるよう、デザインの調整やスライサーなどの機能を追加しました。


BI分析ツールの導入においては、単に技術を使うだけでなく、戦略的なアプローチが重要視されます。ビジネス要件をしっかり把握し、段階を踏んだ体系的な開発プロセスを経ることが大切です。


#### 一般的なBI開発の流れは以下の通りです。

- 事業・ビジネス要件の明確化 
  最初に経営層やユーザー部門と協議し、どのようなビジネス課題を解決したいのか、分析の目的や対象を明らかにします。  
- データソースの選定と統合 
  次に必要なデータソースを特定し、ERP、CRM、その他システムからデータを抽出します。異なるソースのデータ統合も行います。
- データモデリング 
  取得したデータを正規化し、キューブやリレーショナルモデルなどの最適なデータ構造を構築します。
- ETLとデータ加工 
  抽出したデータを目的に合わせて変換、加工します。カスタム計算項目の作成なども行います。
- 分析レポートおよびダッシュボード開発 
  モデリングされたデータをベースに、ビジネス要件に合わせた視覚化レポートやダッシュボードを構築します。
- 運用とメンテナンス 
  ユーザーへの展開と並行し、定期的なモデルやレポートの見直しや機能拡張を続けていきます。

こうした一連のプロセスを経ることで、ビジネスニーズに適したBI環境が実現できます。要件に基づいた分析アプローチと、ユーザビリティの高い視覚化により、経営判断の質が大幅に向上するでしょう。
リーダブルコード10章　要点まとめ

リーダブルコード10章「無関係の下位問題を抽出する」の要点を超簡単にまとめた

# 積極的に小さなリファクタを行う
一見無関係な小さなコードでも積極的にリファクタを行うことで、堅牢で読みやすいコードになる。
本章では、大きな問題から分割した無関係の下位問題を積極的に抽出する意義を説明している。

# 純粋なユーティリティコード
使いまわせそうな有用なコードは関数化して再利用できるようにする
例）文字列の操作、ファイルの読み書きなど

# 思いもよらぬ恩恵、汎用コードをたくさん作る
長くなってしまい可読性の低いコードを関数化し、小さく独立させることで機能追加、可読性向上、エッジケースの処理が楽になる。
プロジェクトから完全に切り離し、`utils/`ディレクトリなどにまとめておくことで、本来重要なプロジェクトコードを簡単にメンテナンスできる

# やりすぎ
小さな関数を作りすぎると、逆に読みにくくなってしまう。常に読みにくさのコストを考える必要がある。
【Next.js】動的インポートで読み込み中のコンポーネントを設定する方法

動的インポートで読み込み中のコンポーネントを設定するには以下のように記述します。

```jsx
import dynamic from 'next/dynamic'
 
const Sample = dynamic(
  () => import('../components/Sample'),
  {
    loading: () => <p>Loading...</p>,
  }
)
 
export default function Page() {
  return (
    <div>
      <Sample />
    </div>
  )
}

```
Julia 独特の数式記法

## Julia 独特の数式記法

‐ a の平方根 √a　　普通は sqrt(a)
‐ a の3乗根は ∛a　　普通は cbrt(a)
‐ a の4乗根は ∜a　　普通は fourthroot(a)


```julia
a = 2
(√a, ∛a, ∜a)
```




    (1.4142135623730951, 1.2599210498948732, 1.189207115002721)



## 特定の数値

- π（円周率）  \pi + tab  （\ p i の後に　tabキー）
- e （ネイピア数）　　\euler + tab

π と 1π の違いにも留意。


```julia
π
```




    π = 3.1415926535897...




```julia
1π
```




    3.141592653589793




```julia
π * ℯ
```




    8.539734222673566



## 演算の優先順位

確信のない場合（や Julia のことがよくわからない人も見る可能性があるような場合）は，カッコを挿入するなど明示的な記述をしましょう。


```julia
a = 3
2a^2 == 2*a^2
```




    true




```julia
1/2a == 1/(2a)
```




    true




```julia
1/2a^2 == 1/(2*a^2)
```




    true




```julia
1/2√3 ==1/(2√3)
```




    true




```julia
1/2√3(a + 1) ==1/(2*√3*(a + 1))
```




    true




```julia
1/2(3 + 5) == 1/(2*(3 + 5))
```




    true




```julia
3a/2(3 + 5) == 3*a/(2*(3 + 5))
```




    true




```julia
3^2(3 + 5) == 3^(2*(3 + 5))
```




    true




```julia
3^2*(3 + 5) == (3^2)*(3 + 5)
```




    true




```julia
√2∛3∜4 == √2*∛3*∜4
```




    true




```julia
√2∛3∜4 == √2*∛3*∜4
```




    true




```julia
√2(3 + 5)√3 == √2*((3 + 5)√3)
```




    true




```julia
√2(3 + 5)∛3∜4 == √2*((3 + 5)∛3)*∜4
```




    true




```julia
(1 + 2)a == (1 + 2)*a
```




    true



a(1 + 2) は a が関数でない限りエラーになります。
アクセス制限されてるサイトが、誰でも見れるようになっていた？？

お久しぶりです。
入社してから早４年目。
現在も様々なプロジェクトに参画しながら、日々色んなことを学んでおります。

今回は、実際に経験した体験談を問題形式で記載し、投稿しようと思います。
この他にも溜まった経験談もあるので、少しづつアウトプットしていけたらと思います。
(忙しくなければ・・・・)
それでは、さっそく

<h2>【問題】</h2>

とあるサイトがあります。
そのサイトは特定のサイト経由でないとアクセスできず404ページを表示し、アクセス制限を実施しています。

ですが、その404ページには、抜け道があり
ヘッダーに設定されているリンクをクリックすると<br>問題なくページ遷移し、他のページも見れるような形で<br>アクセスができるようになりました。

安心したのも束の間、今度はURL部分をクリックし<br>再読み込みを実施したところ、再度404ページが表示されてしまいました。
 
なぜ、このようなことが起きるのでしょうか？
サイト自体は問題なく稼働しているので、特別異常はなさそうです。
<br>
<strong>それでは、シンキングタイムスタート!!
<br>
<br>
<br>
<br>
<strong>💡ヒント:「リンクをクリック」が重要です。
<br>
<br>
<br>
<strong>そろそろわかったかな？
<br>
<br>
<br>
<h2>【正解は...】</h2>
<strong>A.「そのサイトはリファラによりアクセス制限を実施していたため」
になります。</strong>
<br>
<br>
リファラについては以下のサイトがわかりやすく説明されておりました。<br>
いつもお世話になっているので、ご紹介させていただきます<br>


https://wa3.i-3-i.info/word129.html


また、copilotにもきいてみました。　

>リファラとは、アクセス解析時の意味としては「参照元」のことを指します。具体的には、自社のウェブページにアクセスしてきたユーザーがどこから来たのかを示します。<br>例えば、あるページにアクセスしてきたユーザーが、その前のサイトページから来た場合、その前のサイトページが「リファラ」となります。

うん、完璧に説明してくれましたね。さすがです。

問題のサイトはリファラでアクセス制限を行っていたため、404ページにあるヘッダーのリンクからアクセスができるようになってたんですね。
リファラで制限したければ、安易に404ページには、リンクを設置するべきではないですね。
<br>
皆さんは、さらっと回答できましたでしょうか？
私は、実際に業務で調査を依頼されたときに、一瞬「なんでだ？」となってしまいました。

備忘録として、記事に残そうと思います。

それではまた👋
java複数のスレッドの同期処理

## java Thread
スレッドとは、プログラム内での実行スレッドのことです。Java仮想マシンでは、アプリケーションは並列に実行される複数のスレッドを使用することができます。
## synchronized
synchronizedブロックの開始時にsynchronized文で指定したオブジェクトのロックを取得し、終了時にそのロックを開放します。
## wait
ほかのスレッドがこのオブジェクトの notify() メソッドまたは notifyAll() メソッドを呼び出すまで、現在のスレッドを待機させます。
## notify
このオブジェクトのモニターで待機中のスレッドを 1 つ再開します。
## notifyAll
このオブジェクトのモニターで待機中のすべてのスレッドを再開します。
## 実装確認
2つのスレッドで1～100の数字を交替で順番に出力します。
```java
package com.example.thread;

class PrintNumber implements Runnable {
  private int number = 1;
  @Override
  public void run() {
    while(true){
      synchronized (this){
        if(number <= 100){
          notify();
          try {
            Thread.sleep(100);
          } catch (InterruptedException e) {
            throw new RuntimeException(e);
          }
          System.out.println(Thread.currentThread().getName() + ":" + number);
          number ++;

          try {
            wait();
          } catch (InterruptedException e) {
            throw new RuntimeException(e);
          }
        } else {
          break;
        }
      }
    }
  }
}
public class ThreadTest {
  public static void main(String[] args) {
    PrintNumber p = new PrintNumber();

    Thread t1 = new Thread(p, "Thread 1");
    Thread t2 = new Thread(p, "Thread 2");

    t1.start();
    t2.start();
  }
}
```
実行結果
```cons
> Task :ThreadTest.main()
Thread 1:1
Thread 2:2
Thread 1:3
Thread 2:4
Thread 1:5
Thread 2:6
Thread 1:7
Thread 2:8
Thread 1:9
Thread 2:10
Thread 1:11
Thread 2:12
Thread 1:13
Thread 2:14
Thread 1:15
Thread 2:16
Thread 1:17
Thread 2:18
Thread 1:19
Thread 2:20
Thread 1:21
Thread 2:22
Thread 1:23
Thread 2:24
Thread 1:25
Thread 2:26
Thread 1:27
Thread 2:28
Thread 1:29
Thread 2:30
Thread 1:31
Thread 2:32
Thread 1:33
Thread 2:34
Thread 1:35
Thread 2:36
Thread 1:37
Thread 2:38
Thread 1:39
Thread 2:40
Thread 1:41
Thread 2:42
Thread 1:43
Thread 2:44
Thread 1:45
Thread 2:46
Thread 1:47
Thread 2:48
Thread 1:49
Thread 2:50
Thread 1:51
Thread 2:52
Thread 1:53
Thread 2:54
Thread 1:55
Thread 2:56
Thread 1:57
Thread 2:58
Thread 1:59
Thread 2:60
Thread 1:61
Thread 2:62
Thread 1:63
Thread 2:64
Thread 1:65
Thread 2:66
Thread 1:67
Thread 2:68
Thread 1:69
Thread 2:70
Thread 1:71
Thread 2:72
Thread 1:73
Thread 2:74
Thread 1:75
Thread 2:76
Thread 1:77
Thread 2:78
Thread 1:79
Thread 2:80
Thread 1:81
Thread 2:82
Thread 1:83
Thread 2:84
Thread 1:85
Thread 2:86
Thread 1:87
Thread 2:88
Thread 1:89
Thread 2:90
Thread 1:91
Thread 2:92
Thread 1:93
Thread 2:94
Thread 1:95
Thread 2:96
Thread 1:97
Thread 2:98
Thread 1:99
Thread 2:100
```
行列の零空間の正規直交基底を計算するアルゴリズム

有名な方法であるが、メモ書き程度に残す。pythonでは`scipy.linalg.null_space`で以下のアルゴリズムで計算される行列の零空間の正規直交基底ベクトルを列ベクトルとして並べた行列を得られる。

## 特異値分解を利用する方法
$A \in \mathbb{R}^{n \times m}$の零空間
```math
\mathrm{Ker}(A) = \{v \in \mathbb{R}^{m}| Av= \boldsymbol{0}_n\}
```
の正規直交基底を具体的に計算したい。線型写像の次元定理から、
```math
\mathrm{rank}(A) + \mathrm{dim} (\mathrm{Ker}(A)) = m
```
である。ここでは、$\mathrm{rank}(A) = k, \mathrm{dim} (\mathrm{Ker}(A)) = m - k$とする。
$\mathrm{rank}(A) = k$より、$A$は$0$でない特異値を$k$個持つ。それを$\sigma_1>...>\sigma_k>0$として、Aを特異値分解する。
```math
A = U 
\begin{bmatrix}
\mathrm{diag}(\sigma_1, ..., \sigma_k) & O_{k, m-k} \\
O_{n-k, k} & O_{n-k, m-k}
\end{bmatrix}
V^T
```
$U \in \mathbb{R}^{n \times n}, V \in \mathbb{R}^{m \times m}$は直交行列。$U = [u_1,...,u_n], V=[v_1,...,v_m]$とする。
$V^T = V^{-1}$なので、
```math
A V = \begin{bmatrix}
U \begin{bmatrix} \mathrm{diag}(\sigma_1, ..., \sigma_k) \\ O_{n-k, k}\end{bmatrix} & U O_{n, m-k} \\
\end{bmatrix}
```
つまり、
```math
\begin{bmatrix}Av_1 &...&Av_m\end{bmatrix} = \begin{bmatrix}
\sigma_1 u_1 &...&\sigma_k u_k  & O_{n, m-k} \\
\end{bmatrix}
```
となる。
したがって、$A[v_{k+1} ... v_{m}] = O_{n, m-k}$である。
$v_{k+1} ... v_{m}$が求めるべき$A$の零空間の$m-k$本の正規直交基底である。
ちなみに、同様の理由で$u_{k+1}, ..., u_{n}$は$A^T$の零空間の正規直交基底になる。
Palworldに追加されたAPIを叩いてみる

## はじめに
どうも、 @Keichan_15 です。:bow:

2024年に入ってから記事執筆の頻度が急激に落ちてしまい、焦って齷齪している間にもう4月…。時の流れは残酷ですね。:cold_sweat:

最近の私は以前に紹介したおうちサーバーが本格稼働し始めたことで、`cron`でPalworldのサーバーを定時で再起動するスクリプトを組んだり、`docker`を入れてクラウド運用(`fly.io`)していた`ChatGPT-Bot`をオンプレで稼働させるように変更したり、といったことをちまちまやっておりました。

https://qiita.com/Keichan_15/items/f354c665f3058a1e4fe0

https://qiita.com/Keichan_15/items/70907ff47c5e531f0462

コスト面においても、気にする点としては電気代だけなので、`fly.io`や`AWS`といったクラウドサーバーの従量課金を気にする必要もなくなり、結構ストレスフリーな運用ができています。

ところでそんなこんなしている矢先、Palworldの`v0.2.0.6`アップデートで正式に**APIが追加された**という情報が！:tada:

https://twitter.com/Palworld_JP/status/1775736883886379504

今回はこの追加されたAPIを実際に叩いて動作確認をしてみます！

どうも最近`RCON`の調子が悪いんですよね。3回に1回は再起動に失敗するみたいなことがあったり…。
なので、再起動系もこっちのAPIを叩いてサーバーシャットダウン -> 起動シェルスクリプト実行みたいなのを`cron`で回せたらいいなあと。

早速やっていきましょう！:walking:

## サーバー側の設定でREST APIを有効化する

https://tech.palworldgame.com/ja/api/rest-api/palwold-rest-api

> _This is a simple REST API for Palworld._
_Need to configuration `RESTAPIEnabled=True` to use this api._
_This api is now experimental._

`REST API`を有効化するためには、`RESTAPIEnabled=True`に設定してね。とあります。

もう少し細かく説明すると、ワールドの設定ファイルである **PalWorldSettings.ini** に存在する`RESTAPIEnabled`という項目を`True`に設定すれば、`REST API`が使用できるようになります。

Linux Serverだと `/home/steam/Steam/steamapps/common/PalServer/Pal/Saved/Config/LinuxServer`の直下に配置されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/44f57175-3808-5ded-d4c9-0b797138ec01.png)

これで開いているサーバーがREST APIに対応しました。なんて便利なの…。:kissing_heart:

## curlで叩いてみる

では早速`curl`で叩いてみましょう！:joystick:

僕はBASIC認証なるものの仕組みがあまり分かっておらず、`Authroization`で弾かれまくる問題に悩まされていたのですが、色々調べていたところ、`curl`で叩くには **`admin:[admin_password]`** で認証ができるとのこと。

https://www.reddit.com/r/Palworld/comments/1bvh5y5/how_to_configure_a_usernamepassword_for_new_rest/

ということで、サーバーを開いているUbuntu Server内から`curl`コマンドを叩いてみます。

今回は、サーバーに参加しているプレイヤー情報を取得する`Get player list.`を実行してみます。

https://tech.palworldgame.com/ja/api/rest-api/players

```terminal:terminal
$ curl admin:hoge_password http://localhost:8212/v1/api/players
```

:::note warn
`hoge_password`の部分は`PalWorldSettings.ini`で設定している **`AdminPassword`** の値を設定してください！
:::

実際に叩いてみた結果はこちら。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/fa5450d7-a29d-5ccc-ce4c-1c431525f421.png)

このようにサーバーに参加しているプレイヤーデータを取得することができました。

ちなみに余談ですが、`ip`の部分はモロ参加しているプレイヤーのグローバルIPアドレスが書いているので少し怖いなあ…と。笑

レスポンスに含めているのはIPアドレス単位でBanを実施する時とかの為に含めているのかな？:thinking:

他にも様々な種類のAPIがあるので、上手く組み合わせればdiscord側から参加者やサーバーシャットダウン等の仕組みを実現できるかもしれませんね！:relaxed:

## おわりに
いかがでしたでしょうか。

APIを叩く際の参考資料や情報がほぼ見当たらなかった為、今回こちらの記事執筆に至りました。

- `curl`でとりあえずAPI叩いてレスポンス見てみたい！
- `REST API`の設定方法を知りたい！

上記でお困りの方の助けとなれば幸いです！本当に便利ですよ、このAPI！:wrench:

ご覧いただきありがとうございました！:hand_splayed:
AWS Lambda で CloudWatch アラームの自動有効化/無効化を行う方法

この記事では、AWS Lambdaを使用してCloudWatchアラームを自動的に有効化または無効化する方法を詳しく説明します。
AWS EventBridgeとCloudFormationも活用し、完全に自動化されたソリューションを構築する方法について解説します。

#### 1. Lambda関数の概要

**cloudwatch-alarm-autostop** と **cloudwatch-alarm-autostart** という2つのLambda関数を作成します。
これらの関数は、CloudWatchのアラームを特定のタグに基づいて有効または無効にします。

##### cloudwatch-alarm-autostop
このLambda関数は、タグ `Alarm-AutoStop` の値が `yes` のアラームを無効にします。

```python
import boto3

def lambda_handler(event, context):
    cloudwatch = boto3.client('cloudwatch')
    nt = None

    while True:
        response = cloudwatch.describe_alarms(MaxRecords=100, NextToken=nt if nt else None)
        for alarm in response['MetricAlarms']:
            tags = cloudwatch.list_tags_for_resource(ResourceARN=alarm['AlarmArn'])
            if any(tag['Key'] == 'Alarm-AutoStop' and tag['Value'] == 'yes' for tag in tags['Tags']):
                cloudwatch.disable_alarm_actions(AlarmNames=[alarm['AlarmName']])
        nt = response.get('NextToken')
        if not nt:
            break
```

##### cloudwatch-alarm-autostart
このLambda関数は、タグ `Alarm-AutoStart` の値が `yes` のアラームを有効にします。

```python
import boto3

def lambda_handler(event, context):
    cloudwatch = boto3.client('cloudwatch')
    nt = None

    while True:
        response = cloudwatch.describe_alarms(MaxRecords=100, NextToken=nt if nt else None)
        for alarm in response['MetricAlarms']:
            tags = cloudwatch.list_tags_for_resource(ResourceARN=alarm['AlarmArn'])
            if any(tag['Key'] == 'Alarm-AutoStart' and tag['Value'] == 'yes' for tag in tags['Tags']):
                cloudwatch.enable_alarm_actions(AlarmNames=[alarm['AlarmName']])
        nt = response.get('NextToken')
        if not nt:
            break
```

#### 2. IAMポリシーの設定

以下のIAMポリシーをLambda関数にアタッチすることで、必要なCloudWatch APIを呼び出す権限を付与します。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cloudwatch:DescribeAlarms",
                "cloudwatch:ListTagsForResource",
                "cloudwatch:DisableAlarmActions",
                "cloudwatch:EnableAlarmActions"
            ],
            "Resource": "*"
        }
    ]
}
```

#### 3. EventBridgeのCloudFormation設定

以下のCloudFormationテンプレートを使用して、特定の時間にLambda関数をトリガーするEventBridgeルールを作成します。
今回は、毎日AM4:00にして`cloudwatch-alarm-autostart`に付けるトリガーの場合になります。

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: CloudFormation template for EventBridge rule 'cloudwatch-alarm-autostart-0400'
Resources:
  EventRule0:
    Type: AWS::Events::Rule
    Properties:
      Description: Activate alarm at 4:00 AM
      EventBusName: default
      Name: cloudwatch-alarm-autostart-0400
      ScheduleExpression: cron(0 19 * * ? *)
      State: ENABLED
      Targets:
        - Id: k70ks679enybum7o4zas
          Arn: arn:aws:lambda:ap-northeast-1:236693288971:function:cloudwatch-alarm-autostart
```

この設定により、毎日日本時間の4:00 AMに`cloudwatch-alarm-autostart` Lambda関数が実行され、指定されたアラームが自動的に有効化されます。

#### まとめ

このガイドでは、AWS LambdaとEventBridgeを使用してCloudWatchアラームを自動で有効化・無効化する方法を説明しました。
これにより、運用の自動化と効率化が図れます。
Flutter 〜main関数の無いdartファイルのレイアウト確認〜

共同作業などでmain.dartがdartファイルでもUIを確認する。

①別classでウィジェットを作成


```dart
import 'package:flutter/material.dart';

class CustomButton extends StatelessWidget {
  final String label;
  final VoidCallback onPressed;

  const CustomButton({Key? key, required this.label, required this.onPressed})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: onPressed,
      child: Text(label),
      style: ElevatedButton.styleFrom(
        backgroundColor: Colors.blue, // ボタンの背景色を設定
        foregroundColor: Colors.white, // ボタンのテキスト（前景）色を設定
      ),
    );
  }
}
```

②ここからテスト用にmain関数を追加
```dart
// 以下、テスト用のmain関数
void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Custom Button Test'),
        ),
        body: Center(
          child: CustomButton(
            label: 'Test Me',
            onPressed: () {
              print('Test Button Pressed!');
            },
          ),
        ),
      ),
    ),
  );
}
```
実行結果

<img width="50%" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3743467/c529638c-3b92-1d75-ed06-a5811e4d7b05.png>


プログラム全体像
```dart
import 'package:flutter/material.dart';

class CustomButton extends StatelessWidget {
  final String label;
  final VoidCallback onPressed;

  const CustomButton({Key? key, required this.label, required this.onPressed})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: onPressed,
      child: Text(label),
      style: ElevatedButton.styleFrom(
        backgroundColor: Colors.blue, // ボタンの背景色を設定
        foregroundColor: Colors.white, // ボタンのテキスト（前景）色を設定
      ),
    );
  }
}

// 以下、テスト用のmain関数
void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Custom Button Test'),
        ),
        body: Center(
          child: CustomButton(
            label: 'Test Me',
            onPressed: () {
              print('Test Button Pressed!');
            },
          ),
        ),
      ),
    ),
  );
}
```
質的変数を利用した包括的な効果検証

※Qiita初心者でこれが初投稿なので温かく見守ってください

使用するのはJupyter Notebookです。
やる内容としては該当する質的変数が評価する項目にどのような影響を与えているかになります。
# 手順
## ライブラリの読み込み
必要なのは「Pandas」と「matplotlib」になります。
```Python3
import pandas as pd
import matplotlib.pyplot as plt
```
基本的にはExcelでデータは見れますが一応データの冒頭を出力します。
今回はCox比例ハザードモデルのライブラリであるlifelineというライブラリにある白血病のデータをCSVにしたものを読み込みます。
```Python3
df = pd.read_csv("leukemia.csv")
df.head()
```
## 質的変数と評価する変数の名前を定義
次にどの変数を用いて評価・効果検証をするかを決めます。
```Python3
columns = ["status", "sex", "Rx"]
y_name = "logWBC"
```
このとき。「columns」には質的変数を入れてください、また「y_name」には評価する変数の名前を入れてください。
補足ですが、
- Rx→投与(原因)
- status→効果(結果)
- sex→性別
- logWBC→白血球の数のlog

になります

## 効果検証のプログラム
ここからは効果検証を可視化する前準備を行います。
前項と前々項で使用するデータと変数を記載していますが、使用するデータセットと変数名を変えれば他のデータにも応用できます。
```Python3
ave = []
pos = []
dtr = []
lab = []
x = 0
for col in columns:
    values = list(set(df[col].values))
    tmp_ave = []
    tmp_pos = []
    tmp_dtr = []
    tmp_lab = []
    for val in values:
        tmp_df = df[df[col]==val]
        tmp_ave.append(tmp_df[y_name].mean())
        tmp_pos.append(x)
        tmp_dtr.append(tmp_df[y_name])
        tmp_lab.append(col+"_"+str(val))
        x = x + 1
    ave.append(tmp_ave)
    pos.append(tmp_pos)
    dtr.append(tmp_dtr)
    lab.append(tmp_lab)
```
ここで「tmp_lab」の追加について、質的変数には文字列を使っている場合や名義尺度(数値そのものに意味が無いカテゴリとしての数値)を使う場合があるため汎用的にするために「tmp_lab.append(col+"_"+str(val))」としています。

## 効果検証を出力
では実際に検証結果を出力してみましょう。
やり方としては質的変数の項目ごとに各リストに値(とデータフレーム)が入っていますのでfor文で長さを指定する時にこのように指定します。
また、平均値が例えはT検定などで有意に差があるかを比較する際に使いますのでマーカーを付けて出力しましょう。

```Python3
for i in range(len(ave)):
    plt.boxplot(dtr[i], positions=pos[i], labels=lab[i])
    plt.plot(pos[i], ave[i], marker="x")
plt.show()
```

この結果以下のようになります。
![effect_test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782889/685ed116-7d61-90de-3e0f-e7bf31df10a2.png)
ここからあとは各種変数について時間的関係から原因なのか結果なのかを考察して原因なら「○○が原因として見たときこういう効果に違いがあるのか」「結果○○な場合こういう違いがあるのか」などが可視化でき考察の材料になります。
なのでこの場合投与すると白血球数が上がる、男女での差は少ないということが分かります。また、結果白血病の人は白血球数が多いということが分かります。
ただし気を付けてほしいのがこの場合は一つの因子に対して分析しているだけで、複数の変数についてはまた違った分析手法を使います。
それと報告書や論文でこういったものを書くときはグラフを使うのも大事ですが、平均値の差やp値とサンプル数(できれば標準偏差も)など記載した方がより丁寧になると思います。