OmniAICreator/Qiita-1.07M huggingface dataset:
mmdetection v2.25.2以降でモデルの学習を行うときの注意

# 手順の概要
1. 環境
1. 問題点の確認
1. Config内のdataを書き換え

# 環境
mmcv v1.7.1
mmdetection v2.28.2

# 問題点の確認
mmdetection v2.25.2以降では，https://github.com/open-mmlab/mmdetection/pull/8575 において，`tools/train.py`が書き換えられた．その影響でこれまで使っていたConfigファイルから学習させようとしたときに，以下のようなエラーがでて動かない場合がある．
```
Traceback (most recent call last):
  File "/mmdetection/tools/train.py", line 248, in <module>
    main()
  File "/mmdetection/tools/train.py", line 225, in main
    print(cfg.data.train.dataset)
  File "/mmcv/mmcv/utils/config.py", line 50, in __getattr__
    raise ex
AttributeError: 'ConfigDict' object has no attribute 'dataset'
```

https://github.com/open-mmlab/mmdetection/pull/8575 のコメントにある通り，エラーが発生して動かないという文句が書いてある．今回は，その解決方法を書く．
もちろん，この解決方法が気に入らない場合は，mmdetection v2.25.1のコードを使うと良いと思う．（未検証なので動作保証はできません）

# Config内のdataを書き換え
https://github.com/open-mmlab/mmdetection/pull/8575 にある通り，`tools/train.py`は`RepeatDataset`などに対応するように変更されたらしい．そこで，Config内のdataを書き換えることで解決を試みた．以下がその例である．data変数のtrainキーに`times=1`の`RepeatDataset`を適用した．`RepeatDataset`に対応させたということなので，`RepeatDataset`を適用するという方法である．
```
# 変更前
data = dict(
    samples_per_gpu=2,
    workers_per_gpu=2,
    train=dict(
        type=dataset_type,
        ann_file=data_root + 'annotations/instances_train2017.json',
        img_prefix=data_root + 'train2017/',
        pipeline=train_pipeline),
    val=dict(
        type=dataset_type,
        ann_file=data_root + 'annotations/instances_val2017.json',
        img_prefix=data_root + 'val2017/',
        pipeline=test_pipeline),
    test=dict(
        type=dataset_type,
        ann_file=data_root + 'annotations/instances_val2017.json',
        img_prefix=data_root + 'val2017/',
        pipeline=test_pipeline))

# 変更後
data = dict(
    samples_per_gpu=2,
    workers_per_gpu=2,
    train = dict(
        type = 'RepeatDataset',
        times = 1,
        dataset = dict(
            type=dataset_type,
            ann_file=data_root + 'annotations/instances_train2017.json',
            img_prefix=data_root + 'train2017/',
            pipeline=train_pipeline)
    ),
    val=dict(
        type=dataset_type,
        ann_file=data_root + 'annotations/instances_val2017.json',
        img_prefix=data_root + 'val2017/',
        pipeline=test_pipeline),
    test=dict(
        type=dataset_type,
        ann_file=data_root + 'annotations/instances_val2017.json',
        img_prefix=data_root + 'val2017/',
        pipeline=test_pipeline))
```
Proxy（Basic認証）環境におけるUipath Studioインストール・利用手順_2023.3時点

UipathStudioを導入にあたってProxy環境下での利用するにあたって、ハマりました。
uipath.configの設定などを変更してもエラーが解消できずにいましたが、手順だけで
proxy（Basic認証）を通過してサインインする事ができたので記事を書きました。

:::note info
なお、検証についてはStudio2023.2.0 Community Editionでおこなっています。
:::
***これが問題のproxy認証エラーの画面です***
　　　![op0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/c3b5bbde-5919-4972-f317-206367201998.png)

公式サイトにproxy設定のナレッジが展開されていますが、
uipath.config設定後もUipathStudioのproxy認証エラー解消できず

https://www.uipath.com/ja/community-blog/knowledge-base/robot-orchestrator-proxy-configuration-v202210

https://www.uipath.com/ja/community-blog/knowledge-base/proxy-settings

## インストール・利用手順
手順1：公式サイトからサインインし、Automation Cloudを開きます。
　　　![op2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/99b5ba21-8b76-87e3-00dc-769d95dab0f5.png)

手順2：（初回のみ）Automation Cloudが未登録の場合、登録画面に遷移します。
　　　![op2.5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/bbf5aab5-2b7c-a51a-85e5-bb001e1b1f36.png)
　　　![op3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/ee839708-42a7-417d-0c41-cc533390bf72.png)

手順3：Uipath StudioをダウンロードボタンからインストーラーをDLします。

　　　![op4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/35c4e979-a396-4d97-e583-27f118ec5138.png)

手順4：インストーラを実行します。
　　　 UipathStudioを起動をクリックするとproxy認証エラーが表示されるのでそっと閉じます。:umbrella:
　　　![op5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/b64c39cb-f91e-ba6f-ae01-aa11f213d152.png)
　　　![op6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/fc769478-d9fe-6e94-c953-60b9503b98e2.png)

手順5：手順4でインストールしたUiPath Assistantを起動します。Proxy情報を入力した後
　　　（**proxyBasicAuthjsonが作成されます**）に一度、Windowsをサインアウトします:sunny:。
　　　![op7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/5dec8f9a-24ac-7576-d8e9-09fc8e009255.png)


手順6：サインイン後に、もう一度UiPath Assistantを起動します。既定のブラウザに遷移し認証OKになると
　　　UiPath Assistant利用可能な状態になります。
　　　![op8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/2af0f901-9323-2394-0713-1bddd257ac28.png)


手順7：手順6の後にUipathStudioを起動をクリックすると何事もなかったように起動できるようになりました。:v:
　　　![op9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/61b5bcd1-a9ed-ec79-0c93-d56e85b953a8.png)

 以上です。ご精読いただき、ありがとうございました。
![op10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/ee4d2f5c-8c79-7e0c-d461-88faaf37794a.png)
【AWS】まだ間に合う！日本語入力で「???」になっても慌てないで

[前回](https://qiita.com/SarasaMorita/items/d819c90b280969ad4890)無事にRDSに接続できたわし。
「なんかAWS理解できるようになっちゃってインフラのプロになれんじゃね？」
とかイキっておりました。
今回はそんなイキったやつが照合配列についてお勉強するお話です。

# 「え？日本語でおｋ？じゃないの？？」
データ型さえ指定すれば文字列データ入れられるじゃんと考え、**日本語**でデータを入力してINSERTしたものの、、、
![スクリーンショット 2023-03-06 210605.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2863909/211b582b-beee-ec87-1e94-76a042282999.png)


まさかの**文字化け**。
データ型の指定やクエリも以前ローカルのサーバー使ったときと同じにしていたので、「なんでRDSだとおかしくなっちゃうん？？」ってなりましたね。。

# 要デフォルト確認
そもそも論ですが、SQLServerとRDSでは**デフォルトの照合配列が異なっています**。
SQLServerではJapanese_CI_ASが、RDSではSQL_Latin1_General_CP1_CI_ASがデフォルトで設定されています。
**SQL_Latin1_General_CP1_CI_ASについては日本語入力が対応していないため**、日本語で文字列を入れると「??」になってしまっていたようなのです。
しかも、RDSの照合配列を決められるのはDBインスタンス作成時のみのため、作成後に「あ！！日本語のデータ入れないと！！」となっても**インスタンス自体での**変更はできないのです、、

いやーでもテーブル作った後にデータ型変更したくなることくらいあるよね？？

なんとか変更くわえたいものやなあ。

# データベースだけなら何とかなりそう
DBインスタンスは変更できないことがわかったので、データベースエンジン自体の設定をいじっていくことに。

SSMSに該当のインスタンスでログインしたら、オブジェクトエクスプローラーのツールタブから、「オプション」を選択。左側の一覧からデザイナー＞テーブルデザイナー及びデータベースデザイナーを選択します。
次に、テーブルオプション画面で、赤で囲った箇所のチェックを外します。
![スクリーンショット 2023-03-02 231105.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2863909/c631c4bd-e532-6913-89c8-ae3ed755c997.png)
タブを閉じたら、オブジェクトエクスプローラーからデータ型を変えたいデータベースを右クリックし、「プロパティ」を選択します。
左側の「オプション」を選択すると、照合配列を変更できる画面が表示されるので、ここからJapanese_CI_ASに変更します。

![スクリーンショット 2023-03-02 232932.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2863909/d666bae2-fc0e-b1a7-b749-5493f14e9afe.png)
（選択肢多すぎてめっちゃ迷ったのここだけの話）

この時点で該当するデータベース自体の照合配列を変えることが可能になり、以降データベース上で作成されるテーブルの照合配列はJapanese_CI_ASとなります。

それでは、プロジェクト側からデータ型を変更していきます。
まずVisual Studioで該当プロジェクトを開き、表示＞サーバーエクスプローラーから照合配列変更前に作ったテーブルを右クリックし、「テーブル定義」を選択します。![スクリーンショット 2023-03-02 201224.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2863909/51714743-e4ef-e043-f1b1-3d58bc28fe75.png)

CREATE文を記述した際に設定したテーブル定義がひょうじされるので、「COLLATE SQL_Latin1_General_CP1_CI_AS」の部分だけを消して更新ボタンを押します。

この状態でデバックを実行し、日本語のデータを入れると、
![スクリーンショット 2023-03-06 210705.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2863909/51542a16-ecfa-fb50-f84a-4a43b56e8cac.png)
ああ・・！ちゃんと日本語入力が反映されておる・・！！

# ミスったと思っても案外何とかなる
正直まだまだ勉強不足感強すぎて
「そもそもなんでインスタンスの照合配列はSQL_Latin1_General_CP1_CI_ASのままなのに日本語入力できたのか」
とかはまだ調べられていないのが現状です。

とはいえ、「やっちまったー」となっても、細々と調査を続けたことで対処方法がわかったのはわかったなあと思っています。
Googleデジタルマーケティング＆Eコマース：ディスプレイ広告の基礎

# はじめに

”Googleデジタルマーケティング＆Eコマース プロフェッショナル認定証"　の受講が完了しました(2022/3/3)。私がこのコースから得られた素晴らしい体験を、テーマごとに分割して、わかりやすくご紹介しています。興味を持たれた方は、是非下記を受講してみてください。

https://jp.coursera.org/professional-certificates/google-digital-marketing-ecommerce

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/77505f22-0d8f-b3af-4f9c-ed148bcefd65.png" width="800">

# ディスプレイ広告とは？

ディスプレイ広告は、Webページやアプリに掲載されるビジュアル広告フォーマットです。ディスプレイ広告は、画像、テキスト、動画、GIFをディスプレイネットワークに入稿し、理想のオーディエンスの前に配置して、ブランド、サービス、または製品を宣伝することができます。

ディスプレイネットワークは、広告を表示できるWebサイト、ビデオ、アプリのグループです。ディスプレイネットワークでは、マーケティング担当者が特定のオーディエンス、コンテキスト、場所などに広告をターゲティングすることができます。


ディスプレイネットワークの例としては、
- Googleディスプレイネットワーク
- Taboola
- Criteo

があります。しかし、選択肢はたくさんあるので、どれが自社にとって最適かを判断するために、できるだけ多くリサーチすることをお勧めします。

:::note info
ディスプレイ広告は、その効果の高さから、世界中の何百万もの企業で利用されています。
:::


# ディスプレイ広告の種類

| 種類 | 内容  | 
| :--- | :--- | 
| イメージ広告 | Webサイト上に表示される静止画のJPG、PNG、またはアニメーションGIFファイルです。ビジュアルで訴求することで、商品の有用性をユーザーに伝えることができるため、効果的なアプローチとなります。 | 
| テキスト広告 | Webサイトにテキストのみで表示される一般的な広告のことです。文字だけなので、ダイナミックな広告とは言えません。 | 
| レスポンシブ広告 | そのサイズとフォーマットを自動的に調整し、その周りの利用可能なスペースに合わせます。レスポンシブ広告の柔軟性と機能は、彼らが非常に人気があります。また、ネイティブ広告として表示されることもあります。これは、ウェブサイトのコンテンツのネイティブピースのように見えるように設計され、フォーマットされていることを意味します。 | 
| アプリプロモーション広告 | アプリをダウンロードさせることで、ユーザーからのアプリのダウンロードとエンゲージメントを促進する広告です。アプリプロモーション広告は、クリックするとユーザーがアプリストアに直行し、貴社がダウンロードさせたいアプリを簡単に入手できるため、非常に優れています。これらの広告は、御社のコンテンツと互換性のあるデバイスにのみ表示されます。 | 

# マーケティングファネルにおけるディスプレイ広告の位置づけ

Googleでは、ディスプレイ広告は認知度を高め、顧客数を増加させる可能性があるため、ファネルの

- 認知ステージ
- 検討ステージ

で採用されています。

しかし、Googleでは、ファネルのさらに下流に位置するリマーケティングにもディスプレイ広告を採用しています。リマーケティングは、Webサイトやソーシャルメディアのプロフィールにアクセスしたことのある顧客に有料広告を配信します。これにより、

- コンバージョンの増加
- ロイヤルカスタマーの維持

が可能になります。
ReactのNextjsでViteを使って開発をしたい

# Next.jsとViteとは
Next.jsは、Reactアプリケーションをサポートするフルスタックフレームワークであり、サーバーサイドレンダリング、静的サイト生成、ルーティング、データフェッチなどの機能を提供します。一方、Viteは、フロントエンドビルドツールであり、高速な開発サーバー、モジュールバンドラー、Hot Module Replacementなどの機能を提供します。Viteは、プロジェクトのビルド時間を短縮し、開発体験を改善するために設計されています。

# Next.jsでViteを使用する方法
Next.jsでViteを使用するには、2つの方法があります。1つは、開発時にViteを使用することで、もう1つは、Next.jsのビルドシステムをViteに置き換えることです。

- 開発時にViteを使用する場合は、Next.jsのWebpack構成をカスタマイズし、Viteを起動するためのエントリーポイントとして使用します。次のような手順で、ViteをNext.jsプロジェクトに追加することができます。
    - `npm install vite` を実行して、Viteをインストールします。
    - Next.jsの設定ファイルである next.config.js ファイルを作成します。
    - next.config.jsファイルに、Viteのエントリーポイントとして使用するファイルを指定します。
    - `npm run dev` を実行して、Viteの開発サーバーを起動します。
- Next.jsのビルドシステムをViteに置き換える場合は、Viteのビルドプラグインを使用することができます。ビルドプラグインは、Next.jsのビルドシステムの一部を置き換えるため、ビルドプロセスを高速化することができます。ビルドプラグインを使用する場合、Viteは、Next.jsのビルドシステムとの互換性を維持するために、同じWebpack構成を使用します。

# Next.jsでViteを使用する際の注意点
Next.jsのAPIルート機能は、Viteの開発サーバーと同じポートで公開する必要があります。これにより、CORSの問題を回避することができます。
Viteを使用する場合、ファイルシステムの変更を検知するために、プロジェクトのファイル構造を調


# Next.jsとViteの環境を作ってみる
Next.jsはReactアプリケーションを作成するためのフレームワークであり、Viteは高速でシンプルなフロントエンドビルドツールです。Next.jsとViteを組み合わせることで、開発効率を向上させることができます。以下は、Next.jsでViteを使用する方法です。

## 1.Next.jsプロジェクトの作成
最初に、Next.jsプロジェクトを作成する必要があります。次のコマンドを使用して、Next.jsプロジェクトを作成します。

```perl
npx create-next-app my-app
cd my-app
```

## 2.Viteの設定
Viteを使用するために、Next.jsプロジェクトにViteをインストールする必要があります。次のコマンドを使用して、Viteをインストールします。

```perl
npm install --save-dev vite
```

Viteの設定ファイルを作成する必要があります。プロジェクトのルートディレクトリに、vite.config.jsファイルを作成し、以下のコードを追加します。

```js
const { resolve } = require('path')

module.exports = {
  webpack(config) {
    config.resolve.alias['~'] = resolve(__dirname, 'src')
    return config
  },
}
```

この設定は、Webpackの設定を変更するものであり、Next.jsのエントリーファイルとしてViteを使用するために、プロジェクトのエイリアスを追加しています。

## 3.Viteの実行
Viteを実行するには、次のコマンドを使用します。

```perl
npx vite
```

これにより、開発サーバーが起動し、Viteを使用してNext.jsアプリケーションをビルドすることができます。

以上の手順により、Next.jsでViteを使用することができます。注意点として、Viteを使用することでNext.jsの機能の一部が制限される場合があります。特に、Next.jsのサーバーサイドレンダリングとAPIルートの機能は使用できません。したがって、Viteを使用する場合は、この制限に注意してください。

# Next.jsでViteを使用するためのより詳細な情報

## 1.Viteを使用する場合のメリット
Viteは、WebpackやParcelなどの従来のビルドツールよりも高速で軽量であるため、開発者にとってメリットがあります。Viteは、ビルドによる再起動が不要であるため、ファイルの変更を検出し、必要な部分のみ再ビルドします。また、Viteは、開発中のアプリケーションのパフォーマンスを向上させるため、Hot Module Replacementをサポートしています。

## 2.Next.jsでViteを使用する場合の制限事項
Next.jsは、サーバーサイドレンダリングやAPIルートなどの機能があり、これらの機能を使用する場合、Viteが制限されることがあります。特に、Viteは、Node.js上で実行されないため、サーバーサイドレンダリング機能を使用することができません。また、Viteは、開発環境に限定されるため、ビルドプロセスをカスタマイズすることができません。

## 3.Next.jsとViteを組み合わせた開発のヒント
Next.jsとViteを組み合わせる場合、以下の開発のヒントに従うことをお勧めします。

- Viteは、開発環境でのみ使用することをお勧めします。プロダクション環境では、Next.jsが提供するビルド機能を使用することをお勧めします。
- Viteを使用する場合、React Fast Refreshを有効にすることをお勧めします。これにより、ファイルの変更がすぐに反映されるため、開発効率が向上します。
- カスタムWebpack構成を使用する場合、Viteとの互換性に注意してください。Viteは、Next.jsが提供するWebpack構成に依存しています。
- Next.jsのAPIルート機能を使用する場合、Viteの開発サーバーと同じポートでAPIルートを公開する必要があります。これにより、CORSの問題を回避することができます。

以上が、Next.jsでViteを使用するための情報です。注意点を理解し、適切に使用することで、開発効率を向上させることができます。
Raspberry Pi (raspbian)における NAS + ファイルマネージャアプリ による簡便ファイル共有環境構築

# システム構成図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2574123/113df140-ee98-a4e1-e6b9-47d0926378e5.png)


#### ※Raspberry Pi4 ModelB 4GBで動作確認。ソフトはNAS には samba を利用。

## ラズパイ構築とNAS構築は以下を参照

https://qiita.com/parapaper/items/b4cc4ee6d3b7498195eb


## ファイルマネージャー+

https://www.teradas.net/archives/39783/

## メリット/デメリット

DLNAでは参照させたい場所が指定できるので、階層が複雑化したファイルサーバではメリットとはいえるが、DLNA(minidlna)は参照できる拡張子に制限があるため、存在していても見えず、保存されてないと勘違いする事例になる。

拡張子の表示差異は以下を見るとわかりやすい
画像ファイルでいえばJPGしか対応しないため、PNGは表示されないなど。

https://wiki.archlinux.jp/index.php/ReadyMedia

https://unistar.jp/faq/a11/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2574123/57a39760-8bbe-2770-2931-535651bc31eb.png)




その点、NASでは拡張子関係なく表示するので、その懸念はない。
DLNAを介さず、スマホ側のクライアントをファイルマネージャアプリで対応できればよし！
デメリットとすれば、あくまでもファイルマネージャのため、NAS側の階層構造を複雑化すると使いづらいものとなる。
また、複数人で共有するNASの場合、他者が編集しないよう特定の他者にはDLNAで共有することや、raspbianOSのシステムファイルを触らせないよう参照権限しかないユーザを利用するなど使い分けは必要かもしれない。
Javaを基本からまとめてみた【オブジェクト指向・設計図クラス】


プログラムは１回作ったらそれで完成ではなく、実際の開発現場ではいろいろな修正が加わったり、機能が追加されたりなど１回作ったプログラムは変わっていくのがほとんどである。

1つの変更によって次々といろんなところに変更の連鎖が起きていく。
- 修正ミスやいろんなミスなどが起こりやすい。
- 他の人からみて訳がわからないプログラムになる。

##### ⇨ オブジェクト指向でプログラムを書くとデータを分かりやすくまとめて管理することができるようになる

## オブジェクト指向
- 実行用クラスと設計図クラスがある
- オブジェクト:クラスから作られる実体（モノ）
- オブジェクト指向:オブジェクトを中心にてプログラムを作る考え方

### 設計図クラス


クラス（設計図）
属性（何のデータを持っているか）
操作（何の処理を持っているか）
オブジェクト（実体）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/fc8a6d37-e633-94ec-3c4e-4c63a69258b5.png)

#####  ①設計図の中にデータと処理をひとまとまりにしてプログラムを作っていく<br/>②持っているデータや処理を分けて、クラスを組み分けて動かしていく<br/>⇨ このようなプログラムの作り方や考え方のことを『オブジェクト指向』という

## メリット
- みんなで分担して開発ができるので、開発効率やスピードも上がる
- 大規模なシステムをみんなで作成できる
- 作った後のメンテナンスもしやすい
- 機能追加もしやすい
- 必要なクラスや変数だけをその都度メモリ上に読み込んで実行、不要な場合メモリから無くす処理が進んでいくので、メモリの使用効率もよく早く処理を進められる
- 現実社会をプログラムに置き換えやすい

## ２種類のクラス
- 実行用クラス : mainメソッドを記述
- 設計図クラス : 属性と操作を記述　// 属性 ⇨ 変数　 操作 ⇨ メソッド

```
class クラス名{
   変数の定義
　　メソッドの定義
}

//変数の定義
データ型　変数名;
例)String name;
  int score;
```
```Sample.java
public class Student {
//メンバ変数(属性)
	String name;
	int engScore;
	int mathScore;
//メソッド（操作）
void display(){
    System.out.println(name + "さん");
    System.out.println("英語" + engScore + "点・数学"  + mathScore + "点");
}
void setScore(int eng,int math){
   engScore = eng;
   mathScore = math;
}
double getAvg() {
       double avg = (engScore + mathScore)/2.0;
       return avg;
	}
}
```

## メソッドの定義

```
戻り値の型　　メソッド名（引数リスト）{
      (処理)
}
```

- 引数 : 呼び出し元から受け取る値
- 戻り値 : メソッドの処理の後に呼び出し元に返す値『return』で指定する。何も返さない場合は、戻り値の型に『void』を記述する

```
//引数なし　戻り値なし
void display(){
   System.out.println(name);
}

//引数あり　戻り値なし　
//※ 引数の受け取り方は変数の宣言をする　⇨ データ型　変数名のペアで1つのデータを受け取れる

void display(int eng, int math){
   engScore = eng;
   mathScore = math;
}


//引数なし　戻り値あり
//※平均値は小数として返すメソッドなので、戻り値の型は『double型』となっている
double getAvg() {
     double avg = (engScore + mathScore)/2.0;
     return avg;
}
```



## 参考サイト
[オブジェクト指向の必要性とメリットが理解できる！【Java入門講座】3-1 オブジェクト指向](https://www.youtube.com/watch?v=mGEUZcKx4CE)
[オブジェクト指向プログラミングとは](https://thinkit.co.jp/article/13058)
春休みのPython機械学習日記

# はじめに
2023年度の春休みに取り組んだpythonプログラミングの学習内容を記載します。教材は、以下の「Python機械学習プログラミング[PyTorch & scikit-learn編]」を用いています。


https://www.amazon.co.jp/Python%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%EF%BC%BBPyTorch%EF%BC%86scikit-learn%E7%B7%A8%EF%BC%BD-impress-gear-Sebastian-Raschka/dp/429501558X/ref=nodl_?dplnkId=21e797e5-458f-4500-a48d-59cb9f94ba2d

# 第3章 分類問題 機械学習ライブラリscikit-learnの活用
本章では分類を目的とした教師あり学習のアルゴリズム間の相違点を学びながら、それらの長所と短所を見極める力を養う。
ここからは、以下のような構成で分類アルゴリズムを紹介する。

1. **ロジスティック回帰**
1. **サポートベクトルマシン**
1. **決定木**
1. **k最近傍法**

# １.１　ロジスティック回帰と条件付き確率
ロジスティック回帰は、**線形分類問題**と**二値分類問題**に対する単純ながら強力なアルゴリズムの1つである。また名前とは裏腹に、回帰ではなく**分類**のためのモデルである。

早速、主な仕組みについて理解していく。
ロジスティック回帰では、活性化関数に**シグモイド関数**を利用する。
ここで、**シグモイド関数**は以下のように定義されている。
```math
σ(z) = \frac{1}{1+e^{-z}}
```
この関数を図に表すと以下のような**S字形**（シグモイド）曲線が表示される。
<img src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3242311/a5b0d079-99d0-caa9-3408-a9f30579dc04.png" width=50%>
図を見てみると、シグモイド関数は、**z→∞**では σ(z)が**1**に近づくことが分かる。同様に、**z→-∞**では σ(z)は**0**に向かう。したがって、このシグモイド関数は、入力として実数値を受け取り σ(0) = **0.5**を**切片**として、それらの入力を[**0,1**]**の範囲の値に変換する**と結論付けることが出来る。

ここで、これまでに示したシグモイド曲線を活性化関数に用いてロジスティック回帰の全体像を図で確認しててみよう。
<img src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3242311/a0531bb8-c040-1220-358d-71ee9d351ec7.png" width=80%>
特定のデータ点の特徴量がxで、重みとバイアスでパラメータ化されるとすれば、このシグモイド関数の出力は、このデータ点がクラス１に所属している確率 σ(z) = p(y=1| **x**; **w**, b)として解釈される。
図では、クラスラベルの予測値が最終的な結果として用いられているが、
実際には、**クラスの所属関係の確率**（閾値関数を適用する前のシグモイド関数の出力）を見積もることに特に価値がある。

# １.２ ロジスティック損失関数を使って重みを学習
重み**w**とバイアス**b**といったモデルのパラメータを適合させる方法について簡単に説明しておく。
まず、平均二乗誤差(MSE)の損失関数を以下のように定義する。
```math
L（\boldsymbol{w},b|\boldsymbol{x}) = \sum_{i} \frac{1}{2} (σ(z^{(i)})-y^{(i)})^2
```
さらに、分類モデルのパラメータを学習するために、この関数を最小化する。まず、ロジスティック回帰モデルの構築時に最大化したい尤度**L**を定義する。式は以下のようになる。
```math
L(\boldsymbol{w},b|\boldsymbol{x})= p(y|\boldsymbol{x};\boldsymbol{w},b) = \prod_{i = 1}^{n}p(y^{(i)}|\boldsymbol{x}^{(i)};\boldsymbol{w},b) = \prod_{i = 1}^{n}(σ(z^{(i)}))^{y^{(i)}}(1-σ(z^{(i)}))^{1-y^{(i)}}
```
実際には、この式の対数を最大化する方が簡単である。これを**対数尤度**(log-likelihood)関数と呼ぶ

```math
l(\boldsymbol{w},b|\boldsymbol{x})= logL(\boldsymbol{w},b|\boldsymbol{x}) = \sum_{i = 1}[y^{(i)}log(σ(z^{(i)}))+(1-y^{(i)})log(1-σ(z^{(i)}))]
```
まず、対数関数を適用すると、アンダーフロー（下位桁あふれ）の可能性が低下する。アンダーフローが発生する可能性があるのは、尤度が非常に小さい場合である。次に、対数関数を適用して係数の積を和に変換すると、加算を用いてこの関数の導関数が簡単に得られる。
Vue2.7 ＋ Vite のプロジェクトを新規作成する。

# はじめに

非常に基本的な手順なのですが、なかなかそのものズバリを見つけられなかったので自分で書きました。

そもそも弊社でももう Vue3 に移行して久しいので、新規で Vue2.x のプロジェクトを立ち上げることはほぼありません。にも関わらずこの記事を書いたのは、既存 のVue2 プロジェクトを Vue3 に移行する際に Vue2 の段階で vite に移行しておいたほうが Vue3 への移行がスムーズではないかと思ったからです。そのためには素の Vue2.7＋Vite のプロジェクトを新規作成し、ファイルの比較を行いながら移行した方が良いと思いました。

そのため、ここでは「VueCLI で Vue2.7 プロジェクトを作ってからそれを Vite 化する」の**ではなく**、「Vite プロジェクトを作って、それをVue2.7 化する」という手順にしました。その方がクリーンな状態を見れるからです。VueCLI のプロジェクトを Vite 化する方法はたくさん見つかりますが、ゴミがたくさん残って捨てるのに困ると思います。なのでクリーンな状態を作っておくことで最終的に目指す形を確認できるというのが重要だと思いました。

# 手順

## Vite プロジェクトを作成します。

```
$ npm init vite
? Project name: » vite-project
? Select a framework: » - Use arrow-keys. Return to submit.
>   Vanilla
    Vue
    React
    Preact
    Lit
    Svelte
    Others
? Select a variant: » - Use arrow-keys. Return to submit.
>   JavaScript
    TypeScript
```

注意点として、Select a framework: で "Vue" を選んでしまうと Vue3.x が入ってしまいます。ここでは Vue.2.7 を使いたいので "Vanilla" を選びあとから Vue2 を入れます。

# Vite サンプル画面の表示確認

```
cd vite-project
npm install
npm run dev
```

http://localhost:5173/ にアクセスし、以下のような Vite のサンプルページが表示されることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90225/78b16ab3-7351-4609-84c4-e79735aea602.png)

# Vue2.7 化
## Vue2 のインストール
```
npm install vue@2.7.14
npm install -D vite
npm install -D @vitejs/plugin-vue2
```
## vite.config.js の作成
```
touch vite.config.js
```

vite.config.js ファイルの中身は plugin-vue2 の公式リポジトリのドキュメント通りにします。 
https://github.com/vitejs/vite-plugin-vue2 

```:vite.config.js
// vite.config.js
import vue from '@vitejs/plugin-vue2'

export default {
  plugins: [vue()]
}
```

## サンプルソースを Vue で書き直す

このまま実行しても相変わらず Vite のサンプルが表示されるだけなので、以下のように書き換えます。

```:main.js
import Vue from 'vue/dist/vue.esm';

new Vue({
    el: '#app',
    data: {
        message: 'Hello World'
    },
    template: `<div>{{message}}</div>`,
})
```

これで実行します。

```
npm run dev
```
以下のような簡素な Hello World が表示されればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90225/4e9ab236-1d65-e1a8-24ff-75115b5ccd0f.png)


以上になります。
「デカ文字」シリーズまとめ(SSD1306)(Arduino UNO)


目的
SSD1306を使用
秋月　P-12031 白色　128x64 アドレス3C
秋月　AL12832AWWB-H-U02 白色　128x32 アドレス3C
文字を全体的に表示して視認性を上げる
「時計」と「温度計」

---------------------------------------------------


時計


https://qiita.com/caa45040/items/bf68082602b107aa65b8



https://qiita.com/caa45040/items/28a42326026a28b1edf1


---------------------------------------------------


温度計



https://qiita.com/caa45040/items/d146ff39039876ccfa58



https://qiita.com/caa45040/items/9b9edbef3ca42c940ae0
【TestCafe】windowを2つ開いてテストを行う

## 現状
Reactアプリを作成して、TestCafeでテストを行っています。
テストを行うにあたって、ウィンドウを2つ出してテストを行う必要があったのでメモとして残しておきたいと思います。

### やってみる
ウィンドウを2つ出してテストを行う必要があるときというのは動作している間に他の処理を行うなどがあると思います。
そのときに使えるのが`openWindow`になります。
イメージとしては以下の通りにできます。
window1で捜査しているときに`openWindow`を使うことで、任意のwindow2を開くことができ、そこで自由に操作することができます。
![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884542/a01cfa72-73c6-0ce7-9362-5732cf9c2580.png)

公式のURL→https://testcafe.io/documentation/402694/reference/test-api/testcontroller/openwindow

### サンプルコード
サンプルコードをChatGPTに書いてもらいました
```typescript
import { Selector } from 'testcafe';

fixture`Open Window Test`
  .page`http://example.com`;

test('Open new window', async t => {
  const newWindow = await t.openWindow('http://example.com/newpage');

  // Switch to the new window
  await t.switchToWindow(newWindow);

  // Perform actions on the new window
  await t.typeText('#new-page-input', 'Test Text');

  // Switch back to the original window
  await t.switchToPreviousWindow();

  // Verify that the original window is active
  await t.expect(Selector('#new-page-input').exists).notOk();
});

```

`このテストでは、最初のfixtureでexample.comにアクセスします。テストでは、openWindowメソッドを使用して新しいウィンドウを開き、そのウィンドウでアクションを実行します。switchToWindowメソッドを使用して、テストの実行を新しいウィンドウに切り替え、switchToPreviousWindowメソッドを使用して、元のウィンドウに戻ります。最後に、オリジナルのウィンドウがアクティブであることを確認するために、元のウィンドウの存在を確認します。`
初心者Kagglerが初コンペに参加してみた。

超初心者Kagglerが
GoDaddy - Microbusiness Density Forecasting
に参加してみたので感想を書いてみました。

成績は＝　3,318 teams　参加で、2991位です。。。

![reygfgff.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3088680/6fd73ec8-9555-2955-ecd4-ef4c8ce663f2.png)


# コンペの内容は？

コンペティションの目標
このコンペティションの目的は、ある地域の月別マイクロビジネス密度を予測することです。あなたは、米国の郡レベルのデータで訓練された正確なモデルを開発することになります。

あなたの仕事は、政策立案者がマイクロビジネス（非常に小規模な事業体の増加傾向）を可視化するのに役立つでしょう。追加された情報は、これらの小規模ビジネスの成功と影響を改善するための新しい政策やプログラムを可能にします。

https://www.kaggle.com/competitions/godaddy-microbusiness-density-forecasting

ということで、予測系のコンペでしたが、
8か月先までの　Microbusiness Density　を予測するということで、
自分にはかなり難しかったですね。

## 予測に使用したもの
LightGBM と XGBoost の回帰分析を使用しました。
しかし経験不足もあってうまくいきませんでした。

ラグ特徴量やローリング特徴量を作成しても、実際に予測モデルを作成すると
1つ期間をずらしたラグ特徴量ばかりが使われてしまい、
その結果、予測値がすべて同じになってしまいました。

おそらくですが、自分の製作したモデルは期間の特徴を把握しておらず、
月ごとのMicrobusiness Density　のゆらぎというか誤差を全く分析できない
モデルになってしまったのかな？と考えていますが、よくわかりません。　


![57ughj.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3088680/667b7c6e-dce9-4f6d-cc8c-14b4e994ff4f.png)


### 上級者KagglerはLightGBMでも予測できているようだ。
コンペのCodeを公開している人が結構いるのでCodeの中身を見せてもらったのですが、
やり方次第でLightGBMなどでも十分予測ができるようだ。

自分としてはARIMAXやSARIMAX,Prophetあたりを使わないと予測できないんじゃないか？
と考えていたので、実に興味深かったです。


### 初心者が書いたコード。
人に見せる用には制作していません。
https://www.kaggle.com/code/yuujapan/ver2-godaddy-microbusiness-density-forecasting

![ythghf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3088680/8d5712e3-c53d-a910-65d8-3db29ed32e41.png)

Microbusiness Density　が40以上だとあまり回帰しない。
Microbusiness Density　の平均は3.8くらいだったので、離れすぎると予測ができない。
ということで、無理やりMicrobusiness Densityを3.0を上限にして、
残りを後から足すという方法をとってみました。

最初は単純に、Microbusiness Density　40　以上のデータを切り捨ててモデル制作をしていましたが、
最終的に切り捨てない手法を採用しました。

![kukjjjh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3088680/0323537f-579e-4230-78e3-0f8ab72d1216.png)


### ランキング上位者はスタッキングを駆使しているもよう
LightGBM
XGBoost
CatBoost
のスタッキングが多いようですね。
配列の要素の最大値、最小値、合計、平均

***python3***で配列の要素の最大値、最小値、合計、平均を求めるプログラムを実装しました。

```Python3
# 新規作成 2023/3/7
# 配列の最大、最小、平均、並び替え

scores = [30,20,70,40,10,50]
num = 0
pot = 0


while True:
  try:
    num1 = int(input("整数を1つ入力してください"))
    num = num1
    break
  except:
    print("整数を入力してください")

# 配列を1つ追加
scores.append(num1)

while True:
  try:
    w_n = len(scores)
    num2 = int(input(f"0から{w_n}までの整数を1つ入力してください"))
    if num2 < 0 or num2 > w_n:
      raise ValueError
    pot = num2
    break
  except:
    print("整数を入力してください")
# 配列の要素を1つ削除
scores.pop(pot)
print(scores)
#配列の要素の最大値
print(max(scores))
#配列の要素の最小値
print(min(scores))
#配列の要素の合計
print(sum(scores))
#配列の要素の平均
avg1 = round(sum(scores) / len(scores),1)
print(avg1)

```
CKA試験、Node

# Node

- ノードに新たなPodを作成できないようにする
```shell
kubectl cordon <ノード名>
```

- ノードに新たなPodを作成できるようにする
```shell
kubectl uncordon <ノード名>
```

- 特定のノードから実行中のPodをなくす
- ノードに新たなPodを作成できないようにする
```shell
kubectl drain <ノード名> --ignore-daemonsets -force
```


# Node Schedule

次の条件を持つPodを作りなさい
- Pod名： eshop-store
- image: nginx
- Node selector: disktype=ssd

```sh
kubectl run eshop-store --image=nginx --dry-run=client -o yaml > 8.yaml

vi 8.yaml
```

```(修正前) 8.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: eshop-store
  name: eshop-store
spec:
  containers:
  - image: nginx
    name: eshop-store
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
```

```(修正後)　8.yaml
apiVersion: v1
kind: Pod
metadata:
  name: eshop-store
spec:
  nodeSelector:
    disktype: ssd
  containers:
  - image: nginx
    name: eshop-store

```

```sh
kubectl apply -f ./8.yaml
kubectl get pods eshop-store -L disktype
```
[WordPress] コメントを無効にする

WordPress でコーポレートサイトなどを作成し場合、コメント機能は不要なので無効にしておきたいのですが、よく忘れるのでメモ。

コメント機能の無効化は wp-cli で

```shell
wp option update default_comment_status closed
wp option update default_ping_status closed
TABLE_PREFIX=$(wp eval 'global $table_prefix; echo $table_prefix;')
wp db query "UPDATE ${TABLE_PREFIX}posts SET comment_status='closed', ping_status='closed';"
```

Nginx に設定追加して `/wp-comments-post.php` へのリクエストも無効化しておけばなお良い

```nginx
location ~* /wp-comments-post\.php$ { deny all; }
```
ChatGPTにコードを書かせてみた。

# はじめに
ChatGPTはコードも生成できますので、人間がだいたいの指示を与えて、ChatGPTにコードを書かせて実行すればよいのではないかと考え、試してみました。

# やること
「この文章を出力するコードはChatGPTが書きました」というコードを問い合わせるコードをコード内に設けて、ChatGPTから回答があったコードを実行するというコードを作成します。

# プログラム
ChatGPTのAPIを使用します。

メッセージは、{"role": "user", "content": "「この文章を出力するコードはChatGPTが書きました」という文を出力するコードを教えてください。コードのみの記載で結構です。"}]としました。

「コードのみの記載で結構です。」と一言加えませんと、余計な文章も生成され、エラーとなりました。
```python
# パッケージのインストール
! pip install openai
import openai
#import os

# Google Driveに接続する
from google.colab import drive
drive.mount('/content/drive')

# テキストファイルからAPI_KEYを読み込む
with open('/content/drive/MyDrive/OpenAI API KEY.txt', 'r') as f:
  openai.api_key = f.read().strip()

response = openai.ChatCompletion.create(
  model="gpt-3.5-turbo",
  messages=[
    {"role": "user", "content": "「この文章を出力するコードはChatGPTが書きました」という文を出力するコードを教えてください。コードのみの記載で結構です。"}],
  temperature=0.50, # ランダム性　高いと多様　0から1
  max_tokens=1000, # レスの最大トークン数
  #top_p=1.0, # 多様性制御　１が最大　temperatureとの併用は推奨されない
  frequency_penalty=0, # 低いと多様　-2から2
  presence_penalty=0, # 低いと多様　-2から2
)
print(response["choices"][0]["message"]["content"])
```
ChatGPTの回答は以下となります。文書出力に必要なコードのみが出力されました。

```:出力
print("この文章を出力するコードはChatGPTが書きました")
```

# exec関数の実行
次に、chatGPTが生成したコードをexec関数により取り出し実行します。

コードの説明は以下の通りです。
・response["choices"][0]["message"]["content"]から取り出したコードを変数code_to_executeに代入します。
・exec()関数を使用して、code_to_executeに格納されたコードを実行します。
・exec()関数はPythonのビルトイン関数で、引数に与えられた文字列をPythonコードとして評価・実行します。
・実行する前に、コードが信頼できるものであることを確認することが重要です。悪意のあるコードを実行すると、システムに深刻な問題を引き起こす可能性があります。

```python
code_to_execute = response["choices"][0]["message"]["content"]
exec(code_to_execute)
```
出力は以下となりました。「この文章を出力するコードはChatGPTが書きました」という文を出力することができました。
```:出力
この文章を出力するコードはChatGPTが書きました
```
# 感想
ChatGPTにコードのみ出力させることにより、コード内でコードを生成させ、実行させることができました。

今回は初歩的なコードのみとしましたが、これを応用すれば、複雑なコードもコード内で生成させることもできるのではないかと思います。そうしますと、コード内で日本語のたいだいの指示のみでコードがつくられるようなこともできるかもしれません。
LINEとChatGPTでAIカノジョNeon(AI彼女ねおん)のプロトタイプを作ってみた感想や課題

# ▼AIカノジョNeon(AI彼女ねおん)事前登録はコチラ▼
https://lin.ee/fLwRzgm

![S_gainfriends_2dbarcodes_GW.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3241882/1c093533-8c1e-dc0f-e801-6770b83a4343.png)

# LINEでAIカノジョNeon(AI彼女ねおん)を作った背景や目的
多くの日本人が意外と本家のchatgpt に辿り着いてないこと(うちの父は完全別のアプリで危うく月数千円の課金しかけてましたw)と、使いやすさや浸透具合が高くおすすめしやすいので、LINEで作ることにしました。

# AIカノジョNeon(AI彼女ねおん)の機能や特徴
## ①あえて回答を遅く(こちらは現在改善しております。)
好みだと思うのですが回答が早すぎると、やはりBOTくささが出てしまうので、かなり遅めに回答するようにしています。ただ遅すぎるとLINE側でタイムアウトになるようです。

## ②ワンパターン回答には乱数を噛ませる
ユーザーがスタンプ使って来たときは謝るようにしてます。その回答は数パターン用意してます。

## ③モデル
gpt-3.5-turbo 他のモデルとどの程度違うかはまだ検証してません。

## ④性格
ここも好みですが、明るく、カワイイ、にしました。
(なんかやたらにゃんを使うようです。)
ツンデレだと語尾にバカというをワードを連発しがちなので、
うまく調整しないと、ありきたりすぎるキャラかなと思い保留。

# AI彼女とのコミュニケーションの難しさ
言われてみれば当たり前なのですが、スタンプと写真の挙動はなんとかしたいですね。画像として解析するのはちょっと大変かも？
また噂の感情パラメーターを指示しても、systemで性格をいじってるせいかムラがあるので、一旦保留。区切り文字で抜き出せば行ける気がしていましたが甘くなかったです。
またsystemで文字数制限を指示すると、変なところで回答が切れますね。tokenの制限も関係してそう。

# 身内からのフィードバック
①男性A…文字が切れるから分割して回答してほしいとのこと。(過去参照でおそらく解決)
②女性A…スタンプ送って返ってこないね。(ここは一旦謝罪返答するように。)
③女性B…凄いんじゃない？使ってみるね。

# AI彼女ねおんの課題
まずはユーザーの識別や、過去の回答の参照機能が必要で、オリジナルの内部パラメーターも予定してるので、当然ながらDBを使った方が良さそう。
LINE側のパラメーターや仕様が読み切れてないのもあり、いい感じにDBなしでいけた方は是非情報をお待ちしております。

あとは人間らしい振る舞いをどうつけるかは、設計と工夫のしがいがありそうですね。
突貫でまだまだプロトタイプですが
時間がないので、メモ程度の駄文ですみません。

現在、一旦プロトタイプを停止し、事前登録受付中です。

ドンドンブラッシュアップしていきますので、ご意見お待ちしております。
Deep Double Descent: 丸暗記付近で、テスト損失が一度上昇

https://arxiv.org/abs/1706.05394
Submitted on 4 Dec 2019
Cited by 557
OpenAI

# 結論
* Model-Wide DD
    * **critical params = ちょうど丸暗記ができる能力付近**で、一度テスト損失が上昇する
    * **ノイズは損失上昇を大きくする**
* Epoch-Wise DD
    * critical paramsで、ちょうど丸暗記しそうなエポック付近で、一度テスト損失が上昇する
    * ノイズは損失上昇を大きくする

# 感想
* **中途半端なモデルサイズはノイズに弱い**
    * 実務では小さく有効性を確認して、どかっと大きくする
    * EMCは分からない...が、例えばbertでは6mデータに対して110mパラメター
* なぜcritical paramsでテスト損失上昇するのか、背景は語られていない。
    * **トレーニング損失が0になる前後で、テスト損失が上昇**
    * **後続論文では、ノイズがDDの条件と提起されている** ノイズが大きいとciritical params超えてoverparamsでも、DD起こる。個人的には実務上の感覚とも合う
        * 当論文では、ノイズはDDの条件とされていない。バイアスバリアンスで説明される
    * **ノイズがまずパターン学習としてされる問題**（多様体としての次元・半径が大きく、テスト時のサンプルに適用されてしまう問題）と、とりあえず理解

# 詳細
* パラメター軸でもエポック軸でも、テスト損失が存在する薄い谷が見える
![Screen Shot 2023-03-04 at 16.23.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123768/540a311f-5b20-2ab3-6e9e-d20d56957b43.png)

### Model-Wise DD
* ノイズがなければ、損失上昇はないように見える
    * CIFAR-100にはそもそもノイズが含まれる
![Screen Shot 2023-03-07 at 10.13.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123768/a8351e64-a8bd-740b-1ffd-7e0c1f766a8f.png)


### Epoch-Wise DD
* ノイズがなければ、損失上昇はないように見える
![Screen Shot 2023-03-07 at 10.14.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123768/ee242cb3-9656-4491-e5fa-f68eba5346a8.png)
paiza.ioでnadesiko その12

# 概要
paiza.ioでnadesikoやってみた。
練習問題、やってみた。

# 練習問題
九九を書け。

# サンプルコード

```


iを１から9まで繰り返す
    jを１から9まで繰り返す
　　    i * jを継続表示
　　    「　」を継続表示
    ここまで。
　　「」を表示。
ここまで。

```

# 実行結果

```
1　2　3　4　5　6　7　8　9　
2　4　6　8　10　12　14　16　18　
3　6　9　12　15　18　21　24　27　
4　8　12　16　20　24　28　32　36　
5　10　15　20　25　30　35　40　45　
6　12　18　24　30　36　42　48　54　
7　14　21　28　35　42　49　56　63　
8　16　24　32　40　48　56　64　72　
9　18　27　36　45　54　63　72　81　

```

# 成果物

https://paiza.io/projects/4EIv7OstnCBAGCF0os3fEQ?language=nadesiko


以上。
paiza.ioでnadesiko その11

# 概要
paiza.ioでnadesikoやってみた。
正規表現、やってみた。


# サンプルコード

```

「2020年08月09日」を「/(\d+)年(\d+)月(\d+)日/」で正規表現マッチ
それを表示。
抽出文字列[0]を表示。
抽出文字列[1]を表示。
抽出文字列[2]を表示。


テスト文＝「あああああ
#いいいいい
ううううう」
パターン＝「\A#」
テスト文を反復
	対象をパターンで正規表現マッチ
	もし、それが空でなければ、
		対象を表示
	ここまで
ここまで


「マーチ」を「m/ー/k」で正規表現マッチ
表示

「02:50:30」を「(\d+):(\d+):(\d+)」で正規表現マッチ
それを表示。
抽出文字列を表示。




「abc:def:ghi」を「[a-z]+」で正規表現マッチ
表示 # abc
「2005:10:15」を「\d+:\d+:\d+」で正規表現マッチ
表示 # 2005:10:15

抽出文字列は「abc:def:ghi」を「(.+)\:(.+)\:(.+)」で正規表現マッチ
表示。#abc:def:ghi


抽出文字列[0]を表示 # abc
抽出文字列[1]を表示 # def
抽出文字列[2]を表示 # ghi


```

# 実行結果

```
2020年08月09日
2020
08
09
あ
あ
あ
あ
あ


#
い
い
い
い
い


う
う
う
う
う
null
02:50:30

abc,def,ghi
2005:10:15
abc:def:ghi
abc:def:ghi
undefined
undefined

```

# 成果物

https://paiza.io/projects/Jq8_48q-dHtNAZjdziqyXg


以上。
TVTest + tvtPlay で 起動時にファイル選択ダイアログを出す

# 環境

- Windows11 Home
- TVTest 0.10.0 64bit
- tvtplay ver.2.8

https://blog.tsukumijima.net/article/tvtest-usage/ の、「TvtPlayのセットアップ」 に基づいて、ファイル再生のみを用途とした設定を行っている状態

ショートカットのリンク先設定に、` /tvtplay`  を書き足して起動時に tvtplay が有効になるようにしている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/bad7c017-6cc4-f957-3ffd-c5b803a6c1af.png)



#  tvtplay.ini 

以下のオプションを設定する

```
ShowOpenDialog=1
```

ドキュメントによると、

> ShowOpenDialog【ver.1.2～】
    プラグイン有効時に「ファイルを開く」ダイアログを表示する[=1]かどうか
    # /tvtpudp /tvtpipeと組みあわせて利用するとTVTestのチャンネル選択画面などで
    # 便利かもしれません。

設定し、起動するとファイル選択ダイアログが表示されるようになった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/1140ba08-8bfe-96c8-0ad0-27a9ecf5e15d.png)
（Flutter）Google Maps PlatformのiOS用APIキーの隠蔽と利用

google_maps_flutterをiOSで使う場合、Google Maps Platformから発行されたAPIキーをAppDelegate.swiftに書き込む必要があります。
https://pub.dev/packages/google_maps_flutter#ios

ただ、
- APIキーをswiftコードにハードコーディングするのは嫌
- Android側と設定ファイルをひとつにまとめておきたい

の両方を実現する方法がなかなか見つからず苦戦しました。
（実際にはSwiftやiOSアプリ開発への知識が皆無だったため遠回りした感はありますが）
また、日本語記事の情報がほとんど見つからなかったので、非常に簡記ながら投稿しておくことにしました。

Android側の設定については、既にdart-define-from-fileを使っていました。
dart-define-from-fileの使い方は、[このサイト](https://zenn.dev/altiveinc/articles/separating-environments-in-flutter#ios%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AB%E7%92%B0%E5%A2%83%E3%82%92%E5%8F%8D%E6%98%A0%E3%81%95%E3%81%9B%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AB%E5%BF%85%E8%A6%81%E3%81%AA%E3%81%93%E3%81%A8)が平易に書かれておりわかりやすかったです。

上サイトでもiOSについての記述もありますが、肝心のAppDelegate.swiftへの反映の仕方がよくわかりませんでした。
で、見つけたのが[こちら](https://codewithandrea.com/articles/flutter-api-keys-dart-define-env-files/)と[こちら](https://medium.com/flutter-community/how-to-setup-dart-define-for-keys-and-secrets-on-android-and-ios-in-flutter-apps-4f28a10c4b6c)

要は、
1. dart-define-from-fileでAPIキーを書いたJSONファイルを読み込む
1. JSONファイルで指定したキーでinfo.plistへ設定値を取得
1. info.plistで指定したキーでAppDelegate.swiftへ設定値を取得

という感じでAppDelegate.swiftへAPIキーを注入できるようです。

サンプルコード
``` dart-define/env.json
{
    "apiKey":"APIキーを書いておく"
}
```

``` info.plist
<dict>
    ・・・
	<key>API_KEY</key> 
	<string>$(apiKey)</string>
    ・・・
</dict>
```

``` AppDelegate.swift
import UIKit
import Flutter
import GoogleMaps

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    let apiKey = Bundle.main.infoDictionary!["API_KEY"] as! String
    GMSServices.provideAPIKey(apiKey) // google_maps_flutterで利用する場合
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}
```
Javaを基本からまとめてみた【分岐処理・繰り返し処理】

## 構造化プログラミング

構造化プログラミングとは、下の構造を組み合わせてプログラムを書くことをいう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/c3af9a96-2432-ad9e-40c3-df4f9ca5746b.png)


## (1) if文

```
if(条件式){

    『処理１』

} else {

    『処理2』

}
```
- 何方かの処理しか実行されない
- else以降は省略可
- 処理が1つの時は{ }を省略可


```Sample.java
public class Branch {
    public static void main(String[] args) {
    int price = Integer.parseInt(args[0]);
    double rate = 0.10; //消費税率:10%
    int discount, amount;
    
        if (price >= 3000) { //値引額の設定
            discount = 300;
        } else {
            discount = 0;
        }
    amount = (int)((price - discount) * (1 + rate));
    System.out.println("値引金額:" + discount + "円"); 
    System.out.println("税込金額:" + amout + "円"); 
    }
}
```
## (2) else-if文

```
if(条件式){

    『処理１』

} else if(条件式2){

    『処理2』

} else {

    『処理3』

}
```
- 条件式は上から順に判定

```Sample.java
public class Branch {
    public static void main(String[] args) {
    int price = Integer.parseInt(args[0]);
    double rate = 0.10; //消費税率:10%
    int discount, amount;
    
        if (price >= 5000) { //値引額の設定
            discount = 500;
        } else if (price >= 3000){
            discount = 300;
        } else {
            discount = 0;
        }

    amount = (int)((price - discount) * (1 + rate));
    System.out.println("値引金額:" + discount + "円"); 
    System.out.println("税込金額:" + amout + "円"); 
    }
}
```

## (3) switch文

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/c0ed4bb9-a4c5-414d-1266-cebb52814caf.png)

```
if(条件式１){

  case 値１:
    
    『処理１』
  
break;
  
  case 値2:
    
    『処理2』

break;

default:
    
    『処理3』
}
```
- 式は『byte』『short』『int』『char』のみ
- 式の値によって処理の開始位置が決まる
- breakは{]を抜ける
- 値がどの条件値にも当てはまらない場合の処理を、switch文で書きたい時に使うのがdefault

```Sample.java
public class Branch {
    public static void main(String[] args) {
    int num = Integer.parseInt(args[0]);
    switch(num) {
   case1:
     System.out.println("入園料金：8,400円"); 
     break;
   case2:
     System.out.println("入園料金：7,000円"); 
     break;
   case3:
     System.out.println("入園料金：5,000円"); 
     break;
    dafault: 
      System.out.println("1:一般、2:中・高校生、3:小学生・幼児"); 
      }
   }
}
```
## (4) while文

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/bb3c833b-3bbb-da75-620d-876d0914ee68.png)

- ある条件が満たされる間ずっと処理を繰り返す

```
while(条件式){
  
  『処理』

}
```
```sample.java

class Loop1 {
  public static void main(String[] args) {
    int i = 0;
    while(i < 3){
        System.out.println("i =" +i); 
    i ++;
  }
 }
}
```
## (5) for文

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/f2f54686-68f7-a170-a1d4-1ebf81e6cbdd.png)

- 繰り返しの回数が決まっている
- 配列の各要素に対して何かをしたりする時

```
for(式１; 条件式:式２)

    『処理』
}
```
```sample.java

class Loop1 {
  public static void main(String[] args) {
    for(int i = 0; i < 3; i++){
　System.out.println("i =" +i); 
}
}
```



## 参考サイト
[Javaの分岐処理：if、else-if、switchの書き方・使い分けを初心者向けに解説！【Java入門講座】2-8 分岐処理](https://www.youtube.com/watch?v=CTdnHs0gfe0)
[Javaの繰り返し処理：while、forの書き方・使い分けを初心者向けに解説！【Java入門講座】2-9 繰り返し処理](https://www.youtube.com/watch?v=r1Tc8Nr_4_w)
File Storage(Classic)でSnapshotが閾値を超えた際の通知

特に新機能では無いが、試す機会があったのでメモ。

IBM Cloud Classic InfrastructureのFile Storage/Block StorageにはSnapshot機能がある。
サーバーからマウントして利用するデータ領域とは別にSnapshot領域をオーダーして利用するが、そのSnapshot領域の利用率が75%/90%/95%を超えると通知される。また、95%を超えると、古いSnapshotから自動的に削除される。
https://cloud.ibm.com/docs/FileStorage?topic=FileStorage-managingSnapshots&locale=ja&interface=ui#listsnapshotUI

大容量ファイルの書き込みや削除を行いながらSnapshotを繰り返し、閾値を超える状況を作り出し、実際の通知やメールがどのようなものかを確認した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59627/4a343eed-2785-4786-45e6-fa26ac783499.png)

ポータル上は、Notificationのページに通知される。
https://cloud.ibm.com/notifications

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59627/d4d8ae74-1609-6d37-674d-fae090fa6a14.png)


下記のDistribution Listに登録しておくとメールでも届く。
https://cloud.ibm.com/account/notifications-distribution-list

閾値（75%）越え
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59627/4031ffd7-922e-1d93-5fe0-b8b61394b549.png)

閾値(90%)越え
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59627/348ec6f8-e60a-6c75-1efa-18d481179409.png)

95%を超えたため自動削除
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59627/60624f73-db7f-7bc3-9e2e-88cf0a467122.png)

以上
パワポの画面を正方形で作る

パワーポイントは通常、4:3 か 16:9 の横型となるが、縦型や正方形にすることもできる。
デザイン → スライドのサイズ → ユーザー設定のスライドサイズ
にて設定。
幅、高さ の長さを同じにすると正方形の画面で資料を作ることができる。

縦長の資料は、どうしてもWordではなくPowerPointで資料を作りたい場合で、縦長の資料を作成したい際に使える。

正方形の画面を何に使うかというと、アニメーションを駆使して動画を作って、正方形の動画をExportするため。
Instagram は横長動画は左右が切られて正方形になるが、最初から正方形の動画で作ることで、Twitter でも同じ動画をアップすることができる。
GitHub Actions を利用し ".rubocop_todo.yml" を自動更新する


## はじめに

普段開発をしていると、定義ファイルや設定ファイルの更新を行う機会は少なくありません。
".rubocop_todo.yml" を更新するような単純作業は機械にまかせていきたいなと思いこの記事を書きました。

## どのように実現するか

GitHub Actions には 定期実行を行う機能が存在します (`on.schedule`)
定期実行した job の中で `rubocop` を実行し生じた差分を利用し Pull request を作成します。

今回は `peter-evans/create-pull-request` を利用します。

https://github.com/peter-evans/create-pull-request

### GitHub Actions の設定例

`.githu/workflows` directory 以下に ファイルを作成します
yml に記載している 処理は以下の通りです。

- repository を checkout
- Ruby の install & bundle install
- rubocop の実行
- Pull request の作成

```yml:.githu/workflows/update_rubocop_todo.yml
name: Update .rubocop_todo.yml

on:
  schedule:
    - cron: "0 1 * * 1-5"
  workflow_dispatch:

permissions:
  contents: write
  pull-requests: write

jobs:
  export_emoji:
    runs-on: ubuntu-latest
    defaults:
      run:
        shell: bash
    steps:
      - uses: actions/checkout@v3
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.0'
          bundler-cache: true
      - run: bundle exec rubocop --auto-gen-config --auto-gen-only-exclude --no-exclude-limit
      - uses: peter-evans/create-pull-request@v4
        with:
          commit-message: Update .rubocop_todo.yml
          delete-branch: true
          title: Update .rubocop_todo.yml
          reviewers: mziyut
```

上記 yml を main (master) branch 等に push し、定義した時間まで待つか、 Actions 内から手動実行すると
以下のような Pull request が作成されます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55950/5500a45e-7f34-ee00-6395-faa281fa5bc8.png)

## さいごに

- 今回は、 rubocop を例に記載しましたが、 rubocop 以外にも適用できます
- 自動化して時間を使うべきところに使えるようにしたいですね

## References

- [peter-evans/create-pull-request: A GitHub action to create a pull request for changes to your repository in the actions workspace](https://github.com/peter-evans/create-pull-request)
- [ruby/setup-ruby: An action to download a prebuilt Ruby and add it to the PATH in 5 seconds](https://github.com/ruby/setup-ruby)
paiza.ioでnadesiko その9

# 概要
paiza.ioでnadesikoやってみた。
練習問題、やってみた。

# 練習問題
zundokoを書け。

# サンプルコード

```


「ズン,ドコ」を「,」で区切って、ずんどこへ代入
全体は空
番目は、２の乱数
全体は全体に、ずんどこ@番目を、追加
Ａは０
（Ａ＜29）の間
　　Ａ＝Ａ＋１
    番目は、２の乱数
    全体は全体に、ずんどこ@番目を、追加
    流れは全体の、１０だけ文字右部分
    もし、流れが、「ズンズンズンズンドコ」　ならば
        Ａ = 30
    ここまで
ここまで
全体を表示
「キ・ヨ・シ！」を、表示




```

# 実行結果

```
ズンズンズンズンズンズンズンズンズンズンドコ
キ・ヨ・シ！
```

# 成果物

https://paiza.io/projects/8bxFL0CzFxs-TjQa2ogVgg


以上。
AWS Hands-on for Beginners　手を動かしなら学ぶ Analytics サービス入門：学習メモ

## はじめに

AWSハンズオン for Beginnersシリーズとして提供されている「[AWS Hands-on for Beginners 手を動かしながら学ぶ Analytics サービス入門](https://pages.awscloud.com/JAPAN-event-OE-Hands-on-for-Beginners-Analytics-2022-reg-event.html?trk=aws_introduction_page)」を実施した際のメモです。
データを活用する目的は、ビジネスの意思決定をするためです。
データ量が少なければ、表計算ソフトなどで可視化可能ですが、大容量となるとデータレイク、データウェアハウスなどを構築する必要が出てきます。
本ハンズオンでは、AWSのデータウェアハウスサービスであるAmazon Redshiftを使用し、データのロードをしたり、クエリを発行して結果を受け取ることを試してみます。また、Amazon QuickSightを使用して、Redshift内のデータの可視化も行います。

## アジェンダ

1. 今回のハンズオンで構成する構成等の紹介
2. ハンズオンで構築する構成の紹介、インスタンスの作成を行う
3. Amazon Redshift クラスターのセットアップ
4. Amazon Redshift クラスターへのデータロード
5. Amazon Redshift に対してクエリ実行
6. Amazon QuickSight の概要
7. Amazon QuickSight のセットアップ
8. Amazon QuickSight を用いた可視化
9. 本シリーズのまとめと次のステップ
10. ハンズオン環境削除方法

## メモ

### 分析手法とデータウェアハウス

分析対象のデータの規模によって手法を変える必要があります。
例えば、表計算ソフトでは企業単位のデータを扱うことが難しい、これはデータの転送時間やデータの共有などに大きく影響するためです。
RDBMSを使うと言う手もありますが、それでも対応できない規模のデータ(1TB以上)がある場合、データウェアハウスを使用することになります。
データウェアハウスは目的に合わせて加工済みのデータを格納します。

### データの収集から分析、可視化まで流れ

```
アプリ＝＞OLTP DB＝＞ETL＝＞OLAP DB＝＞BIツール
※本ハンズオンではOLAP DBからBIツールまでの流れを体験する。
```

### OLTP

ECサイト、ゲームアプリでよく使用される。
リアルタイム性、同時使用、高いレスポンスを備える。
検索、更新するデータ量は少ない場合が多い。

### OLAP

大量のデータを複雑なクエリで分析する場合が多い。
同時に使用されることは少ない。
リアルタイム性は求められない場合が多い。

### OLAPとしてのRedshift

Redshiftは列指向データベースです。行指向と異なり特定列のデータのみデータの取得分析が可能であり、効率が良いです。
Redshiftへの接続はクエリエディタから行います。
クエリエディタからSQL文を実行し、テーブル作成、データをSelectします。
クエリエディタのタブ1つに対して、クエリは1つしか実行できません。
用意されたDDLを実行するとusersテーブルはすでにあるとエラーがでました。クエリエディタを確認するとusersの他、salesなどのテーブルがすでに存在しているというものでした。おそらく、データベースをdevにしているため、サンプル用としてこれらテーブルがすでに用意されていると考えました。そのため、当該テーブルを手動で削除の上、ハンズオンを進めました。
RedshiftにはRDBと同じくスキーマという概念があります。デフォルトはpublicです。

### Redshift データロードベストプラクティス

S3にデータを配置して、COPYコマンドを使用し、Bulk Loadする方法が効率よくデータをロードするベストプラクティスとされます。

```
COPY [テーブル名] FROM [S3パス] IAM_ROLE [IAMロールのARN];
```

- テーブル毎に1つのCOPYコマンドを実行します。
- データは複数ファイルに分割した方が効率良いです。
- データファイルはGZIPなどで圧縮すると転送効率がよくなります。
- 1ファイルあたり圧縮後、1MBから1GBに収まるサイズにすると転送効率がよくなります。

### Redshiftで使用できるSQL構文

データを取得するクエリはSQL構文を使用できます。
SELECT
FROM
GROUP BY
ORDER BY
SUM
サブクエリ
テーブルの結合も可能です。

### 　QuickSight

QuickSightは様々なAWSサービスと連携し、データを可視化できるサーバレスBIサービスです。
高速なインメモリデータベースであるSPICEを保有しているため、QuickSightのみでも、CSVをブラウザやS3から取り込んでBIできます。

### 　　QuickSightパフォーマンス

大量にデータがある場合、データはRedshiftに保存した方が効率良くなります。QuickSightはRedshiftからデータをクエリし、BIできます。
また、インメモリデータベースであるSPICEにクエリ結果をキャッシュし、パフォーマンスを上げることができます。

### 雑記1

現在、Standard版はなく、エンタープライズ版とエンタープライズ+Q版しかありませんでした。
後者を選択してみましたが、名前、電話番号入力後の画面で強制的に前画面に戻されてしまい、選択できませんでした。

### 雑記2

Redshiftの自動接続を使用してみたところ、権限がないとエラーになってしまいました。そのため、手動接続で実施しました。

### 雑記3

Redshift（クラスタ）、QuickSightともにセキュリティグループを設定できます。今回は各SGのインバウンドルールにそれぞれのセキュリティグループをソースとして追加し、相互接続を可能にしました。
QuickSightコンソールから配置するVPCサブネットを設定します。

### 雑記4

データ分析基盤は後々のニーズや拡張性を考慮し、疎結合であるべきです。つまり、データの蓄積、データの加工は1つの機能にまとめるのではなく、別々で管理すべきです。

### データレイク

加工済みのデータを蓄積するのがデータウェアハウスです。必要なデータをすぐに分析できますが、様々なニーズに対応することが難しいとされます。
一方、データレイクは未加工のデータを蓄積し、必要な時にそれを加工し、分析する機構です。
データレイクの条件として、データを一元的、多様に管理できること、データを失わないことなどが挙げられ、AWSだとS3がそれを担います。

## ハンズオンの感想

データ分析で使用するAWSサービスRedshift、QuickSightの初歩的な使い方を学ぶことができました。
今後データをビジネスに活用していく動きは多くなっていき、本ハンズオンで得た知識は今後携わるプロジェクトで役に立つと感じます。
paiza.ioでelixir その208

# 概要
paiza.ioでelixirやってみた。
練習問題やってみた。

# 練習問題
openai apiを叩け。


# サンプルコード

```
:inets.start
:ssl.start

token = "sk-****"

json = """
{
  "model": "gpt-3.5-turbo",
  "messages": [{"role": "user", "content": "Hello!"}]
}
"""
{:ok, {{_, _, _}, _, body}} = :httpc.request(:post, {
	'https://api.openai.com/v1/chat/completions', 
	[{'Authorization', 'Bearer #{token}'}], 
	'application/json', 
	json
}, [], [])
IO.puts(body)


```


# 成果物

https://paiza.io/projects/o17WQ57DcyWpqM45gkjFOQ

以上。
EKS ManagedNodeGroupのkubeletのパラメータ変更方法

EKSのManagedNodeGroup(以下MNG)のkubeletのパラメータ変更方法がわかりづらかったので記事にします。
## パラメータ変更方法
MNGで使用するLaunchTemplateのusedataに以下の記述をします。
以下の例は未使用イメージをガベージコレクトするしきい値を変更するものです。

```bash
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="==MYBOUNDARY=="

--==MYBOUNDARY==
Content-Type: text/x-shellscript; charset="us-ascii"

#!/bin/bash
set -ex

# Inject imageGCHighThresholdPercent value unless it has already been set.
if ! grep -q imageGCHighThresholdPercent /etc/kubernetes/kubelet/kubelet-config.json; 
then 
    sed -i '/"apiVersion*/a \ \ "imageGCHighThresholdPercent": 70,' /etc/kubernetes/kubelet/kubelet-config.json
fi

# Inject imageGCLowThresholdPercent value unless it has already been set.
if ! grep -q imageGCLowThresholdPercent /etc/kubernetes/kubelet/kubelet-config.json; 
then 
    sed -i '/"imageGCHigh*/a \ \ "imageGCLowThresholdPercent": 50,' /etc/kubernetes/kubelet/kubelet-config.json
fi

--==MYBOUNDARY==--\
```

LaunchTemplateの変更を行った場合、MNGで管理しているNodeの入れ替えが発生するので注意してください。
Nodeの入れ替え後、以下のコマンドを実行することで設定が反映されているか確認することができます。

```bash
$ kubectl proxy

# 新しく作成されたNodeの名前を入れる
$ node_name=

# 適用されているkubeletの設定が表示される
$ curl -sSL "http://localhost:8001/api/v1/nodes/${node_name}/proxy/configz" | python3 -m json.tool
```

## 参考資料
以下の記事とやり方はほぼ同じなのですがMNGでは `bootstrap.sh` は自動で実行されるので不要でした。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/eks-worker-nodes-image-cache/

MNGでのuserdataの記述方法で `bootstrap.sh` を呼び出す方法も記載されていますが
わざわざ `bootstrap.sh` を実行せずとも、`kubelet-config.json` を編集するだけでよさそうでした。

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/launch-templates.html#launch-template-user-data
基礎の基礎　ターミナルってなんぞ。

【ターミナルとは】
言葉自体の意味は「端末」のこと。通信システム・ネットワークの末端に接続され、他の機器と通信を行う主体となる機器のこと。コンピュータシステムでは利用者が直接操作する機器を指す。
実際は
文字ベースでの入力機能をソフトウェアで再現した「端末エミュレータ」を指すことが多い。

・・・と難しい説明をしてみたが、簡単に言うと人間がポチポチ英語を打ち込んでコンピュータに指示したり反応をもらえたりするソフトのこと。

コマンドはUNIXコマンドやLinuxコマンドと呼ばれる。
普段のパソコンのWindowsやMac OSみたいなOSのこと。

英語ポチポチしてコンピュータを操作する環境をCUI（Charavter　User　Interface）と呼ぶらしいです。

昔はキーボードで操作するコンピュータしかなかったけど
マウスやタッチパネルができた。（便利！）

これはグラフィカル（目でわかる、絵画的）なユーザインターフェイス（コンピュータとユーザとの接点）をGUI（Graphical　User　Interface）という。

【ターミナルを使用するメリット】
画面のいろんなところを見たり、クリックしたりしなくていい。
同じ処理を何回もするのが楽。

【ターミナルを使うデメリット】
いっぱい英語（コマンド）を覚えなきゃいけない。