OmniAICreator/Qiita-1.07M huggingface dataset:
[過去記事]lambdaからAPI Keyが設定されたAPIを実行する

## 前提

今回のlambdaはNode.js 18.xを使います。また関数の作成など細かい方法は下記で記載しているので省略します！

要リンク用意（モジュール無し）

要リンク用意（モジュールあり）

また、API Keyが設定されているAPIは別のlambda関数を用意します。今回は下記の記事で作成したreturnHello関数をそのまま使ってみます！

https://qiita.com/miriwo/items/aee5fbe285a1338daac9

## 今回作るもの

![private__Online_Whiteboard_for_Visual_Collaboration-3-1024x528.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/e24a77c2-cb3e-13e8-947c-f239f412e315.png)

lambda関数2個とAPI Key付きのAPIをAPI Gateway作成します。

### lambda関数1つ目（returnHello関数）とAPI Gateway

「Hello from lambda!」の文字列とステータスコード200を返すreturnHello関数を作成します。
API Keyで認証設定したAPIをAPI Gatewayで作成し、returnHello関数のトリガーに設定します。

### lambda関数2つ目（getHello関数）

Node.jsのrequestモジュールを使ったreturnHello関数のエンドポイントにアクセスし、レスポンスをconsole.logに出力する処理を記載したgetHello関数を作成します。

## 準備

### lambda関数1つ目（returnHello関数）とAPI Gatewayの作成

下記の記事を参考にreturnHello関数の作成とAPI Keyを用いた認証を設定したAPIをAPI Gatewayで作成し、returnHello関数のトリガーに設定し、API Keyを確認後メモしておいてください！

要リンク用意（モジュールあり）

### lambda関数2つ目（getHello関数）の作成

lambdaの作成画面を開き下記の設定でgetHello関数を作成してみましょう！

- 関数の種別：一から作成
- 関数名：getHello
- ランタイム：Node.js 18.x
- アーキテクチャ：x86_64
- 実行ロール：基本的なLambdaアクセス権限で新しいロールを作成

上記の設定が完了したら「関数の作成」をクリックしましょう。

関数の作成後はテストイベント設定から下記の設定でテストイベントを作成しておきましょう。

- イベントアクションをテスト：新しいイベントを作成
- イベント名：test
- イベント共有の設定：プライベート
- テンプレート - オプション：hello-world

上記の設定が完了したら「保存」をクリックしましょう。

下記の記事の「追加モジュールの準備」から「レイヤーの作成」と「レイヤーの設定」を参考にrequestモジュールをレイヤーとして追加しましょう。追加したレイヤーをgetHello関数に設定しましょう。

index.mjsの内容を下記の内容に書き換えましょう！（コードの保存とデプロイをお忘れなく！）

```index.mjs
import request from 'request';
const url = 'getHello関数のAPI GatewayのエンドポイントURl';
const apiKey = 'getHello関数のAPI Key';

const method = 'GET';
const options = {
    url: url,
    method: method,
    headers: {
        'x-api-key': apiKey
    }
};

export const handler = (event) => {
    request(options, function (error, response, body) {
        console.log(body);
    });  
};
```

## 実行

準備は整いました！getHello関数の方のテストを実行して結果をみてみましょう！

はい！下記の様にreturnHello関数のエンドポイント経由で「Hello from Lambda!」の文字列を取得しログに出すことができました！

![getHello_-_Lambda-1024x299.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/fbc6a8e0-9f61-9bbb-6234-9809b2af5873.png)

本当にAPI Keyで認証されているか不安な場合は下記のようにgetHello関数のheadersを削除して保存 + デプロイを行いテストを実行してみましょう！

```index.mjs
import request from 'request';
const url = 'getHello関数のAPI GatewayのエンドポイントURl';
const apiKey = 'getHello関数のAPI Key';

const method = 'GET';
const options = {
    url: url,
    method: method,
};

export const handler = (event) => {
    request(options, function (error, response, body) {
        console.log(body);
    });  
};
```

{"message":"Forbidden"}がconsole.logで出ており、ちゃんとgetHello関数がreturnHello関数のエンドポイントにリクエストを送り、更にそのエンドポイントにAPI Keyの認証がかかっていることが分かりました！

## まとめ

今回はlambdaからAPI Keyの認証がかかったAPIを実行してみました！リクエストのヘッダー情報にキー名をx-api-keyとしてキーの値を渡してあげれば認証が突破できそうですね！ステキ！

## 参考文献

https://github.com/request/request#requestoptions-callback

https://github.com/request/request#custom-http-headers

https://github.com/request/request#requestoptions-callback
Informatica IDMCの始め方 接続定義の作成 ①Snowflake編

# はじめに
株式会社ジールの@Seiken-Saiです。
今回はInformatica社のSaaS製品であるIntelligent Data Management Cloud（以下IDMC）のデータ統合サービス「Cloud Data Integration（以下CDI）」で、Snowflakeに接続する手順をご紹介します。
IDMCでは、Informatica社より提供されるコネクタを使用して、簡単にSnowflakeに接続することが出来ます。
本手順の前提条件は下記です。
・ランタイム環境(SecureAgentサーバ)が構築されていること
・IDMCのDeveloper権限を持つユーザーが使用できること
・接続先のSnowflakeが準備されていること

# 接続定義の作成手順
### 1.IDMCポータルにログインし、管理者画面を選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166088/31c06933-b401-66f5-108e-5f89e1092339.png)

### 2.管理者画面の左ペインより、接続を選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166088/1fa3a263-07d4-b046-7767-f46ff44f2f11.png)

### 3.接続画面より、新しい接続を選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166088/3abaa202-76f2-cf43-0258-f4292d55638e.png)

### 4.接続の詳細に、必要な情報を入力します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166088/108ee25e-cc01-27e5-206c-87b3174c4d0b.png)

接続先のSnowflakeの情報を入力
【接続名】
　接続の名前を定義　※各接続名は組織内で一意である必要あり
【説明】
　任意
【タイプ】
　snowflake cloud Data Warehouse V2
【ランタイム環境】
　構築済のランタイム環境を選択
【Authentication】
　標準　※接続方式に応じて変更する
【Username】
　Snowflake接続時に使用するユーザーIDを入力
【Password】
　Snowflake接続時に使用するパスワードを入力
【Account】
　接続先のSnowflakeのURLを入力
【Warehouse】
　接続時に使用するWarehouseを入力
【Additional JDBC URL Parameters】
　接続時に追加するパラメータを入力


### 5.接続テストを実施します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166088/0e3c6b21-144e-35de-5634-88079156c16e.png)

接続に成功した場合、「この接続のテストに成功しました」と表示されます。
接続に成功したことを確認して保存します。
これで、IDMCでSnowflakeの接続定義の作成は完了です。

# おわりに
IDMCでは、Snowflakeに限らずOracle、Amazon Redshift、Amazon S3等の様々なデータベース/サービスと接続をすることが出来ます。また、複雑なETL処理もGUI上で作成することが出来ます。

株式会社ジールでは、「ITリテラシーがない」「初期費用がかけられない」「親切・丁寧な支援がほしい」「ノーコード・ローコードがよい」「運用・保守の手間をかけられない」などのお客様の声を受けて、オールインワン型データ活用プラットフォーム「ZEUSCloud」を月額利用料にてご提供しております。
ご興味がある方は是非下記のリンクをご覧ください：
https://www.zdh.co.jp/products-services/cloud-data/zeuscloud/?utm_source=qiita&utm_medium=referral&utm_campaign=qiita_zeuscloud_content-area
[過去記事]AWS lambda Node.jsの追加モジュールを使用せず他のAPIを実行してみる

## 今回作るもの

![private__Online_Whiteboard_for_Visual_Collaboration-1-1024x429.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/e93efa46-4472-86c2-880a-e3414044a6c9.png)

今回はlambdaを用いてQiitaのユーザー情報APIを実行しレスポンスをconsole.logで出力してみようと思います！

## 前提

今回の作業にはAWSのアカウントを持っていることを前提とします。また、lambda関数作成権限とIAMロール作成権限が必要です。

## 準備

### lambda

まずはブラウザからAWSにログインしコンソールを開き、lambdaのホームまで移動しましょう。
その後、左サイドバーの「関数」をクリックし、開いたページで「関数の作成」をクリックしましょう。

![関数_-_Lambda-1024x365.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/f6eaf6e9-d9bd-d478-0700-ebc765595ee8.png)

開いたページで下記の様に設定します。

関数の種類：一から作成
関数名：getQiitaUserForDefault
ランタイム：Node.js 18.x
アーキテクチャ：x86_64
実行ロール：基本的なLambdaアクセス権限で新しいロールを作成
詳細設定：特に設定しない。

設定内容を確認し「関数の作成」をクリックします。

![関数の作成_-_Lambda-1024x726.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/3d09dfee-051c-c8c5-247a-946150775941.png)

遷移先ページで「Test」をクリックします。

![getQiitaUserForDefault_-_Lambda-1024x577.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/88485a6d-9ae9-23e1-ca5e-c9c9d3a5970c.png)

開いたページで下記の様に設定します。

イベントアクションをテスト：新しいイベントを作成
イベント名：test
イベント共有の設定：プライベート
テンプレート - オプション：hello-world

設定内容を確認し「保存」をクリックします。

![getQiitaUserForDefault_-_Lambda-1-696x1024.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/2e36beb2-ab0c-f2a5-fbb3-6194814d3708.png)

コードソースの「index.mjs」をクリックし開きます。

![getQiitaUserForDefault_-_Lambda-2-1024x500.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/b18bd027-27c9-b636-5b9e-09e7e597366d.png)

表示されたindex.mjsの内容を一旦削除し下記のコードを記載します。

```index.mjs
import https from "https";

const url = "https://qiita.com/api/v2/users/miriwo";

export const handler = (event) => {
    https.get(url, (res) => {
        let body = '';
  
        res.on("data", function (d) {
            body += d;
        });
    
        res.on('end', function () {
            console.log(body);
        })
    })
    .on("error", (e) => {
        console.error(e);
    });
};
```

「cmd」+「s」でindex.mjsを上書き保存し「Deploy」をクリックして反映します。

![getQiitaUserForDefault_-_Lambda-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/41fd6046-5aa7-8d8e-755c-fe48d8d70cf8.png)

## 実行

それではテストを使って記載したコードを動かしてみましょう！
「Test」をクリックしてコードを動かします。

![getQiitaUserForDefault_-_Lambda-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/82da8f65-837b-082d-5249-50d8d55e10a2.png)

すると「Execution result」タブが増え、テスト結果が出力されます！その中にQiitaのAPIのレスポンスが表示されているはずです、、！これで外部のAPIを実行し、そのレスポンスを出力する事ができました！

![getQiitaUserForDefault_-_Lambda-5-1024x480.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/cc3a88ed-5a55-ae6c-38ce-177f8db8d3f6.png)

## まとめ

今回はlambdaのNode.jsから追加モジュール無しでAPIを実行してみました！非同期処理、、、独特、、、！

## 参考文献

https://qiita.com/miriwo/items/c1727868d9225f4e4c4a
【NewRelic】LookupTableにREST API経由でCSVファイルをアップロードする。

NewRelicのLookupTableという機能を使ってみました。

# LookupTableとは
* メトリックとは別でCSVをテーブルとして保持できる機能
* 上記をNRQL上でも表現可
* メトリックと組み合わせることで、管理しやすくなる。
    * ホスト名に日本語名称を付与
    * 「〇〇システム」という文言とホストやサービスを紐づけが出来る。
参考：公式サイトより
https://docs.newrelic.com/jp/docs/logs/ui-data/lookup-tables-ui/

# アップロード方法
ブラウザ(NewRelicのコンソール)からアップロードする方法とRESTAPIを使った方法の2つがあります。

インプットとなるCSVの値がそんなに変動しない場合は、手動アップロードで良いですが、そこそこの頻度で値が変わったり定期的にアップロードする仕組みの場合は後者のAPIを使った方法が良いです。
ということで後者のやり方を確認してみます。
※手動アップロードについては画面をポチポチ押すだけです。

# 環境
- Windows11(ただのPC
- Python（Ver3.11

# 準備
- Pythonのインストール
- API連携に必要な以下の情報の取得　※APIキーはNewRelicのコンソールで作成・取得可
    - アカウントID
    - APIキー
- アップロードするCSVファイル
    - 今回はそれっぽい架空のシステムの情報をまとめたCSVを用意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2774397/957aa9b2-decf-6811-9741-a5c80f192be1.png)

# スクリプト作成
- 以下サンプルです。CSVファイルをJSON変換して、CurlコマンドでLookupTableへPOSTしています。
- 文字コードですが、SJISだと文字化けしてしまうので注意しましょう（UTF-8なら日本語でも大丈夫
- エラーハンドリングとかはガン無視

```python:Try_NR-csvdataUpload-api.py
import subprocess
import json
import csv

# アカウントIDなど
endpoint = 'https://nrql-lookup.service.newrelic.com/v1/accounts'
account_id = '<NewRelicアカウントID>'
table_name = '<任意のテーブル名>'
api_key = '<APIキー>'
# CSVファイルのパス　　↓対象のCSVファイルを指定
csv_file = r'C:\temp\fictional_systems_and_servers_japanese.csv'
# CSVファイルからデータを読み取ってJSON形式に変換する
def csv_to_json(csv_file):
    data = {
        "table": {
            "headers": [],
            "rows": []
        },
        "description": "CSV data upload"
    }
    with open(csv_file, 'r', newline='', encoding='utf-8') as file:
        reader = csv.reader(file)
        data["table"]["headers"] = next(reader)  # ヘッダーを取得
        for row in reader:
            data["table"]["rows"].append(row)
    return data

# CSVからデータを読み取ってJSONに変換
data = csv_to_json(csv_file)

# Curlコマンドを構築
curl_command = [
    'curl',
    '-X', 'POST',
    '-H', 'Content-Type: application/json',
    '-H', f'Api-Key: {api_key}',
    '-d', f'{json.dumps(data)}',
    f'{endpoint}/{account_id}/{table_name}'
]

# Curlコマンドを実行
subprocess.run(curl_command)
```

# 結果
- 上記スクリプトを実行してみました。（モザイク多めですいません・・
テーブル名は「Testupload」という名前にしてみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2774397/dc22eef6-bf12-19a2-aae7-5dc0e76f007f.png)


- NewRelicにサインインして、確認します。LookupTableは「Logs」の中にあります。<br>「testupload」というテーブルがいますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2774397/7e658181-0036-c532-532d-9640b4cd15bc.png)

- NRQLで「testupload」の内容を確認してみます。Lookuptableを参照する場合は、「lookup」を使用します。
`FROM lookup(testupload) SELECT *`
CSVの内容が連携されていることが確認出来ました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2774397/c4f23f5a-1775-e7b1-1568-88328262038a.png)

# 参考：NRQLで使ってみる。
- 検証用で連携させていたEC2(nr-test)の情報とCSVの情報と紐づけてみました。
- JOINを使ってサブクエリとして使うと、上手い事表示されます。
https://docs.newrelic.com/jp/docs/nrql/using-nrql/lookups/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2774397/067cc89f-ef0b-e53c-3ca0-c3be8687af76.png)
Tips to Excel Your Salesforce Pardot Implementation

 Pardot is a popular Software-as-a-Service (Saas) platform powered by Salesforce that offers marketing solutions, email automation, and lead management for B2B enterprises in this digital era. It is one of the most trusted B2B marketing portals, which is usually used by the marketing and sales team to close deals quickly. It defines the right path for you so that you reach the right lead on time.

Built on the world’s #1 CRM, Pardot is the best marketing solution for its users that reduces the burden of Sales and Service Reps. Powered with AI, Pardot works smartly by automating triggered conversations and replies to the concerned leads. According to the reports, businesses have increased sales growth by 34% and 40% in their marketing after the Salesforce Pardot Implementation.
![Tips-to-Excel-Your-Salesforce-Pardot-Implementation-Blog.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3691603/38809826-f697-d042-7c45-7d173ccaeabb.jpeg)

 
Features offered by Salesforce Pardot 
- An Effective Way of Lead Nurturing
- Build personalized Email Marketing Templates
- Smooth Sales Alignment with approved mini-campaigns
- Helpful ROI Reporting
- Powered by Artificial Intelligence
- Smarter Lead Generation

Sometimes it becomes a challenge for the B2B marketer to reach both buyers and the internal team at the same time when you are aware that you're operating across such a wide range of individuals. Use these below-mentioned tips to direct your marketing efforts:

1) Grow faster with smarter engagement: Pardot being a powerful platform helps its users to get real-time sales alerts, speed the lead follow-ups, and useful data at their fingertips facilitating you to connect and close leads on time.

2) High-quality Lead generation: Running targeted marketing campaigns with custom landing pages and forms keeps your sales pipeline completely stocked with a constant flow of high-quality leads.

3) Customer Engagement: Build custom engagement campaigns that adapt to each customer’s buying signals and move them through the pipeline faster.

4) Discover the true ROI: Easily monitor the campaign performance to maximize marketing efforts that drive more revenue with actionable reporting.

Conclusion
Salesforce Pardot Integration can help you bring the best out of your marketing campaigns. It combines your marketing efforts and delivers optimum results. Its AI-powered features enable businesses to ease their marketing and sales processes, contributing to increased revenue and growth.

However, utilizing its full potential demands experts’ guidance.

Atocloud is a renowned Salesforce Development Company offering top-notch Salesforce Pardot Services to elevate your marketing purposes. We have a team of expert Salesforce Pardot Consultants who are nothing but a true combination of diligence and dedication so that they can deliver services flawlessly. Our sole motive is to satisfy our customers consistently. 

Contact us to hire Salesforce Pardot Experts for your enterprise!

Reference Link : https://www.atocloud.com/blog/excel-your-salesforce-pardot-implementation
PowerBIとRedshiftを接続（インターネット経由）

# 1.Redshiftでの設定

## 1.1 ユーザー・グループの設定

まずは、PowerBIでアクセスする際のユーザー等を作成していきます。

以下のコードはスーパーユーザーでしかできないので注意が必要です。

### 全てのテーブルにアクセスができるユーザー・グループ

```sql
CREATE GROUP powerbi_group_all;

GRANT SELECT ON ALL TABLE TO GROUP powerbi_group_all;

CREATE USER powerbi_all PASSWORD XXX in group powerbi_group_all
```

### トランザクションテーブルにアクセスができるユーザー・グループ

```sql
CREATE GROUP powerbi_group_transactions;

GRANT SELECT ON TABLE transactions TO GROUP powerbi_group_transactions;

CREATE USER powerbi_transactions PASSWORD XXXX in group powerbi_group_transactions
```

これらのユーザー名とパスワードを使って、PowerBIでアクセスしていきます

ただ、このままでは
PowerBIを開いてもRedshiftにアクセスはできません。

## 1.2　インバウンドルール・パブリックアクセスの設定

### デフォルトではパブリックアクセスは禁止されています。
当たり前ではありますが、パブリックアクセスを許可する必要性があります。

以下のRedshiftの設定からパブリックアクセスを許可してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526914/7c40fed2-7859-e870-fc00-fc1c228fc107.png)

RedshiftのVPCにもインバウンドルールとして、許可しておく必要がありますので、設定してください
接続したいIPアドレスをソースに記載してください。
もしテストでやりたい場合は、
0.0.0.0/0でフルアクセスしてください。本番では当たり前ですがしっかりと設定するように

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526914/a56beb42-0a4f-1e18-3208-a9ce4cedb5db.png)


# 2.PowerBI上での設定
データ取得から、詳細に移動していただいて、Redshiftを探してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526914/88604d30-8f4a-7baa-afed-7ac1eea4e0e1.png)

Serverはクラスターの上部に記載されているものを記載。データベースは任意のデータベースです
次にユーザー名とパスワード名が聞かれるので、上記で記載したものを追加してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526914/43b05ac0-647b-f8c6-f500-4d7ce4c698ba.png)



これによって、ネットワーク間でRedshiftとPowerBIを接続させることができました。

# 3.番外編　SCHEMA
ユーザー(グループ)によって、テーブルのアクセスをかけることは非常に重要です。

また、```schema```を使うことで、さらに制限をかけることができます。

例えば、
```
GRANT USEAGE ON SCHEMA masked TO GROUP グループ名
GRANT SELECT ON ALL TABLES IN SCHEMA masked TO GROUP グループ名

```
これらを行うことで、機密なデータをマスクすることができます。
例えば、ユーザーのメールアドレスなどです。

## 適切なスキーマ設定なども行っていきましょう。

それでは。
DyLoRA: 動的ランク調整でモデルチューニングが7倍速く！

※ このページは「DyLoRA: Parameter-Efficient Tuning of Pretrained Models using Dynamic Search-Free Low Rank Adaptation」の要約になります。

## このページでわかること
- DyLoRAは、事前学習済みモデルの効率的なチューニングを実現するために、異なるランクサイズで動的に学習する技術
- 従来のLoRAのランクサイズ選択と固定の問題を解決し、トレーニング時間を大幅に短縮しながら広範なランクサイズで一貫した性能を提供
- 実験結果により、DyLoRAはLoRAよりも最大7倍速く、性能を損なわずに動作することを確認

## 対象読者
- 事前学習済みモデルの効率的なチューニング方法を探している人
- モデルのサイズやチューニングのコストを最小化しつつ高性能を維持する技術に関心がある人

## 従来手法の問題点
1. **事前学習済みモデルのファインチューニングのコストとリソースの負担**:
   - 事前学習済みモデルのサイズが増大するにつれて、ファインチューニングにかかるコストとリソースの負担が増加している

2. **LoRA（Low-Rank Adaptation）のランクサイズ選択の難しさ**:
   - LoRAはパラメータ効率の高いチューニング技術ですが、ランクサイズの選択が固定であり、トレーニング後に変更できないという問題がある
   - 最適なランクサイズを見つけるためには、広範なランクサイズを試行錯誤する必要があり、これには多大な時間と労力がかかる

3. **LoRAの固定ランクによる制約**:
   - LoRAは特定のランクサイズに対してのみ最適化されているため、異なるランクサイズでの適応が難しいという問題がある
   - これにより、異なるデバイスやタスクに対して柔軟に対応できないという制約がある

## DyLoRA
### DyLoRA とは？
DyLoRA（Dynamic Low-Rank Adaptation）は、事前学習済みモデルの効率的なファインチューニングを目的とした技術です。DyLoRAは、既存のLoRA（Low-Rank Adaptation）の問題点を解決するために開発されました。具体的には、DyLoRAは異なるランクサイズでモデルを動的に適応させることで、固定ランクのLoRAが抱える制約を克服します。

### DyLoRA のメリット
1. **ランクサイズの動的適応**:
   - DyLoRAは異なるランクサイズでモデルをトレーニングし、ランクサイズを動的に変更することができます。これにより、広範なランクサイズに対して一貫した性能を発揮
   
2. **検索コストの削減**:
   - DyLoRAは最適なランクサイズを見つけるための大規模な検索を必要としません。トレーニングの際にランクサイズを動的に調整するため、時間とリソースを大幅に節約
   
3. **一貫した高性能**:
   - DyLoRAは広い範囲のランクサイズにおいてLoRAと同等以上の性能を発揮します。トレーニング時間も短縮され、リソース効率が高い

### DyLoRA の手順
1. **ランクサイズのサンプリング**:
   - トレーニングの各ステップで、事前定義されたランダム分布からランクサイズ \( b \) をサンプリングする
   
2. **行列のトランケーション**:
   - サンプリングされたランクサイズに基づいて、LoRAのアッププロジェクション行列 \( W_{up} \) とダウンプロジェクション行列 \( W_{dw} \) をトランケート (一部を切り詰める) する
   
3. **フォワードパス**:
   - トランケートされた行列を用いて、モデルの出力を計算する
   
4. **ロス計算とバックワードパス**:
   - 特定のランクサイズに対してロスを計算し、対応する行列の部分のみを更新します。これにより、効率的なトレーニングが可能になる

### DyLoRA の性能
1. **トレーニング時間の短縮**:
   - DyLoRAは従来のLoRAと比較して、トレーニング時間を4倍から7倍短縮できる
   
2. **一貫した性能**:
   - DyLoRAは、GLUEベンチマークや各種自然言語生成タスク（E2E、DART、WebNLG）において、LoRAと同等以上の性能を示す
   
3. **柔軟性**:
   - DyLoRAはランクサイズを動的に変更できるため、異なるデバイスやタスクに対して柔軟に対応可能

## まとめ
以上がDyLoRAの要約でした。私自身 LoRA を使うことがあったのですが、ハイパーパラメータの調整に苦労したので、DyLoRA のように動的に調整できるのは嬉しいですね。

おわり。
RBACを有効化したKong Gatewayのメトリクス取得方法

以前[Kong Prometheus Pluginで非Promethus対応のサービスのメトリクスを取得する](https://qiita.com/ipppppei/items/3f1abc938a3bc2d4a541#kong-promethues-plugin)という記事でKong Gateway利用時にGatewayを通過する通信のメトリクスの取得方法を確認したが、RBAC化した場合上手く動かなくて少しハマったので対応策をメモに残す。

## 問題の背景
Kong GatewayでPrometheus用のメトリクスを取得しようと思った場合、Admin APIの`/metrics`を叩くと公式のドキュメントには[記載がある](https://docs.konghq.com/gateway/latest/production/monitoring/prometheus/)。
ただ、RBACを有効化した状態だと認証が通らず以下のようなエラーとなる。
```sh
$ curl https://kong.${MYHOST}/api/metrics -k
{"message":"Invalid credentials. Token or User credentials required"}
```
認証を突破するにはヘッダに`"kong-admin-token:<AdminのPassword>"`を渡せば突破できる。
```sh
$ curl https://kong.${MYHOST}/api/metrics -k -H kong-admin-token:kong
- # TYPE kong_bandwidth_bytes counter
：（省略）
```
ただ、厄介なのがこのヘッダの形式は（おそらく）Prometheusに直接渡す事が出来ない。
少なくともPrometheus Operatorの`kind: ScrapeConfig`では渡せる認証はBasic認証かAuthenticationヘッダの指定のみとなっている。
そのため、Admin APIが期待するヘッダ(`kong-admin-token`)をPrometheus内に設定することが出来ない。

## 対応策
認証なしで`/metrics`にアクセスする方法があるのでこれを使う。
Kong Gateway内には[Status API](https://docs.konghq.com/gateway/latest/reference/configuration/#status_listen)と呼ばれるヘルスチェック用のAPIが用意されている。
公式ドキュメントには[この辺](https://docs.konghq.com/gateway/latest/production/monitoring/healthcheck-probes/)に記載がある。
これには`/status`しか書いていないが、実は`/metrics`でメトリクスも取得することが出来る。
なのでこれを使って取得してみる。
なお、Kong Gatewayの[HelmChartの説明](https://github.com/Kong/charts/tree/main/charts/kong#kong-service-parameters)には明確に`Service`や`Ingress`を提供しないと記載されているため、手動で作成する。
```yaml
cat <<EOF > ./status-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: kong-status
  namespace: kong
spec:
  ports:
  - name: status
    port: 8100
    protocol: TCP
  selector:
    app.kubernetes.io/component: app
    app.kubernetes.io/name: kong
EOF
kubectl apply -f ./status-svc.yaml
```
次にPrometheusとKong Gatewayが異なるクラスタに存在するなどの場合は`Ingress`も作成する。（ここでは省略する）
Prometheus Operatorを使っている場合、`ScrapeConfig`を作成してスクレイピングを行う。
```yaml
cat <<EOF > ./scraping.yaml
apiVersion: monitoring.coreos.com/v1alpha1
kind: ScrapeConfig
metadata:
  labels:
    release: prometheus-stack
  name: scraping-kong
  namespace: kong
spec:
  metricsPath: /metrics
  scheme: HTTP
  staticConfigs:
  - labels:
      job: kong-gateway
    targets:
    - kong-status.kong.svc:8100
EOF
kubectl apply -f ./scraping.yaml
```
変更適用後、ScrapeInterval(デフォルトで30秒)待つと以下のようにRBACが有効な環境でも無事メトリクスを見に行くことが出来た。
![20240527150525.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/82e4ac6d-3907-6860-b356-478c86110342.png)

なお、今回作成した`Service`はHelmChartと別管理になるため、デプロイやアップグレード時の修正などライフサイクル管理を行う際は取りこぼさないよう気をつける必要がある。

※追記
公式の説明は[ここ](https://docs.konghq.com/hub/kong-inc/prometheus/#accessing-the-metrics)にある。
色々試行錯誤し、記事化した後に公式の説明があるのに気がついた。。。
Javaの`Integer`クラスのキャッシュ機構とプリミティブ型の比較について

## はじめに

Javaプログラミングにおいて、`Integer`クラスのキャッシュ機構とプリミティブ型の比較は、パフォーマンスとメモリ効率に大きな影響を与える重要な概念です。本記事では、`Integer`クラスのキャッシュ機構、オートボクシング、プリミティブ型とラッパークラスの比較について見ていきます。

## コード例

以下のコードを例に、それぞれの動作を説明していきます。

```java
class Main {
    public static void main(String[] args) {
        Integer a = 128;
        Integer b = 128;
        Integer c = 127;
        Integer d = 127;
        int e = 127;
        int f = 127;

        System.out.println(a == b); // false
        System.out.println(a.equals(b)); // true
        System.out.println(c == d); // true
        System.out.println(c.equals(d)); // true
        System.out.println(e == f); // true
        // System.out.println(e.equals(f)); // プリミティブには使えません
    }
}
```

## 詳細解説

### 1. オブジェクト参照の比較

```java
System.out.println(a == b); // false
```

- `a`と`b`はそれぞれ`128`という値を持つ`Integer`オブジェクトです。
- しかし、`128`はキャッシュ範囲（`-128`から`127`）の外にあるため、`a`と`b`は異なるオブジェクトになります。
- `==`演算子はオブジェクトの参照を比較するため、異なるオブジェクトを指す`a`と`b`の比較結果は`false`となります。

### 2. オブジェクトの値の比較

```java
System.out.println(a.equals(b)); // true
```

- `equals`メソッドはオブジェクトの値を比較します。
- `a`と`b`はどちらも`128`という値を持つため、比較結果は`true`となります。

### 3. キャッシュ範囲内のオブジェクト参照の比較

```java
System.out.println(c == d); // true
```

- `c`と`d`はそれぞれ`127`という値を持つ`Integer`オブジェクトで、`127`はキャッシュ範囲内の値です。
- キャッシュ範囲内の値は同じオブジェクトが再利用されるため、`c`と`d`は同じオブジェクトを指します。
- `==`演算子はオブジェクトの参照を比較するため、同じオブジェクトを指す`c`と`d`の比較結果は`true`となります。

### 4. キャッシュ範囲内のオブジェクトの値の比較

```java
System.out.println(c.equals(d)); // true
```

- `equals`メソッドはオブジェクトの値を比較します。
- `c`と`d`はどちらも`127`という値を持つため、比較結果は`true`となります。

### 5. プリミティブ型の比較

```java
System.out.println(e == f); // true
```

- `e`と`f`はプリミティブ型の`int`で、どちらも`127`という値を持ちます。
- プリミティブ型の比較では、`==`演算子は値そのものを比較するため、比較結果は`true`となります。

### 6. プリミティブ型に対する`equals`メソッドの使用

```java
// System.out.println(e.equals(f)); // プリミティブには使えません
```

- プリミティブ型にはメソッドがないため、`equals`メソッドを使用することはできません。

## キャッシュ機構の詳細

Javaの`Integer`クラスには、特定の範囲内の整数値をキャッシュして再利用する機構があります。デフォルトで、このキャッシュ範囲は`-128`から`127`です。この範囲内の整数は頻繁に使用されるため、キャッシュによってメモリ使用量を削減し、パフォーマンスを向上させます。

キャッシュ範囲内の整数が再利用されるため、同じ値の`Integer`オブジェクトは同一のインスタンスを指します。しかし、キャッシュ範囲外の整数は新たにインスタンス化されるため、異なるオブジェクトとなります。

## オートボクシングとアンボクシング

Javaでは、プリミティブ型と対応するラッパークラスの間で自動的に変換が行われます。この機能をオートボクシング（プリミティブ型からオブジェクトへの変換）およびアンボクシング（オブジェクトからプリミティブ型への変換）と呼びます。

例:
```java
Integer boxed = 127; // オートボクシング
int unboxed = boxed; // アンボクシング
```

## まとめ

Javaの`Integer`クラスのキャッシュ機構とプリミティブ型の比較は、メモリ効率とパフォーマンスに重要な影響を与えます。キャッシュ範囲内の整数は同じオブジェクトを再利用し、範囲外の整数は新しいオブジェクトが生成されます。また、オートボクシングとアンボクシングにより、プリミティブ型とラッパークラスの間で自動的に変換が行われます。
NGSデータのマッピングとデータ処理のための汎用スクリプト


# NGSデータのマッピングとデータ処理のための汎用スクリプト

次世代シーケンシング（NGS）データの処理は、ゲノム解析の重要なステップです。ここでは、Minimap2とSAMtoolsを使用してNGSデータのマッピングとデータ処理を行うための汎用スクリプトを紹介します。

## 背景

NGS技術は、短時間で大量のデータを生成するため、データ処理の効率化が求められます。Minimap2は、高速かつ正確なリードマッピングツールとして広く使用されており、SAMtoolsはSAM/BAMファイルの操作に便利なツールです。本スクリプトでは、これらのツールを組み合わせて、効率的なデータ処理を実現します。

## 使用ツール

本スクリプトでは以下のツールを使用します：

1. **Minimap2** - 高速かつ正確なリードマッピングツール
2. **SAMtools** - SAM/BAMファイルの操作ツール

これらのツールは、以下のコマンドでConda経由でインストールできます：

```bash
$ conda create -n mapping_env
$ conda activate mapping_env
$ conda install -c bioconda minimap2 samtools
```

## スクリプト

以下に、Minimap2とSAMtoolsを使用した汎用スクリプトを示します。

```bash
#!/bin/bash

# ログファイルの設定
LOGFILE="path/to/mapping.log"

# Minimap2を使用したマッピングとSAMtoolsの処理をバックグラウンドで実行し、ログファイルに記録
{
    echo "Indexing reference genome with minimap2"
    minimap2 -d path/to/consensus.mmi path/to/consensus.fasta

    echo "Mapping reads with minimap2"
    minimap2 -ax sr path/to/consensus.mmi path/to/sample_R1.fastq.gz path/to/sample_R2.fastq.gz > path/to/mapped.sam

    echo "Converting SAM to BAM"
    samtools view -S -b path/to/mapped.sam > path/to/mapped.bam

    echo "Sorting and indexing BAM"
    samtools sort path/to/mapped.bam -o path/to/sorted.bam
    samtools index path/to/sorted.bam

    echo "Getting read counts for BAM"
    samtools idxstats path/to/sorted.bam > path/to/idxstats.txt

    echo "All tasks completed"
} &> $LOGFILE &

echo "Script is running in the background. Check the log file for details: $LOGFILE"
```

## スクリプトの簡単な説明と使用方法

このスクリプトは、以下の手順でNGSデータのマッピングとデータ処理を行います：

1. 参照ゲノムのインデックス作成（Minimap2）
2. リードデータの参照ゲノムへのマッピング（Minimap2）
3. SAMファイルをBAMファイルに変換（SAMtools）
4. BAMファイルのソートとインデックス作成（SAMtools）
5. BAMファイルのリードカウント取得（SAMtools）

スクリプトを実行するには、必要なファイルパスを適切に置き換えた後、以下のコマンドを実行します：

```bash
$ bash path/to/run_mapping.sh
```

スクリプトはバックグラウンドで実行され、進捗状況はログファイルに記録されます。

## 出力ファイルの例と見方

スクリプトの実行後、以下の出力ファイルが生成されます：

- `mapped.sam` - マッピング結果のSAMファイル
- `mapped.bam` - SAMファイルをBAM形式に変換したもの
- `sorted.bam` - ソートおよびインデックス付けされたBAMファイル
- `idxstats.txt` - BAMファイルのリードカウント情報

例えば、`idxstats.txt` の内容は以下のようになります：

```
seq1    50000   12345   6789
seq2    60000   23456   7890
...
```

各行は以下の情報を含みます：

- `seq1` - シーケンス名
- `50000` - シーケンスの長さ
- `12345` - マッピングされたリード数
- `6789` - マッピングされなかったリード数

このようにして、マッピングおよびデータ処理結果を詳細に確認することができます。

## まとめ

本記事では、NGSデータのマッピングとデータ処理のための汎用スクリプトを紹介しました。このスクリプトを利用することで、Minimap2とSAMtoolsを効果的に活用し、効率的なデータ解析が可能となります。是非、あなたのプロジェクトにも活用してみてください。
react

```react
<Controller
  name={conditionIds.hoge}
  control={control}
  render={({ field }) => (
    <TextField
      {...field}
      label={conditionLabels.hoge}
      value={getValues(conditionIds.hoge)?.toString()}
      onChange={(event) => setValue(conditionIds.hoge, event.target.value)}
      maxLength={100}
    />
  )}
/>
```
このコードがフォームの送信を引き起こす仕組みは、HTMLのデフォルトの動作に基づいています。HTMLフォームでは、テキストフィールド内でEnterキーを押下すると、そのフォームが自動的に送信されるようになっています。これは、<input>や<button>タグなどのフォーム要素が一つの<form>タグ内にある場合、特にtype="submit"のボタンがなくても、Enterキーによる送信が可能です。

Reactの<TextField>コンポーネントは、内部的には<input>タグをレンダリングしており、そのため同じ動作が適用されます。したがって、ユーザーが<TextField>内でEnterキーを押すと、ブラウザはその親フォーム要素のonSubmitイベントをトリガーします。

react-hook-formを使用している場合、Controllerコンポーネントは<TextField>をラップしており、onSubmitイベントはuseFormフックで定義されたhandleSubmit関数によって処理されます。これにより、フォームのデータが検証され、指定された送信処理が実行されます。

以下のような構造で、<form>タグとhandleSubmit関数が定義されていると仮定します：
```react
<form onSubmit={handleSubmit(onSubmit)}>
  <Controller
    name={conditionIds.hoge}
    control={control}
    render={({ field }) => (
      <TextField
        {...field}
        label={conditionLabels.hoge}
        maxLength={100}
      />
    )}
  />
  {/* 他のフォーム要素 */}
</form>
```
この場合、<TextField>でEnterキーを押すと、handleSubmit関数が呼び出され、フォームの送信処理が行われます。これが、テキストボックスでEnterキーを押下することで内容がフォームで送信される仕組みです。

Reactでは、TextFieldコンポーネントは最終的に<input>タグをレンダリングします。<input>タグはtype="text"属性を持っている場合、フォーム内でEnterキーが押されたときにフォーム送信をトリガーするというHTMLの標準仕様に従います。

react-hook-formのControllerコンポーネントを使用している場合、fieldオブジェクトのプロパティとしてonChangeハンドラが提供されています。そのため、TextFieldに{...field}を展開することで、onChangeを含む必要なすべてのイベントハンドラが自動的に適用されます。これにより、ユーザーがTextFieldでEnterキーを押下すると、onChangeイベントが発火し、それがフォームのonSubmitイベントをトリガーすることになります。

この挙動は、TextFieldにカスタムのonChangeハンドラを設定していなくても発生します。react-hook-formはonSubmitイベントを処理するためのhandleSubmit関数を提供しており、これによりフォームの送信時にバリデーションやデータの処理が行われます。したがって、TextFieldでEnterキーを押下すると、handleSubmit関数が呼び出され、フォームが送信される流れになります。このプロセスは、<form>要素のonSubmitプロパティにhandleSubmit関数が割り当てられていることを前提としています。
ファイルシステムの整合性保持

# 整合性がなくなる
システムを運用していると、ファイルシステムの内容に不整合が生じることがあります。
典型的な例が、ファイルシステムのデータをストレージに読み書きしている最中に、システムの電源が強制的に落ちるような場合です。
...
これら一連の処理はプロセスから見ると、一つにまとまった不可分の処理（アトミック）になっています。
...
不整合をファイルシステムが検出すると、マウント時に検出した場合は、```ファイルシステムをマウントできなくなった```り、読み出し専用モードで再マウントされたり、```システムがパニック```にしたりします。

### 気づき
ファイルシステムの読み書きがアトミック処理になっているからファイルシステム側が混乱するのか。

# ジャーナリングによる不整合防止
ファイルシステム内に```ジャーナル領域という特殊なメタデータ領域```を用意します。
* 更新に必要なアトミックな処理の一覧を一旦```ジャーナル領域```に書き出す。この一覧を```ジャーナルログ```と呼ぶ。
* ジャーナル領域の内容に基づいて、実際にファイルシステムの内容を更新する。

# 気づき
それ以降の図を見るとジャーナル領域とは更新処理の予定表なものなのか。
それでジャーナル領域に更新予定を書き込んでいる間に電源が落ちるとそのジャーナル領域を破棄する。
更新処理最中に電源が落ちると再起動後にジャーナル領域を再び読み込み完了させる。

# コピーオンライトによる不整合の防止
### ファイルシステムの格納方法
ext4やXFSなどは、一旦ストレージデバイス上にファイルのデータを書き込んだら、その後ファイルを更新すると、ストレージデバイス上の```同じ位置にデータを書き込み```ます。
### コピーオンライトによるファイル更新
ファイルにデータを書き込んだ後は、更新するごとに```別の場所にデータを書き込み```ます。

### 気づき
別の位置にデータを書き込むことによって電源が落ちても作成されたファイルを削除するだけいいのか。

# バックアップをとっておく
ファイルシステム不整合の発生は減らせますが、完全に無くすのは困難です。なぜならファイルシステムにバグがあれば依然同じ問題が発生しますし、ハードウェアに問題がある場合も問題が起こりうるからです。
　ではどうすればいいかというと、一般的には、ファイルシステムの```定期的なバックアップファイル```を取っておき、ファイルシステム不整合が発生した時には、```最後にバックアップをとった時点の状態に復元```することが対策となります。

# 出典
https://gihyo.jp/book/2022/978-4-297-13148-7

# 感想
ファイルシステムの方で更新時の問題を解決してくれるが、バックアップをとっておくことが重要だ。
複数バージョンの Go

## Go Toolchains

Go には [Go Toolchains](https://go.dev/doc/toolchain) という機能があって、自分で複数バージョンの Go をインストールする必要はないかも。

* デフォルトの Go が go.mod の指定よりも新しい時、デフォルトの Go が動く。
* デフォルトの Go が go.mod の指定よりも古い時、go.mod に指定された Go をインストールして使う。

ここで面白い事に、新しい Go がインストールされてもデフォルトの Go は勝手に新しい物と入れ替わらない。go.mod の記述が新しくて新しい Go がインストールされた後でも go コマンドは古いままだ。

go.mod の指定を無視して強制的に切り替えるには GOTOOLCHAIN 環境変数を使う。例えば。

```shell
$ go version
go version go1.22.3 darwin/arm64

$ GOTOOLCHAIN=go1.20.14 go version
go: downloading go1.20.14 (darwin/arm64)
go version go1.20.14 darwin/arm64
```

あと、何に使うのかわからないが `GOTOOLCHAIN=バージョン+auto` という設定もある。auto とはデフォルトのバージョン自動設定の動作なのだが、バージョン+auto とすると自動設定を行う Go のバージョンを指定できる。例えば go.mod の指定が `go 1.22` の時 `GOTOOLCHAIN=go1.21.4+auto` を指定すると、go1.21.4 の時代の自動設定にはバグがあるので以下のようにエラーになる。

```shell
GOTOOLCHAIN=go1.21.4+auto go version
go: downloading go1.22 (darwin/arm64)
go: download go1.22 for darwin/arm64: toolchain not available
```

## 以下古いメモ

これも何度も忘れるのでメモする。

* Go のインストーラを使うと、Go は `/usr/local/go` にインストールされる。
    * あとで別のバージョンのインストーラを使うと、`/usr/local/go` は削除される。
* go install コマンドでインストールすると、Go は `~/go/bin` と `~/sdk` にインストールされる。

例えば 1.21.4 を使いたい時はこうする。なぜ二度コマンドが必要なのかは不明。

```shell
go install golang.org/dl/go1.21.4@latest
go1.21.4 download
```

.zprofile など設定ファイルの中で alias をつけると便利。

```
export PATH="$PATH:$HOME/go/bin"
alias go="go1.21.4"
```

Go では後方互換性が保証されているので複数の Go を入れる動機は無さそうだが、プロジェクトで使う Go のバージョンが決まっている場合にうっかり新しい機能を入れたくない場合にやっぱり複数の Go があると便利だと思う。

* 参考
    * [Managing Go installations - The Go Programming Language](https://go.dev/doc/manage-install)
    * [Backward Compatibility, Go 1.21, and Go 2 - The Go Programming Language](https://go.dev/blog/compat)
【GitHub Copilot Workspace】日本語を表示させるプロンプト

# Specificationを日本語にするプロンプト
GitHub Issueのcommentに下記を追加しておく
```md
- プロンプトは日本語で返してください
```
or
```md
# MUST
- 全ての返答は日本語で返してください
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188242/22b28fd0-44f9-6925-8c58-fb7ab070b629.png)

## 結果
Specificationが日本語で表示される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188242/0d1dc0d4-05f8-bafc-5567-f5b8b28d963a.png)

しかし、Planには適応されない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188242/9b64a599-cedd-ea29-9f69-cdad693f977a.png)

# プルリクを日本語にするプロンプト
GitHub Issueのcommentに下記を追加しておく
```md
- Pull RequestタイトルとPull Requestの本文を日本語で記述すること
```

![スクリーンショット 2024-05-28 2.51.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188242/676ff813-5aba-0495-af3d-a0b75fe0d11d.png)

## 結果
プルリクのタイトルと本文中の説明を日本語で記述してくれる

![スクリーンショット 2024-05-28 2.53.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188242/369563e9-0657-58cf-0806-725529f93d9a.png)
Python3ではじめるシステムトレード：確率変数と独立

長い間、正確に理解できていなかったので、メモとして残しておきます。

確率変数 $ X $ が正規分布 $ N(\mu, \sigma_X^2) $ に従う場合、その確率密度関数（PDF）は次の式で表されます：

$$
f(x) = \frac{1}{\sqrt{2\pi \sigma_X^2}} e^{-\frac{(x-\mu_X)^2}{2\sigma_X^2}}
$$

ここで、
- $ \mu_X $ は分布の平均（期待値）です。
- $ \sigma_X $ は標準偏差で、$ \sigma_X^2 $ は分布の分散です。

この関数は $ x $ の値に対して確率密度を与え、$ \mu_X $ を中心に対称なベル形のカーブを描きます。

この際に確率変数$X$は独立です。

どうように、確率変数 $ Y $ が正規分布 $ N(\mu, \sigma_X^2) $ に従う場合、その確率密度関数（PDF）は次の式で表されます：

$$
f(y) = \frac{1}{\sqrt{2\pi \sigma_Y^2}} e^{-\frac{(y-\mu_Y)^2}{2\sigma_Y^2}}
$$

ここで、
- $ \mu_Y $ は分布の平均（期待値）です。
- $ \sigma_Y $ は標準偏差で、$ \sigma_Y^2 $ は分布の分散です。

この関数は $ Y $ の値に対して確率密度を与え、$ \mu_Y $ を中心に対称なベル形のカーブを描きます。

この際に確率変数$Y$は独立です。

この場合の同時確率密度関数は

確率変数 $ X $ と $ Y $ がそれぞれ独立して正規分布 $ N(\mu_X, \sigma_X^2) $ と $ N(\mu_Y, \sigma_Y^2) $ に従う場合、それぞれの確率密度関数は以下のようになります：

$$
f_X(x) = \frac{1}{\sqrt{2\pi \sigma_X^2}} e^{-\frac{(x-\mu_X)^2}{2\sigma_X^2}}
$$

$$
f_Y(y) = \frac{1}{\sqrt{2\pi \sigma_Y^2}} e^{-\frac{(y-\mu_Y)^2}{2\sigma_Y^2}}
$$

これらが独立しているとき、$ X $ と $ Y $ の同時確率密度関数は両者の密度関数の積となります。この場合、同時密度関数 $ f(x, y) $ は次のように表されます：

$$
f(x, y) = f_X(x) \cdot f_Y(y) = \left(\frac{1}{\sqrt{2\pi \sigma_X^2}} e^{-\frac{(x-\mu_X)^2}{2\sigma_X^2}}\right) \cdot \left(\frac{1}{\sqrt{2\pi \sigma_Y^2}} e^{-\frac{(y-\mu_Y)^2}{2\sigma_Y^2}}\right)
$$

これを展開すると、

$$
f(x, y) = \frac{1}{2\pi \sigma_X \sigma_Y} e^{-\left(\frac{(x-\mu_X)^2}{2\sigma_X^2} + \frac{(y-\mu_Y)^2}{2\sigma_Y^2}\right)}
$$

となります。これにより、$ x $ と $ y $ の値に対する同時確率密度が計算されます。


確率変数 $ X $ と $ Y $ が相関関係にある場合、通常これらは多変量正規分布、特に二変量正規分布を用いてモデル化されます。二変量正規分布の同時確率密度関数は次のように表されます：

$$
f(x, y) = \frac{1}{2\pi \sigma_X \sigma_Y \sqrt{1-\rho^2}} \exp\left(-\frac{1}{2(1-\rho^2)}\left[\frac{(x-\mu_X)^2}{\sigma_X^2} - 2\rho\frac{(x-\mu_X)(y-\mu_Y)}{\sigma_X \sigma_Y} + \frac{(y-\mu_Y)^2}{\sigma_Y^2}\right]\right)
$$

ここで、
- $ \mu_X $ と $ \mu_Y $ はそれぞれ $ X $ と $ Y $ の平均です。
- $ \sigma_X $ と $ \sigma_Y $ はそれぞれ $ X $ と $ Y $ の標準偏差です。
- $ \rho $ は $ X $ と $ Y $ の間の相関係数で、値は $-1$ から $1$ の範囲です。

この同時密度関数は、$ X $ と $ Y $ の間にどの程度の相関が存在するかを示す $ \rho $ を含んでおり、$ \rho = 0 $ の場合は $ X $ と $ Y $ が独立であるとして、上述の独立な場合の同時密度関数に帰着します。相関係数 $ \rho $ が $ 0 $ 以外の場合、これら二つの変数間には直線的な関係があると想定され、その強さと方向が $ \rho $ によって調整されます。

つぎに確率変数$X_1,\cdots,X_n$を考えます。どちらも同じ確率密度関数から取られています。この場合には$X$は$X$に関して独立です。また$Y$も$Y$に関して同様です。しかし、確率変数$X$と$Y$の間には相関があるので、独立ではありません。
AWS CDK（とマネジメントコンソール）でAmazon Cognitoの招待メッセージをカスタマイズする

こんにちは！
ポーラ・オルビスホールディングスのITプロダクト開発チームでスクラムマスターをしている川田です。

今回は、最近チームで実施したAmazon Cognitoの招待メッセージをカスタマイズする方法について、アウトプットも兼ねてご紹介しようと思います！:muscle:

# 背景
以前の記事で、私たちの開発チームが利用している技術や開発環境についてご紹介しました。

https://qiita.com/t_kawada_pohd/items/ae5dcae996d06b02752b

その際には触れていませんでしたが、私たちが開発したシステムのユーザー認証にはAmazon Cognitoを利用しています。オルビスではMicrosoft Entra ID (Azure AD)によってアカウント管理を行っているので、Cognitoの外部IdPとしてEntra IDを指定することでSSOを行う構成となっています。
この対応によりオルビスで業務されているほとんどの方はSSOができる状態なのですが、一部の方は勤務体系等の都合によりEntra IDでの管理対象外となっている方がいます。そのような方も私たちのシステムを使用する場面があるため、Cognitoのユーザープールにユーザーを登録しています。

Cognitoでユーザー登録を行うと、登録したメールアドレス宛に招待メッセージと共に一時パスワード（または確認コード）が送られます。試しに自分を登録してみて、送られてきたメールを確認してみましょう！:eyes:

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550354/4000598c-82b3-0776-34d5-6a78f097a8a3.png)

とてもシンプルです・・・:sweat_smile:
ということで、この招待メッセージをカスタマイズしてユーザーフレンドリーな内容にしてみます。

# マネジメントコンソールから変更してみる
まずはマネジメントコンソールから変更してみます。テンプレートの設定はユーザープール単位で行うため、Amazon Cognito → ユーザープールと辿ってから設定を行うユーザープールを選択します。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550354/0746d0d3-8364-70de-e764-a9e0ca1a963f.png)

ユーザープールの概要の下に表示されているタブから、メッセージングを選択します。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550354/799125a0-703a-aa2f-18ce-59ee81c3c753.png)

メッセージテンプレートのメッセージタイプから招待メッセージをクリックし、表示されるウィンドウ内の編集ボタンをクリックします。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550354/5f98c39e-64b9-38da-4a92-9b5bd4134167.png)

Eメールの件名とメッセージを変更しましょう。メッセージはHTMLメールで送信されるため、メッセージに改行を含める場合は改行タグ（`<br>`）を使用する点に注意が必要です。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550354/24cffc4e-8a1e-59b3-ddd2-0d063ff30636.png)

また`{username}`と`{####}`はテンプレートのプレースホルダーとして準備されており、それぞれユーザー名と一時パスワード（確認コード）に置き換えられてメールが送られます。

https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/cognito-user-pool-settings-message-customizations.html

以上の変更を保存し、実際にメールを送ってみたところイイ感じになりました！:+1:

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550354/0400c0da-f28c-074d-8305-c53d99535e28.png)

# AWS CDKで変更してみる
続いて、マネジメントコンソールで実施した内容をAWS CDKでやってみます。AWS CDKを使うことで、インフラストラクチャをコードで定義してプロビジョニングを実現できます。

AWS CDKでは、UserPoolクラスに対してuserInvitationの各プロパティを設定することで実現可能です。

https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cognito.UserInvitationConfig.html

マネジメントコンソールと同様の内容を、以下のように設定します。

```
new cognito.UserPool(this, 'myuserpool', {
  // ...
  userInvitation: {
    emailSubject: 'XXシステム仮パスワード発行のお知らせ',
    emailBody: ' {username} 様<br>
      <br>
      管理者があなたをXXXに招待しました。<br>
      下記のURLにアクセスして、ログインIDとパスワードでログインしてください。<br>
      <br>
      URL: <a href=" https://my-cool-system.co.jp/">https://my-cool-system.co.jp/</a><br>
      ログインID: {username}<br>
      初期パスワード: {####}<br>',
  },
});
```

こちらの設定内容でプロビジョニングし、実際にメールを送ってみたところ、マネジメントコンソールで実施した内容と同じ結果が得られました！:+1:

# おわりに
今回はCognitoから送信される招待メッセージをマネジメントコンソールで簡単にカスタマイズする方法と、それをAWS CDKから実現する方法についてご紹介しました。
AWS Lambdaを利用することでより詳細なカスタマイズを行うことも可能なので、機会があればトライしたいと思います！:muscle:

https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/user-pool-lambda-custom-message.html
SwiftのImageAnalyzerで画像内の縦書き文章を認識する(縦書きOCR)

# 結論
画像内に日本語の文章しかないなら、ImageAnalyzerを使えばおけです！

```sample.swift
func recognizeVerticalText(image: UIImage) async -> String {
        var recognizedText = ""
        guard #available(iOS 16.0, *) else { return recognizedText } // iOS16以上必須
        let analyzer = ImageAnalyzer()
        let configuration = ImageAnalyzer.Configuration(.text)
        do {
            let analysis = try await analyzer.analyze(image, configuration: configuration)
            recognizedText = analysis.transcript
        } catch {
            // error時の処理
        }
        return recognizedText
    }
    
```
## 注意
日本語と英語が混じった横書きの文章にはなぜかImageAnalyzerでは認識できません！代わりに王道(?)のVNRecognizeTextRequestを使います！

```sample.swift
func recognizeHorizontalText(image: UIImage?) async -> String {
        var recognizedText = ""
        guard let cgImage = image?.cgImage else { return recognizedText }
        let handler = VNImageRequestHandler(cgImage: cgImage, options: [:])
        let request = VNRecognizeTextRequest { request, err in
            guard let observations = request.results as? [VNRecognizedTextObservation], err == nil else { return }
            let texts = observations.compactMap({
                $0.topCandidates(1).first?.string
            }).joined(separator: ", ")
            recognizedText = texts
        }
        request.recognitionLanguages = ["ja-JP", "en-US"] // 認識する言語の指定
        request.recognitionLevel = VNRequestTextRecognitionLevel.accurate // 認識速度重視ならfast、正確さ重視ならaccurate
        request.usesLanguageCorrection = true
        
        do {
            try handler.perform([request])
        } catch {
            // error時の処理
        }
        return recognizedText
    }
```

## なぜImageAnalyzerでは日本語と英語が混じった横書きを認識できないのか？
いろんな種類の画像で検証してみましたが、原因不明です。画像内に英文しかない時に認識できるのはもちろん、日本語文章しかない時に縦書きと横書きの同時認識は可能でした。また、Configuration下にlocalesという値を見つけたんですが、もしかしたら、このlocalesがVNRecognizeTextRequestでいうrecognitionLanguagesのような役割を果たしているのかもしれません。なので、localesを正しくいじいじすれば解決しそうな気がします！知らんけど

## 対抗策
自分はUISwitch(SwiftUIではToggle)で、縦書きを認識するか横書きを認識するかあらかじめユーザーさんに決めてもらい、上記二つのメソッドをスイッチのオンオフで条件分岐して使っています。しかし、ユーザーさんの手間が増えてしまうのでできれば避けたいです。recognitionLanguagesのようにImageAnalyzerでも言語の指定方法があるのか、ある場合どうコードを書けば良いのか、ご存知の方いらっしゃったら教えていただけると助かります！

## 余談
オーディオブック作成アプリ「パシャリス」をAppStoreで公開してたんですけど、今までは参考書とかノートとか横書きの文章しか認識できなかったため、かなり欠陥アプリだったんですよねwwwでも、これで縦書きの本とかでもオーディオブック化できるようになり、より幅広い分野での音声学習が可能になりました！ImageAnalyzerの解説を上げてくださった参考記事の方には感謝しかありません！届けこの思い！ではでは！

## ImageAnalyzerの参考記事
https://zenn.dev/publictheta/articles/b957d065bd39b7
LinuxからRenesas Flash Programmerを使用してファームウェアを書き込む

# 手順

[ここから](https://www.renesas.com/jp/ja/software-tool/renesas-flash-programmer-programming-gui#downloads)
Renesas Flash Programmer V3.15.00 Linux(x64)
をダウンロード(*1)

解凍して
```shell
tar xf RFP_CLI_Linux_V31500_x64.tgz
```

設定
```shell
cd linux-x64
sudo cp 99-renesas-emu.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules
```

もしかすると再起動が必要かもしれない。

実行
```shell
./rfp-cli -d ra -t e2 -vo 3.3 -rts -a ~/workspace/sample.hex
```

# オプション指定の意味
|オプション名 | 内容 |例 |例の意味|
|-|-|-|-|
|d|デバイス名|ra | CPUがRA |
|t| 使用エミュレータ |e2 | liteではないe2エミュレータを使用 |
| vo | 電圧供給 | 3.3 | 3.3vを供給(*2) | 
| a | オート | -  | その他を自動設定で書き込む | 

(*1) 要ユーザ登録
(*2) PCから供給する電圧の意味。電源に刺さっている基盤に設定してはいけない
Reactを使って、クリックするとカードのように裏表が回転するコンポーネントを作成

# はじめに
クリックするとクルクルと回転して、裏表を表示してくれるコンポーネントを作成したので共有したいと思います。

🔽参考GIF
![画面収録 2024-05-27 12.36.21.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2708101/d0056e28-dc7d-c61c-f83b-b99200e0d4e2.gif)

# 実装

jsxファイルに以下を記述して、コンポーネントを宣言します。
解説として、簡単なコメントを入れています。

```javascript
import "./styles.css";
import { useState } from "react";

// 裏面と表面に表示する要素をpropsで受け取る
const Card = (props) => {

  const [isFlipped, setIsFlipped] = useState(false);

  // クリック時に裏表をstateに割り当て
  const handleClick = () => {
    setIsFlipped(!isFlipped);
  };

  // 裏表によってclassNameや表示する要素を変えている
  return (
    <div
      className={`card ${isFlipped ? "is-flipped" : ""} `}
      onClick={handleClick}
    >
      <div className="card-inner">
        <div className={`card-element ${isFlipped ? "is-flipped" : ""}`}>
          {isFlipped ? (
            <p className="card-back-element">{props.backElement}</p>
          ) : (
            <p className="card-front-element">{props.frontElement}</p>
          )}
        </div>
      </div>
    </div>
  );
};

export default Card

```

cssファイルは以下のように記述します。
ほとんどが見た目に関わる部分なので、大切な部分にはコメントを入れてます。
```css
.card {
  width: 300px;
  height: 250px;
  cursor: pointer;
}

.card-inner {
  position: relative;
  width: 100%;
  height: 100%;
  /* transform-style: preserve-3d; */
  transition: transform 0.5s; /* 回転のアニメーション*/
}

.card.is-flipped .card-inner {
  transform: rotateX(180deg); /*クリックされると回転*/
}

.card-element {
  position: absolute;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 24px;
  background-color: #ffffff;
  box-shadow: 0 3px 10px 5px rgba(131, 116, 94, 0.1);
  border: 1px solid black;
  border-radius: 10px;
  transition: box-shadow 0.3s ease-in-out;
}

.card-element.is-flipped {
  box-shadow: 0 -3px 10px 5px rgba(131, 116, 94, 0.1);
}

.card-front-element {
  font-weight: bold;
}

.card-back-element {
  transform: rotateX(180deg); /*カードが回転して逆になるから、裏面の要素は回転された状態に*/
  display: "inline-block";
}

```

呼び出す際の例はこちらです。

```javascript
<Card frontElement="表" backElement="裏" />
```

# おわりに

見た目なんかは好きに編集してみてください！
参考になると幸いです！

※補足
初めは、transform-style: preserve-3dを使って実装したんですけど、カードリストを表示した際のふとした時にエラーが出たんで、今回紹介したものに変えました。
なぜエラーになるのか分からないままなので、詳しい方がいればご教授ください！
【Flutter】下線を2重にする方法

こんにちは。
今回は、Text(テキスト)の下線を２重線にする方法を紹介します。

# 方法
![スクリーンショット 2023-08-13 20.18.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524120/ce57fee2-1687-ea40-8538-b4c8b9db94e0.png)

Textの下線を２重線にするには、TextStyleの引数「decorationStyle」を使います。
そして、TextStyleの引数「decorationStyle」に「TextDecoration.double」を指定します。


# 使用例
```dart
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: Text(
          '2 Line',
          style: TextStyle(
              decoration: TextDecoration.underline,
              decorationStyle: TextDecorationStyle.double,
              fontSize: 50),
        ),
      ),
    );
  }
}
```

# 実行例
![スクリーンショット 2024-05-27 12.58.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524120/ed362f50-1059-3dcf-cbd6-e81f5baabf8b.png)




# 最後に
ここまで読んでいただき、ありがとうございました！
いいねしてくれたら、スキップして喜びます:heartpulse:
.envファイルで環境変数を設定する方法

## はじめに
大学の授業で、入力されたアーティストと近しいアーティストのネットワーク図を作成するシステムを作ったので、今回は個人的な趣味で、そのシステムを発展させてWebアプリケーションを開発しました。その際、APIのアクセスキー（環境変数）をコードに直接記述してGitHubに（publicで）上げてしまうと情報セキュリティの問題があると気付き、環境変数をセキュアに管理する方法を調べたので、その備忘録を残します。

## 方法
`.env`ファイルを使用します。

具体的には、`python-dotenv`モジュールを使用して`.env`ファイルを読み込みます。

`.env`ファイルを使用することのメリットは以下の通りです。
- 環境変数を一元管理でき、設定の変更や追加が簡単になる
- データベースの接続情報やAPIキーなどの機密情報をソースコードに直接書かずに済むため、セキュリティが向上する（`.gitignore`ファイルに`.env`を記述することで、GitHub上に公開されずに済みます。`.gitignore`ファイルの作成は後述）
- チームで開発する際に、個々の開発者が自身の環境に合わせた.envファイルを用意することで、他の開発者や本番環境の設定に影響を与えることなく作業できる

## 手順
### 1. python-dotenvモジュールをインストールする
```
$ pip install python-dotenv
```
コマンドプロンプト上あるいはVSCodeのターミナル上で、`pip`コマンドを使用して、`python-dotenv`モジュールをインストールします。

### 2.「.env」ファイルを作成する
ルートディレクトリの直下に以下の`.env`ファイルを作成します。
自分の場合は[前回記事](https://qiita.com/k-suna/items/3b6e5aba24e0861deb25)で紹介したWebアプリケーションのプロジェクトがあるので、以下のようになります。
```text:ディレクトリ構造
{プロジェクト名}/
├── static/
│   └── style.css
├── templates/
│   └── index.html
│   └── result.html
│   └── error.html
├── app.py
└── .env 
```
自分はSpotify APIを使用していたので、`.env`ファイルにそのクライアントIDとシークレットキーを記述しました。
```text:.env
export SPOTIFY_CLIENT_ID='XXXXXXXXXXXX' 
export SPOTIFY_CLIENT_SECRET='YYYYYYYYYYY'
```

### 3.「.env」ファイルを読み込む
```python:app.py
from dotenv import load_dotenv
import os

# .envファイルから環境変数を読み込む
load_dotenv()

#SpotifyAPIのアクセストークン情報
# 環境変数からSpotify APIのクライアントIDとシークレットを取得
client_id = os.getenv('SPOTIFY_CLIENT_ID')
client_secret = os.getenv('SPOTIFY_CLIENT_SECRET')

print(client_id) #client_idが表示される
print(client_secret) #client_secretが表示される
```
`load_dotenv()`を使用して`.env`ファイルを読み込みます。これにより、`.env`ファイルに書かれたアクセストークン情報が環境変数に設定されます。

そして、`os.getenv()`を使用して環境変数の値を取得します。`print`文で適切に表示されることを確認してください。該当の環境変数が存在しない場合、Noneが返されます。

### 「.gitignore」ファイルの作成
gitで管理する場合に`.gitignore`ファイルを作成し、その中にファイル名を書くことで、書かれたファイル名をgitの管理対象から外すことができます。
手順としては以下の通りです。ルートディレクトリの直下に以下の`.gitignore`ファイルを作成します。
```text:ディレクトリ構造
{プロジェクト名}/
├── static/
│   └── style.css
├── templates/
│   └── index.html
│   └── result.html
│   └── error.html
├── app.py
├── .env
└── .gitignore
```
```text:.gitignore
.env
```
上記のように作成することで、GitHubにpublicでプロジェクトを公開しても、`.gitignore`ファイルのおかげで、`.env`ファイルは公開されずに済みます。

## 終わりに
今回は、APIアクセストークンなどの環境変数のセキュアな管理方法についてまとめました。次回以降では、GitやDockerの操作方法などを書こうと思います。

## 参考文献
以下の記事を参考にしました。ありがとうございました。

https://qiita.com/s_ryota/items/26f1a05737a48ad08956

https://psrobo2501.link/programming/env01

https://zenn.dev/nakashi94/articles/9c93b6a58acdb4
SSH接続しているサーバー上でPythonの最新版をインストールしたい

SSH接続しているサーバー上でPythonの最新版をインストールしたい


# 私の状況
Python　コマンドを打てば、下記のようなものが出たがバージョンが2.xxxでちょっと古かった

~~~
$ python
Python 2.7.5 (default, Nov 16 2020, 22:23:17) 
[GCC xxxxxxxxxx (Red Hat x.x.x-xx)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> python3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'python3' is not defined
>>> 
KeyboardInterrupt
>>> 

~~~

Python３を打つと下記のように出てしまう

~~~
bash: python3: command not found...
Similar command is: 'python'

~~~


# 作業方針

簡単な作業方針としては「環境変数の設定」を行うという作業をします。



# 具体的な作業

具体的には下記のコマンドを打ちます。

~~~
$ ls .*
~~~
のあと
~~~
$ more .bashrc
~~~
するとファイルを見つけられるので

~~~
$ nano .bashrc
~~~

コマンドを打って、下記をコピペしました。
export先のディレクトリを一番下の行に追加しているのですが、実際は自分が行ったPythonコード回した結果をどこに置きたいかというのを自分の好きなディレクトリに指定してください。

~~~
# Python 3
PY3DIR=/usr/local/Python-3.8.2
export PATH=${PY3DIR}/bin:${PATH}
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${PY3DIR}/lib
export PYTHONPATH="/*directly path you like*/**"
~~~

上記を挿入するところは基本的には一番下にしておくとよさそう。
環境変数の設定は、シェルの初期化ファイルの一番下に追加するのが一般的です。これにより、他の設定がすべて読み込まれた後に適用されるため、予期せぬ競合を避けることができるらしい。


# 試してダメだった行程

上に行きつくまでにいろいろ試してダメだったケースは下記の通り（エラーが出たなど）


https://pages.github.nceas.ucsb.edu/NCEAS/Computing/local_install_python_on_a_server.html

上記のものを見たりもしたのですが、実際にコマンドを入れてみてもうまくできずにエラーになったので下記のような作業を行っています。