OmniAICreator/Qiita-1.07M huggingface dataset:
JDLA_E資格の深層学習「設計」

#1. ニューラルネットワークの設計

ある程度NNの概要が分かってきた。ここでNNの設計に関して触れる。

#2. ニューラルネットワークの入力層

ニューラルネットワークへ入力するのは、数値になるデータであればなんでも入力できるが、モデル学習のために入れるデータに関して注意点もある。
画像データでも音声データでもビッグデータでもなんでもそうだが、おかしなデータが入っていると、学習に悪影響を与えてしまう。

##2.1. 入力層への入力データの制限

以下のようなデータを入れないように入力層を設計しよう。

**NNモデルへ入れるべきでないデータ**

1. 欠損値の多いデータ
1. 誤差の大きいデータ
1. 人為的な加工が入ったデータ（偏見の入ったデータ、別のNNの出力）
1. 無意味な数値が入ったデータ

**欠損値の処理**
欠損値を含むデータがあった場合、ゼロ埋め、その行データ自体を除外、その列データ自体を除外などの処理をしよう。


**理想：エンドツーエンドのNN**
いくつかのNNは組み合わせたモデルは、前後のNNがうまく動いていないと全体としてうまく動かない。NNは一つだけで、入力データに対して、NN変換をして、出力が直ぐに得られるモデルをエンドツーエンドのNNモデルという。これが利用である。

**one hot vector**
０か１のベクトルで、１が一つしかないものをone hot vectorという。教師らベル・データとして理想。


#2.2. 入力層のデータ処理

前節のように入力データには、利用する為にさまざまな注意点がある。このため、入力層ではこれらをケアする処理が必要である。

1. 欠損値処理
1. データ結合
1. データの正規化、正則化

#2.3. データの水増し（Dataset Augmentation）

学習データが少ない場合に、なんとかして水増しをしよう。
画像認識のような分類タスクの問題を学習するには、水増しは効果的である。
それ以外は逆効果の場合もあるから注意。

**入力層での水増し手法**

入力層では、データ自体に下記のようないろんな加工をすることで、入力するデータ自体を水増しするようにしよう。

+　回転
+　ぼかし
+　色温度
+　ノイズ
+　拡大・縮小
+　ジグソー

**中間層での水増し手法（データ拡張）**

中間層では、前段では細かい特徴を認識して、後段では、大まかな特徴量をつかむように処理が進む。
このため、中間層で使うデータに対して、適宜ノイズなどを加えてやることで、多くのデータを使った学習を行っているのと同義のことができる。これも水増しの一手法である。

モデルをどうこうするよりも、データ拡張によってデータを増やすほうが、はるかに**性能向上**が期待できる。

![特徴量伝搬.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1436941/5a99ca8a-8676-998b-252d-5b092dbb21ab.png)


##3. 転移学習

前節でみた学習のフローを見ると、中間層の前段では、犬自体の特徴量ではなく、目や鼻など、動物としての特徴のみを学習している。
こういった学習済みモデルは、ほかのタスクへも転用出来る。この例では犬の分類だが、犬と猫の分類タスクに転用するなど。
ベースになる学習済みモデルを使って、別のタスクを解くための負荷の軽い学習をすることを、転移学習という。転移学習では、学習済みモデルの重み更新は行わない。
学習済みモデルの重みも更新することは、ファインチューニングといわれる。

![特徴量伝搬.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1436941/5a99ca8a-8676-998b-252d-5b092dbb21ab.png)
AWS CLI で S3にファイルをアップロード・ダウンロードする

# AWS CLI のインストール
[AWS CLI のインストール、更新、およびアンインストール](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-install.html)より、自身のOSに合わせてのAWS CLIをインストール

# AWS CLI の設定
ターミナルを開いて、AWS CLIのセットアップ。

```
$ aws configure
AWS Access Key ID [None]: myaccesskey
AWS Secret Access Key [None]: mysecretkey
Default region name [None]: ap-northeast-1
Default output format [None]: json
```

- `Access Key`と`Secret Key`は、AWSサービスのIdentity and Access Management (IAM)>アクセス管理>ユーザー>認証情報から設定できる。
- `region`は使っているAWSデータセンターの場所を指定。東京であれば`ap-northeast-1`

すでに設定してある場合、下記で確認できる。

```
$ cat ~/.aws/config          # region & output format
$ cat ~/.aws/credentials     # access key & secret access key
```


# S3バケットの作成
```
$ aws s3 mb s3://bucket-name
```

# S3のバケット一覧出力

```
aws s3 ls
```

# ファイルをローカルからS3にアップロード
```
$ aws s3 cp sample.txt s3://mybucketname/
```

# ファイルをS3からローカルにダウンロード

```
$ aws s3 cp s3://mybucketname/sample.txt ./
```
- `./`で現在のディレクトリを指定

# ディレクトリ内の全てのファイルをローカルからS3にアップロード

```
$ aws s3 cp sample-dir s3://mybucketname/ --recursive
```
ディレクトリ内のファイルのみコピーされる


# ディレクトリ内の全てのファイルをS3からローカルにダウンロード

```
$ aws s3 cp s3://mybucketname/sample-dir ./ --recursive
```

# 作成経緯
参考にしたQiita記事が3年以上前に作成されており、自分の環境では詰まってしまったのでまとめ直した

# 参考
- [AWS CLI での高レベル (s3) コマンドの使用 - 公式ドキュメント](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-move)
- [AWS CLI で S3 にファイルをアップロード - Qiita記事](https://qiita.com/seyself/items/43426f57c50021ea55f8)
[PHP]連想配列

#はじめに
超基礎的な部分ではありますが、PHPとRubyの微妙な違いを見過ごしたくないので、あえて基礎から丁寧に学んでいきます！今回は、PHPで連想配列について学んだのでアウトプットします。

#連想配列

連想配列はインデックス値ではなく、キーと値でデータを管理する仕組みのことです。
これに関しては見た方が早いので、まずは簡単なプログラムを書きます。

```index.php

$index=[
'name'=>'本田圭介'
'sports'=>'サッカー'
]；

echo $index['sport'];#サッカー

```

indexという配列に対して、nameキーには本田圭介、sportsキーにはサッカーが入っています。
取り出す際は、キーを指定してやれば取り出すことが可能です。

また、連想配列は以下のように階層構造をとることも可能です。

```php

$member=[
 '本田'=>[
    "sports"=>"サッカー",
　　"position"=>"MF" 
 ],
'香川'=>[
    "sports"=>"サッカー",
　　"position"=>"FW" 
 ]
]；

echo $member['香川']['position']; #"FW"
```

今回見てわかる通り、ハッシュを使ったような形で管理することがわかりました。

#おわりに

以上、本当に簡単にまとめました。
基礎とはいえ、PHPとRubyの微妙な違いに対応できるように丁寧に学んでいきます！
rustc_apfloat: Rustコンパイラにおける任意精度演算ライブラリ

# はじめに

以前「[Rustのsoftfloatライブラリ比較](https://qiita.com/dalance/items/265a0fc7d64388c1db33)」という記事でRustにおけるソフトウエア実装の浮動小数点数演算ライブラリを紹介しました。このときに気づかなかったのですが、実はもう一つ有力なライブラリがあったのを最近発見しましたので紹介します。

# rustc_apfloat

これはRustコンパイラ内部で使われている任意精度の浮動小数点数演算ライブラリです。（apfloatはArbitrary Precision Floatの略です）

https://doc.rust-lang.org/stable/nightly-rustc/rustc_apfloat/index.html

なぜRustコンパイラ内でこのようなライブラリが必要かというと、主に`const`な浮動小数点数演算を行うためです。
一般的に浮動小数点数演算はLLVM-IRを経由して各アーキテクチャの機械語に変換され、CPUで実行されます。
基本的にCPUが実装する浮動小数点数演算はIEEE-754という規格に従っていますが、規格で定義されていない部分も少しあり、全てのCPUから全く同じ結果が得られるわけではありません。

もし`const`な浮動小数点数演算の結果がCPU毎に違っていたとすると、その演算結果をconst genericsに適用して型を生成したときに、CPUによって違う型が生成されてしまう可能性があり、クロスコンパイルのバイナリとネイティブコンパイルのバイナリの相互運用性に問題が生じる可能性があります。

そこでコンパイラ内でソフトウエア実装の浮動小数点数演算を用意して、それを使って`const`計算を行うことで任意のアーキテクチャで全く同じ演算結果を保証できるようにしました。これがrustc_apfloatです。
これはLLVMの[APFloat](https://llvm.org/doxygen/classllvm_1_1APFloat.html)をRustに移植したもので、`unsafe`なしのpure-Rustコードになっています。

具体的な経緯は以下のPRにあります。

https://github.com/rust-lang/rust/pull/43554

基本的にコンパイラの実装で使われているのでそのまま依存関係に含めることはできませんが、全く同じものをクレートにした人がいるので普通に使うことができます。

https://crates.io/crates/rustc_apfloat

また、このrustc_apfloatを正式にクレート化しようという話もあります。元がLLVMのコードなので現在はライセンスの取り扱いについて議論しているところのようです。

https://github.com/rust-lang/rust/issues/55993

# 使い方

使い方は以下のような感じです。IEEE-754準拠の`Half`/`Single`/`Double`/`Quad`やPowerPCの`DoubleDouble`が用意されています。内部表現は全て`u128`です。

```rust
use rustc_apfloat::{ieee::Half, Float, Round};
let a = 0x1234;
let b = 0x7654;
let a = Half::from_bits(a as u128);
let b = Half::from_bits(b as u128);
let d = a.add_r(b, Round::NearestTiesToEven);
assert_eq!(d.value.to_bits(), 30292);
```

# パフォーマンス

以前測定したのと同じ環境で測定してみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84296/e60a9059-d9e2-3abc-83cb-6f368da6c2e4.png)

縦軸は対数なのでご注意ください。前回最も早かったC実装の`softfloat-sys`と比べると10倍くらいは遅いですが、`rug`とは同等ですし、十分使える範囲だと思います。pure-Rustということで、WASMなどCバインディングを使いにくい環境に適しているのではないでしょうか。
Webアクセシビリティ

#はじめに#
今回、WEBアクセシビリティについて気になったので調べてみました。簡単な内容ですがまとめてみました。

#Webアクセシビリティとは#
PC・スマホの普及でWebで情報の取得が当たり前になっている中で、文字が読みにくいかたや耳が聞こえにくいかたなどがWebから情報を取得する際にアクセシビリティが確保されていないと情報格差を招くことになります。

また、障害のある方に関係なくても使いづらい状況は発生する事があります。例えば怪我をして一時的にデバイスの使用が困難な時、屋外での劣悪な環境での使用、心身の状態、状況によって使いやすさは左右されます。

 WEBアクセシビリティの考え方は、心身の障がい・年齢に関わらず誰もがWebを利用でき情報を取得できることが第一に考えられています。

 W3CというWeb技術の標準化を推進している団体が定めたWCAGというWEBアクセシビリティーのガイドラインがあり、アクセシビリティに対応するための推奨事項が掲載されており、これに準拠することによりアクセシビリティを確保できるとなっています。また、JISによるWEBアクセシビリティも同様に公表されています。



#WCAG#
[W3Cから2021年１月２１に、WCAG3.0が公開されました。](https://www.w3.org/TR/2021/WD-wcag-3.0-20210121/)

WCAGは略称で正式名称は、
**Web Content Accessibility Guidelines**

A〜AAAの適合レベルが用意されており。
レベルAが最低限の達成基準でレベルAAAが最高の達成基準となります。

また、レベルAを満たしていないとページを閲覧できない人が出てくる可能性があり、逆にレベルAAAの中には、適合することは難しいとされているものがあります。

ではどんな基準があるのか、WCAGによる達成基準の例を一部紹介します。

レベルA

- エラーメッセージでエラー箇所、修正方法を明示する。
- キーボードのみでも操作可能であること
- 動画に字幕をつける
- 画像に代替テキストをつける
- リンクテキストはリンク先がわかるように表記する。
- 読みやすいように見出し、リストなど文章構造を正しくマークアップする
- ページ内容がわかるタイトルの設定
レベルAA
- 文字色と背景色のコントラスト比が4.5:1以上である
- キーボード操作時はフォーカスインジケーターを表示する
レベルAAA
- セキュリティの確保が必要な場合、制限が必要不可欠な場合などを除いて入力方式の制限をしないこと
その他にも達成基準がガイドラインに多く掲載されています。


#JIS X 8341-3#
正式名称は、
**高齢者·障害者等配慮設計指針-通信情報における機器、ソフトウェア及びサービス-第3部：ウェブコンテンツ**
現在、投稿時点ではJIS X 8341-3：2016が最新です。
こちらもWCAGのように、適合レベルがあります。


https://waic.jp/resource/jis-x-8341-3-2016/

#最後に#
調べていてわかったことは、デザインをどれだけ凝ったとしてもユーザーが使いやすいかどうかも考えなればいけないと知ることができました。

また、すべての基準を満たすことは難しいので、基本的なに実践できる項目の達成など、実践できる項目から実践することが重要で、WEBアクセシビリティに対応できると思います。
詳しく知りたい方や気になった方は、各サイトのURLを載せておきますので参考になれば幸いです。

#参考文献#
・エーイレブンワイ
https://weba11y.jp/basics/
・WCAG2.1日本語訳版
https://waic.jp/docs/WCAG21/
・WCAG2.2
https://www.w3.org/TR/WCAG22/
・ウェブアクセシビリティ基盤委員会
https://waic.jp/
GASでシートが存在しない場合のみ作成

#GASでシートが存在しない場合のみ作成する
調べてもGASでシートの存在チェックが出てこないので、必死に書いてみました。
ただ素人コーダーなので、いろいろと問題もあるかもしれません。

##
```javascript
function SheetCopy() {
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var TargetSheet = spreadsheet.getSheetByName('原本');
  var date = new Date();
  var date = Utilities.formatDate( date, 'Asia/Tokyo', 'yyyy.MM.dd');
  try{
    var JudgeSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("foo_"+ date);
//判定用の変数で存在を判定したいシートの適当なところに空白を代入。
//これでエラーが出るかチェック
    JudgeSheet.getRange(100, 100).setValue("");
  }catch (e){
    var newSheet = TargetSheet.copyTo(spreadsheet);
    newSheet.setName(Utilities.formatString("foo_"　+ date));
  }
}
```
RPAの小技（Bizrobo）

RPAに関する自分用の備忘録です。色々なロボットを作った中で記録しておきたいものを抜粋しました。

<h2>使用しているRPAツール</h2>
Bizrobo!Basic

<h2>APIの連携方法</h2>

**前準備 使用したいAPIのトークン一式を発行しておく**

①発行したアクセストークンをテキストファイルに保存する
②ロボサーバ上にテキストファイルを配置する
③サーバに配置したテキストファイルからリフレッシュトークンを取得して変数に格納する
④REST Webサービス呼び出しステップを設定する
設定が必要な項目
URL：APIを使用するURLを設定する
リクエスト：POST
パラメータで指定
リフレッシュトークン：③で格納した変数
クライアントID
クライアントシークレット
グラントタイプ：リフレッシュトークン
コンテンツタイプ：application/json
オプション：クレデンシャル
ユーザー名：リフレッシュトークンを使用するユーザー名
パスワード：リフレッシュトークンを使用するパスワード
⑤APIを叩いて取得したトークンをアクセストークンとして変数に格納する
⑥APIを使用するために必要な処理を作成
（GASを利用する場合はGASに設定したい項目を取得する処理など）
⑦REST Webサービス呼び出しステップを設定する
設定が必要な項目
URL：APIを使用するURLを設定する
リクエスト：POST
ローボディで指定
APIで渡したい項目をローボディで指定する
コンテンツタイプ：application/json
オプション：クレデンシャル
ユーザー名：リフレッシュトークンを使用するユーザー名
パスワード：リフレッシュトークンを使用するパスワード
Authorizon Bearer：⑤で取得した変数
Accept: application/json
Host:ホストの設定

<h2>バッチファイルとの連携方法</h2>
①バッチファイルを作る
②ExecuteCommandLineを設定する
バッチを叩くコマンドをコマンドラインで指定（エクスプレッションがおすすめ）

<h2>SELECT文でDBのデータを取得する方法</h2>
**前準備：データベースの設定を行う**
①データベース照会を設定する
②SQLクエリにSELECT文を設定する
※SELECT以外はデータベースの項目から対応している設定を選択する

<h2>その他メモ</h2>
・エクスプレッションで正規表現、関数が指定できるので、
ConvertVariablesを設定する際に使用すると便利。
IndexOff使って文字の抽出などが可能。
・パスワードやユーザー名やファイルの置き場所など、テキストベタ書きで設定しがちな値は変数に設定して都度変数を渡すようにすると便利。
error用filterでlambdaのrequestId取得

## 概要
ログ出力した時にCloudWatchに出ているidの取得です。

公式に書いてあったfilter処理の情報から、ログ探って取得しました。
エラー時にインサイトとかで特定しやすいだろうと思ってのID抽出です。

※header情報なんで、lambdaでheader取得したら流用は効きそうです。

##コード

```
    let reqestId = ""
    const ctx = host.switchToHttp()
    const request = ctx.getRequest()

    if (request.headers['x-apigateway-context']) {
      const context =  JSON.parse(decodeURIComponent(request.headers['x-apigateway-context']));
      if (context['awsRequestId']) {
        reqestId = context['awsRequestId'];
      }
    }
```

## インサイト
```
fields @timestamp, @message
| sort @timestamp desc
| filter @message like 'ce3b81bb-b3d0-428e-a6b6-47a422f5dd91'
| limit 20
```

## 参考
https://nodejs.org/api/http.html#http_class_http_incomingmessage
https://maku77.github.io/js/web/encode-uri.html
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/nodejs-context.html
laravel アプリを作成してローカルサーバーを起動できるようにする

# 目的

- laravelアプリを作成してローカルサーバーを起動しブラウザで確認するまでの作業を記載する

# 環境

- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.5) |
| ハードウェア | MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) |
| プロセッサ | 2 GHz クアッドコアIntel Core i5 |
| メモリ | 32 GB 3733 MHz LPDDR4 |
| グラフィックス | Intel Iris Plus Graphics 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| PHP バージョン | 7.4.8 | Homebrewを用いてこちらの方法で導入→[Mac HomebrewでPHPをインストールする](https://qiita.com/miriwo/items/cd54077aad7e139cf518) |
| Laravel バージョン | 8.X | commposerを用いてこちらの方法で導入→[Mac Laravelの環境構築を行う](https://qiita.com/miriwo/items/adaaaeecae69d6392e08) |

# 情報

- 筆者はMacに直接構築したLaravelアプリ動作環境にて検証を行い記事を記載する。
- 環境構築は下記に沿って実施した。
    - [Mac Laravelの環境構築を行う](https://qiita.com/miriwo/items/adaaaeecae69d6392e08)
- 今回はlaravel8のアプリを作成し、アプリ名は「test_app」とする。

# 方法

1. 任意のディレクトリで下記コマンドを実行し、アプリを作成する。（完了まで時間がかかるので待機する。）

    ```terminal
    $ composer create-project "laravel/laravel=8.*" test_app
    ```

1. 下記コマンドを実行して先のコマンドで作成されたディレクトリに移動する。

    ```terminal
    $ cd text_app
    ```

1. 下記コマンドを実行してローカルサーバーを起動する。

    ```terminal
    $ php artisan serve
    ```

1. 下記にアクセスしてその下の画像と同じページが表示されることを確認する。
    - [http://127.0.0.1:8000/](http://127.0.0.1:8000/)

        ![Laravel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/394805df-5660-3de4-0348-86d5af39369f.png)
Javascript 変数


本日はJavascriptの変数について学習をしましたので、そちらについて記事に残していきます。


前回の記事でも使用しましたが、変数は値を格納するための箱のようなイメージになります。
ですので、変数の中には様々な値を格納することができます。

```javascript
let x = 4;
```
上記のようにコードを書くと、 x は 4 という数値を格納していることになります。

変数はその名の通り、格納している値を変更できます。
格納している値を変更する際は、let を使わずに定義することができます。

```javascript
let x = 4;
x = 6;
```
この場合、最初に x は 4 という数値を格納していますが、その後に数値が変更され 6 という数値を格納していることになります。

今までの例では数値のみを格納していましたが、変数は数値以外にも様々な値を格納することができます。

```javascript
let str = "変数"; //文字列
let num = 4; //数値
let arr = ["a", "b"]; //配列
let obj = {a: "b"}; //オブジェクト
let fun = () => {}; //ファンクション(関数)
```
このように様々な値を格納できるので、配列の中に複数の値を格納して任意の値を取り出したり、文字列の結合や数値の四則演算をすることが可能です。
WordPress reCAPTCHA v3 設定方法(ContactForm7・MW WP Form)

##概要
WordPressでスパム対策の一環として、reCAPTCHA[^1]を設置する機会があるかと思いますが、プラグインによって設定方法が若干異なっていたので、2大プラグイン(ContactForm7・MW WP Form)の設定方法をまとめました。

[^1]: reCAPTCHAとは、Googleが無料で提供している、botと人間を区別するためのサービスです

## ContactForm7の場合

1． [https://www.google.com/recaptcha/about/](https://www.google.com/recaptcha/about/)
ここから reCAPTCHA v3 のサイトキー、シークレットキーを取得します

2． ダッシュボードのメニュー「お問い合わせ＞インテグレーション」→「インテグレーションのセットアップ」
ここにサイトキー、シークレットキーを入力したら設定完了
ContactForm7のフォームに、reCAPTCHAの設置画像が表示されます

3． そのままだとサイト全体にreCAPTCHAの設置画像が表示される為、フォームのページのみに設置画像を表示させたい場合は、functions.phpに以下のように記述します

```php
//reCAPTCHA v3 のロゴをフォームのページ以外非表示にする
function load_recaptcha_js() {
    if (!is_page('form')) { // サイトに合わせてformの箇所は修正して下さい
        wp_deregister_script( 'google-recaptcha');
    }
}
add_action('wp_enqueue_scripts', 'load_recaptcha_js',100 );
```

これで、フォームのページのみに表示されます

## MW WP Formの場合

1． [https://www.google.com/recaptcha/about/](https://www.google.com/recaptcha/about/)
ここから reCAPTCHA v3 のサイトキー、シークレットキーを取得します

2． 「reCAPTCHA for MW WP Form」プラグインをインストールします

3． ダッシュボードのメニュー「MW WP Form」→「reCAPTCHA v3」
ここにサイトキー、シークレットキーを入力し、ショートコードをコピーします

4． ショートコードをMW WP Formのエディタ部分に貼り付けます

5． バリデーションルールの reCAPTCHA V3 にチェックを入れれば設定完了

※MW WP Formの場合は、functions.phpに追記しなくても、フォームのページのみにreCAPTCHAの設置画像が表示されます


## まとめ
設定方法は管理画面の表示が違えどもほとんど一緒ですが、
大きな違いとしては、

【ContactForm7】reCAPTCHAを設定するためのプラグインのインストールが不要
【MW WP Form】reCAPTCHAを設定するためのプラグインのインストールが必要

【ContactForm7】サイト全体にreCAPTCHAの設置画像が表示される為、全体に表示させたくない場合functions.phpへの記述が必要
【MW WP Form】フォームのページにのみ表示される為、functions.phpへの記述は不要

かと思います

ご参考にしてみて下さい
[AWS_23]起動テンプレートの作成

##環境
**Amazon Web Service**

* EC2(Amazon Linux 2 , t2.micro , 汎用SSD 8GB)
* RDS(MySQL , db.t2.micro)

**ローカルPC**

* MacBook Pro(2.9 GHz デュアルコアIntel Core i5 , 8 GB 2133 MHz LPDDR3)
* macOS 11.3.1（20E241）



##概要
現在、EC2インスタンスが2台の冗長構成となっているが、負荷が大きくなり2台では賄えない可能性がある。（弱小ブログサイトでは不要そうだが）そこで`AutoScaling`を使うことで、自動的に新しくEC2インスタンスを立ち上げてスケールアウトすることができる。

その際に、どのようなEC2インスタンスを立ち上げるのか設計図になるものが**起動テンプレート**。

現在の構成図
![構成図09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/758644/9cf213b5-3c65-82d1-8b8a-a4913b63077a.png)



##起動テンプレートの作成
1. テンプレートの起動　＞　起動テンプレートを作成をクリックする。
1. 以下項目を入力していく。
    * 起動テンプレート名： `LaunchTemplate1`
    * テンプレートバージョンの説明: `1.0.0`
    * Auto Scaling のガイダンス: `EC2 Auto Scaling で使用できるテンプレートをセットアップする際に役立つガイダンスを提供`にチェックを入れる。
    * AMI: `WebServer`(既に作成済みのMyAMI)
    * インスタンスタイプ: `t2.micro`
    * キーペア名: `Mykeypair`(既に作成済みのKeypair)
    * ネットワーキングプラットフォーム: `VPC`
    * ストレージ: `8GiB,汎用SSD
    * リソースタグ
        * キー: `Name`
        * 値: `WebServer-Auto`
        * リソースタイプ: `インスタンス`
    * ネットワークインターフェイス
        * セキュリティグループ: `Web-SG-1`(既に作成済みのセキュリティグループ)
        * パブリック IP の自動割り当て: `有効化`
1. `起動テンプレートを作成`をクリックする。
M1 MacからHerokuにデプロイするには（２）

## はじめに

https://qiita.com/sugiyamashiori/items/5ddae663c09fc78d2d23

以前、上記の記事を書きました。これは動作確認せずに書いた、ただの英文和訳なのでした。

## 結論：Rubyのバージョンを下げるなどする

で、私はRubyでアプリを作ったのですが、それを材料に記事のとおりトライしてみたところデプロイできず（汗）。結果、Rubyのバージョンを下げることで解決しました。

今回は初心者としてのその記録です。なおDocker（プレビュー版）使ってます。


#### 1. Rubyのバージョンを下げる

私は2.6.6から2.6.3に下げました。下記のように編集します。

```ruby:.ruby-version
ruby-2.6.3
```
```ruby:Dockerfile
FROM ruby:2.6.3
```
```ruby:Gemfile
ruby '2.6.3'
```

#### 2. Gemfile.lockを一度消す
`Gemfile.lock`を開き、内容を全て消去して、保存します。
（内容はbuildすると自動で新規作成されます）

#### 3. ビルド

```
$ docker-compose down
```
```
$ docker-compose build
```
```
$ docker-compose up
```

#### 4. 新しくできたGemfile.lockを編集

```Gemfile.lock
PLATFORMS
  ruby
```

以上です！あとは普通にデプロイすればOKです。

## 補足１：デプロイ時のWarningについて
上記の手順でデプロイすると、`git push heroku master`に対して下記のような注意が出ますが、「もっと新しいRubyあるよ！」の旨なので無視します。

```
remote: 
remote: ###### WARNING:
remote: 
remote:        There is a more recent Ruby version available for you to use:
remote:        
remote:        2.6.7
remote:        
remote:        The latest version will include security and bug fixes. We always recommend
remote:        running the latest version of your minor release.
remote:        
remote:        Please upgrade your Ruby version.
remote:        
remote:        For all available Ruby versions see:
remote:          https://devcenter.heroku.com/articles/ruby-support#supported-runtimes
remote: 
```

## 補足２：App修正と再デプロイ時の注意点
Appを修正する場合、Rubyのバージョンを元に戻して修正作業をし、デプロイ時に再びバージョンを下げる必要があります。手間ですね。。

## おわりに

読んでいただきありがとうございました！
もっと良い方法があれば教えてください。
無料の VPS を借りる （Oracle Cloud 編）

# はじめに

Oracle Cloud はずっと無料で使える Always Free プログラムがあります。
折角なので構築して遊んでみましょう。

公式サイト [Oracle Cloud Free Tier](https://www.oracle.com/jp/cloud/free/)

登録にはショートメールが受け取れる携帯電話番号とクレジットカードが必要ですが、自動的に有料プランへ移行したり、知らない間に課金されることはありません。

# 無料で Oracle Cloud のインスタンスを作成する

画像が多いのでスライドにまとめています。
スライドに従って操作すればインスタンスを作成できます。

<iframe src="https://docs.google.com/presentation/d/e/2PACX-1vTtytvoIfF5Z_pHkdlQpctZ5UQ2bXvYCobumXIAotTz6Fn-XzSV0Dq-glmq6t_ESvTQgkEPcAWdWJou/embed?start=false&loop=false&delayms=3000" frameborder="0" width="100%" height="570" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>

ここでは RHEL 8 互換の Oracle Linux 8 を使用します。

公式より：
>Oracle Linuxは、アプリケーション・バイナリでRed Hat Enterprise Linuxと完全に互換性があります。

Oracle Linux は CentOS のように使えます。
CentOS 8 は2021年末でサポート終了の予定ですが、Oracle Linux 8 はそれ以降もサポートが続きます。

# SSHで接続する

次の説明は Windows ユーザー向けです。
ここでは [RLogin](https://kmiya-culti.github.io/RLogin/) を使用します。SSHのターミナルソフトであれば、何でも構いません。

RLogin （無料）の入手先
* [公式サイト](https://kmiya-culti.github.io/RLogin/)
* [GitHub](https://github.com/kmiya-culti/RLogin/releases/)

スライドに従って、インスタンス（VPS）に接続してください。

<iframe src="https://docs.google.com/presentation/d/e/2PACX-1vQHGi9tja8fBSGEYIl64OiPKoYvdcf_ARz2GOdS35tS6F9lBZRZK8gzyfH0KaRaTOGJR2CJyjZSK5gh/embed?start=false&loop=false&delayms=3000" frameborder="0" width="100%" height="570" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>

これで準備は完了です。

# RLoginの記事（他者さま）
https://qiita.com/pocket8137/items/e294715b5154487b9ae0

https://qiita.com/murachi1208/items/d6e4ce7ba75f1625fe51

# Next

https://qiita.com/dxa/items/046d6e78d1e1ca16d72c

https://qiita.com/dxa/items/01d78bda1ca5df73bab6
gulp-imageminで「syscall: spawn /Users/xxxxxx/node_modules/pngquant-bin/vendor/pngquant」と出た時の応急処置


該当ディレクトリに`pngquant`がないと言われている。
実際に確認してみて、無かったら直接設置すると解消する。

### 環境
macOS 10.15.7
gulp-imagemin 7.1.0
imagemin-pngquant 9.0.0
node v14.15.4

### 対処法

１）以下にアクセスする。
https://github.com/imagemin/pngquant-bin

２）`npm install`だと設置されないため、一式ダウンロードしたのち、

３）同梱の「`vendor/macos/pngquant`」を、直接「`node_modules/pngquant-bin/vendor`」に設置する。

応急処置的な対処なので、別の環境でも再発するかもしれない。
Spring BootとPostgreSQLで時間計測 powered by AMD Ryzen7 4800H(8core/16thread)

##検証環境

- Spring Boot環境
 - v2.5.0 
 - OS Windows10
 - OpenJDK 16.0.1
- PostgreSQL環境
 - v10.15 
 - OS Red Hat Enterprise Linux 8.4
 - 仮想化環境 vmware workstation player 16.1.2 4core/メモリ8GB割り当て 
- JMeter環境
 - v5.4.1
 - OS Windows10(Spring Bootと同居構成＝本当はよくない。）
 - jdk-8u291-windows-i586（最新版だと動かないので意図的に古い版を利用）


##検証コード

```
package com.example.demo.controller;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(path="/jdbc")
public class JDBCController {
    
    @Autowired
    JdbcTemplate jdbcTemplate;

    @RequestMapping(path="/id", method=RequestMethod.GET)
    public String index() {
        List<Map<String,Object>> list;
        list = jdbcTemplate.queryForList("select name from test"); // indexのないキー検索
        int recordCount = list.size();
        return "HelloWorld:" + recordCount;
    }

    @RequestMapping(path="/id/{id}", method=RequestMethod.GET)
    public String read(@PathVariable String id) {
        List<Map<String,Object>> list;
        list = jdbcTemplate.queryForList("select id from test where id = ?", id); // PK検索
        return "HelloWorld:" + list.toString();
    }


    @RequestMapping(path="/process", method=RequestMethod.GET)
    public String prooscess() {
        String line = "";
        int exitCode = 0;
        try {
            ProcessBuilder processBuilder = new ProcessBuilder();
            processBuilder.command("cmd.exe", "/c", "echo HelloWorld");
            Process process = processBuilder.start();
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String temp = null;
            while ((temp = reader.readLine()) != null) {
                line = line + temp;
            }    
            exitCode = process.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return line+ " rc:" + exitCode;
    }

    @RequestMapping(path="/hello", method=RequestMethod.GET)
    public String hello() {
        return "HelloWorld";
    }
    
}
```

##検証結果

| 検証シナリオ|性能|備考|
|:-----------------|------------------:|:------------------:|
| "HelloWorld"を返すRESTコントローラ|37000tps ||
| PK検索結果を返すRESTコントローラ|6800tps||
| indexなしで10000件スキャンして件数を返すRESTコントローラ|340tps||
| indexなしで20000件スキャンして件数を返すRESTコントローラ|160tps|下記と同tpsを出すのに苦労しました。|
| ProcessBuilderでOSコマンド実行するRESTコントローラ|160tps|OSプロセス起動のオーバーヘッドが大半|

※いずれのシナリオも同じJMeter(Number of threads 200/Loop Count 500/Ramp-up 0)で負荷掛け実行。

#結論
「JavaからのOSプロセス起動を多用する設計にしてしまうとCPUが何個あっても足りません！」ということを数字をもって示すことができました。
既存のレイアウトの一部にJetpack Composeを組み込む

#はじめに
Google I/O 2021でアナウンスされたように、今後Jetpack ComposeでUIを組み込んでいくのが推奨されていくようです。
そこで、本記事では既存のアプリにJetpack Composeを組み込む方法を説明します。

#既存のアプリにJetpack Composeを組み込む
###レイアウト
レイアウトファイルの一部でComposeを使う時の例です。

```xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/hello"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp"
        android:textSize="20sp"
        android:textColor="@color/black"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

    <androidx.compose.ui.platform.ComposeView
        android:id="@+id/compose"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/hello"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>
```
通常のレイアウトファイルでComposeを使いたい箇所にComposeViewを記述します。
このComposeView内にコード上でCompose関数を使うことになります。

###Compose関数の追加
上記のレイアウトをActivity内でCompose関数と一緒に使う時の例です。

```kotlin
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        findViewById<ComposeView>(R.id.compose).setContent { 
            Greeting(message = "Hello Compose!")
        }
    }

    @Composable
    fun Greeting(message: String) {
        Text(text = message, fontSize = 20.sp, textAlign = TextAlign.Center)
    }
}
```
ComposeViewを取得して、それに対してsetContentブロックを定義します。
そのブロック内でCompose関数を呼び出す等して、ComposeでUIを記述できます。

###完成イメージ
<img width="300" alt="screenshot.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/952082/05101a33-832f-ed8d-24fa-e2ec14aeecdb.png">

#おわりに
今回は既存のxmlで実装したレイアウトの一部にComposeで実装したレイアウトを組み込む方法を説明しました。
比較的簡単に組み込めるので、徐々にComposeで実装する部分を増やしていくことはできると思います。

#参考
[Jetpack Composeを使ってみる | Android Developers](https://developer.android.com/jetpack/compose/documentation?hl=ja)
【JS】includes()で特定要素を複数指定したいとき

ES6で追加された `includes()` メソッドは、とても便利ですが、指定できる特定の要素はひとつしか指定できません。でも複数指定したいときはないでしょうか？この記事では特定の要素を複数指定する方法を紹介します。結論からいうと、**`includes()` に特定要素は複数指定できないでの独自関数を作ります。**

## `includes()` の使い方
まず `includes()` の使い方をおさらいしてみましょう。すでにわかっているよ！という人は読み飛ばしてください。

[Array.prototype.includes()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/includes)

> includes() メソッドは、特定の要素が配列に含まれているかどうかを true または false で返します。


```js
const numArray = [1, 2, 3];

console.log(numArray.includes(2)); // 出力：true

const animals = ['cat', 'elephant', 'hipo'];

console.log(animals.includes('cat')); // 出力：true
```

このように使います。また、配列だけでなく文字列に対しても使えます。

[String.prototype.includes()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/includes)

> includes() メソッドは、1 つの文字列を別の文字列の中に見出すことができるかどうかを判断し、必要に応じて true か false を返します。

```js
const text = 'I have no idea about JavaScript';

const word = 'idea';

console.log(text.includes(word)); // 出力：true
```

## `includes()` で特定要素を複数指定する
`includes()` だけではだめなので、 `some()` と `every()` を使って独自の関数を定義していきます。

### 複数の特定要素のうちひとつでも当てはまったら true を返す独自関数

```js
const isIncludes = (arr, target) => arr.some(el => target.includes(el));
```

#### 解説
`some()`は配列の少なくとも一つの要素が、指定された関数で実装されたテストに合格するかどうかをテストします。

[Array.prototype.some()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/some)

独自関数 `isIncludes` に特定要素の配列(arr)と検索したい要素(target)を渡してあげると `true` か `false` を返します。



### 複数の特定要素のうち全部当てはまったら true を返す独自関数

```js
const isAllIncludes = (arr, target) => arr.every(el => target.includes(el));
```

#### 解説
`every()` は、配列内のすべての要素が指定された関数で実装されたテストに合格するかどうかをテストします。

[Array.prototype.every()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/every)

独自関数 `isIncludes`と同じく特定要素の配列(arr)と検索したい要素(target)を渡してあげると `true` か `false` を返します。

### 独自関数　`isIncludes` と `isAllIncludes`の使い方
こんな感じで使います。検索したい対象が配列の場合、 `forEach()`を使えば良いかと思います。

```js
const text = 'Beef or chicken ? Sorry, I have no Kebap.';
const fruits = ['banana', 'apple', 'orange', 'lemon'];
const searchWord1 = ['an', 'ge'];
const searchWord2 = ['chicken', 'Kebap'];

// 複数の特定要素のうちひとつでも当てはまったら true を返す
const isIncludes = (arr, target) => arr.some(el => target.includes(el));
// 複数の特定要素のうち全部当てはまったら true を返す
const isAllIncludes = (arr, target) => arr.every(el => target.includes(el));

// 配列fruitsに対して実行
fruits.forEach(elm => {
  console.log(elm, isIncludes(searchWord1, elm));
/* 出力：
"banana" true
"apple" false
"orange" true
"lemon" false
*/
});

// 文字列textに対して実行
console.log(isAllIncludes(searchWord2, text)); // 出力：true
```

## 感想
「`includes()`で複数指定〜」といっておきながら、 `includes()` だけでは実現できませんでした。無念！

無理に`includes()` を使わなくても `indexOf` や正規表現を使っても実現できるかと思いました。

---

**参考**

2024/06/19/追記
参考に上げていたサイトが怪しいサイトに置き換わっていたので削除しました。
NumPyとOpenCVのimportでエラーが出る件

# 初めに
環境設定......なにそれおいしいの？
そんな自分が出会った，やらなければいけない事orzについて，備忘録として記載していきます．
（文章力が無いので読みづらい場合はすいません...）

本稿では，NumPyとOpenCVをimportした際に起きたエラーについて記載します．

## import numpy as npでエラー
[環境構築](https://qiita.com/thinknee/items/a1aed765948c6a68db4d)が終わり，[conda activateのエラー](https://qiita.com/thinknee/items/ba19898a051176cfab69)も解決したので，早速，画像をあれこれしてみよう！と息巻いて...
![NumPy_error.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545522/712ecb94-8de2-66e0-cc99-258b154efabf.png)
Oh...

# 解決編
ということで，早速ですが，OpenCVとNumPyについて，使えるようにしていきたいと思います．

##### 環境変数の追加
左下のWindowマークを押し，**環境変数を編集**と検索し選択します．
環境変数のウィンドウが開いた後は，上の枠にある，Path→編集→新規を順に押し，以下を追加します．

”C:\Users\自身のユーザー名\Anaconda3\Library\bin”
<font color="Gray">参考：[VSCodeでPythonの初回実行に失敗](https://www.premium-tsubu-hero.net/technology/it/visual-studio-code/howto-vscode-condainit-failed/)</font>

追加したら_OK_を押します．これでNumPyは動くかもしれないです．（OpenCVはまだ動かないはず）

##### OpenCVのインストール
続いて，OpenCVをインストールします．
（もし既にインストールしていれば，状況に応じた説明を読むか，アンインストールしてください）

ターミナルで以下を記載して，*Enter*を押します．
他の書き方を試したときにどうなったのかは付録（下の方）に記載します．

```
conda install -c conda-forge opencv=4.0.1
```

##### NumPyのインストール
続いて，上記のインストールでは，NumPyのバージョンが古いみたいなので，NumPyをアップデート？インストール？します．
<font color="Gray">参考：</font>[【Pythonエラー対策】ImportError: numpy.core.multiarray failed to import](https://algorithm.joho.info/programming/python/numpy-core-multiarray-failed-to-import/)

下記をターミナルに記載してください．

```
conda install numpy
```

これで動きます！

# 付録

```
conda install opencv
conda install opencv=4.0.1
conda install -c conda-forge opencv
```

これらのインストール方法では，エラーが解消できませんでしたorz
多分，PythonのバージョンやOpenCVのバージョンが色々と関係してくる可能性があるのかもしれないですね．（適当）
※　pipを用いる場合は以下のコマンド

```
pip install opencv-python
```

# 最後に
何かをやろうとするたびにエラーが出るのはどうにかならないのかな...
心が折れそうですが，それでも，めげずにやっていこうと思います！

次は，OpenCVとGitHubの連携についてやってみたので，方法について以下に記載します．
[OpenCVとGitHubの連携について](https://qiita.com/thinknee/items/52481209820167534eeb)
【Python】クラス変数の妙

# はじめに
Pythonを勉強していて、妙を感じるところがあったので備忘録として残そうと思いました。

# クラス変数とインスタンス変数
クラス変数はインスタンスを生成してもすべてのインスタンスで値を共有してしまう。
共有したくない場合は例のようにインスタンス変数を使用しないといけない。


```python:クラス変数
class Instance:
    values = [] # クラス変数

    def add_list(self, value):
        self.values.append(value)

ins1 = Instance()
ins1.add_list("データ1")
ins2 = Instance()
ins2.add_list("データ2")
print(ins1.values)

# 結果
# ['データ1', 'データ2']
```

```python:インスタンス変数
class Instance:
    def __init__(self):
        self.values = [] # インスタンス変数

    def add_list(self, value):
        self.values.append(value)

ins1 = Instance()
ins1.add_list("データ1")
ins2 = Instance()
ins2.add_list("データ2")
print(ins1.values)

# 結果
# ['データ1']
```
【完結編！】SDF EditorでShadertoyやGLSLのモデリングが劇的に簡単に！


  
***21年5月30日に、SDF Editorのソースコードが公開され、
より簡単にGLSL用のコードが出力できるようになりました。***

***下記記事をごらんいただき、本記事は下記記事の参考としてください。***

https://qiita.com/quittardis/items/5002dc5563b0aef2b472


-----------------------------------------------------------------------
 本記事は、以下の二つの記事の完結編です。

***SDF EditorでShadertoyやGLSLのモデリングが劇的に簡単に！<Pyhtonでコンバーターを書きました>***
https://qiita.com/quittardis/items/7a0d23359fcebaeb21a6  

***【改良版！】SDF EditorでShadertoyやGLSLのモデリングが劇的に簡単に！***
   https://qiita.com/quittardis/items/7a0d23359fcebaeb21a6　　


![shadertoy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430586/d6125332-8385-33db-af7d-892069467625.png)


###SDF Editorの全プリミティブ、モディファイア、オペレータに対応

###cnvSDF.py    https://github.com/ultrahamlet/cnvSDF
 ***cnvSDF.py***は、"SDF Editor" https://joetech.itch.io/sdf-editor 出力結果をShadertoy(GLSL)の 
コードに変換する。"SDF Editor"の以下の要素に対応している。

***プリミティブ Primitives***
Box, Frame, Cylynder, InfCylynder, Capsule, Cone, Capped Cone, Round Cone, InfCone
Sphere, Ellipsoid, Solid Angle, TriPrism, Hexprism, Torus, CappedTorus, Link,
Octahedron, Pyramid, Plane, 

***モディファイヤ Modifires***

Translation, Rotation, Mirror, RepInf, Replim, Elongation

***オペレータ Operator***

Union, Subtraction, Interection, Onion, Thicken, SmoothUnion, SmoothSubtraction, SumoothIntersection　　

***cnvSDF.pyの使い方***

　**1.** "SDF Editor"でモデリングする。
　
　**2.** データをデフォルトのファイル名、"test.json"で保存する。

　**3.** ShadertoyのプラグインをインストールしたVisual Studo Codeで、
　viewSDF.fragを開き、sdfという文字列をサーチし、"SDF Editor"の
　下方の出力枠の中のsdf関数とsdf(vec3 p0)｛...}を置き換える。

　**4.** cnvSDF.pyを実行し、その出力結果であるテキストをviewSDF.fragの先頭
　にコピーする。

　**5.** いったん、viewSDF.fragをセーブし、再び開く。

　**6.** マウス右ボタン-> Shadertoy:Show GLSL Preview　でRaymarchingの結果を表示。

  これを
　**7.** マウス右ボタン-> Shadertoy:Create Protbale GLSL Preview　で得られる
　viewSDF.html　はローカルでもweb上でも同じRaymarchingのリアルタイムCGが表示できる。
アップデート確認APIの設計

アップデート確認APIの設計案

## 最新版の取得

パッケージとバージョンを渡す。

`GET /packages/{package:name}/releases/latest?version={version}`

- 渡されたバージョンよりも新しい有効なリリースがあったら、最新のものを返す。
- 渡されたバージョンよりも新しい有効なリリースがなかったら、何も返さない。

## 現行版の確認

パッケージとリリースの識別子を渡す。

`GET /packages/{package:name}/releases/{release:name}`

- 指定されたリリースが登録されていて、有効になっていたら、それを返す。
- 指定されたリリースが登録されていなかったり無効になっていたりしたら、何も返さない。

# DB

```
packages {
  id: primary id
  name: string (unique)
}
```

```
releases {
  id: primary id
  package_id: foreign id
  name: string (unique)
  url: string (nullable)
  notes: text (nullable)
  publish_date: DateTime (有効化される日時)
  expire_date: DateTime (無効化される日時)
}
```

# CLI

## パッケージの作成

```
package:create {package:name}
```

## パッケージの削除

```
package:remove {package:name}
```

## リリースの公開

```
package:release:publish {package:name} {release:name}
```

## リリースの廃止

```
package:release:expire {package:name} {release:name}
```

オプションで指定したバージョン以下をまとめて廃止できてもいいかも。
Push通知の調査メモ

# Push Notification

プッシュ通知に関するメモ。
特にモバイル端末におけるプッシュ通知について。

## できること

- メッセージを表示する
- メッセージを表示しない
- 画像を添付する
- サウンドを設定する
- バイブレーションを設定する
- 通知をクリックするとアプリを開く
- 通知をクリックするとアプリの特定のページを開く
- フォアグラウンドのアプリで通知をフックする
- バックグラウンドのアプリで通知をフックする
- 特定のユーザーに送信する
- トピックを購読しているユーザーに送信する

## できないこと

- 起動していないアプリで通知をフックする

## 発行方法による違い

プッシュ通知には、クライアントを登録したサーバーから発行する「リモート通知」と、モバイル端末自身が発行する「ローカル通知」がある。

### リモート通知

サーバーから通知を発行する。

iOS の場合は APN (Apple Push Notification) を使う。
Android の場合は FCM (Firebase Cloud Messaging) を使う。

FCM から APN に送ることもできる。

### ローカル通知

モバイル端末から通知を発行する。

## バックグラウンド通知

iOS は 7.0 からバックグラウンドのアプリに通知できる。

### APN の設定

通知する側で `aps.content-available` を `1` に設定する。

通知されるアプリの設定で `Capability > BackgroundMode > Remote notifications` を有効にする。

https://qiita.com/chocoyama/items/56cd3ac2daaf69dffa0f

## サイレント通知

通知を画面上に出さない。

### iOS

`aps.alert` を設定しなければ、画面上には表示されない。

FCM の場合は `message.notification.title` と `message.notificaiton.body` が `aps.alert.title` と `aps.alert.body` の代わりになっているので、それらを消しておけばいい。

### Android

？

## 参考資料

- [FCM のパラメータ詳細](https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages)
- [APN のパラメータ詳細](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification)
- [Android のカスタムプッシュ通知でリッチな UX をユーザーに届けよう](https://medium.com/eureka-engineering/android%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%83%97%E3%83%83%E3%82%B7%E3%83%A5%E9%80%9A%E7%9F%A5%E3%81%A7%E3%83%AA%E3%83%83%E3%83%81%E3%81%AAux%E3%82%92%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%AB%E5%B1%8A%E3%81%91%E3%82%88%E3%81%86-d30ce6cd96ef)
IBM Watson v4 Developer受験のススメ

IBM Watson v4 Developerを受験してきました。
https://www.ibm.com/certify/exam?id=C1000-104

これから受験を考えている方向けに、思ったところを伝えていこうと思います。
実際の試験問題に関してはお伝えできませんが、受験対策方針など、役立つところがあれば幸いです。

#受験に向いている（と思う）人
* IBM Watson APIを普段から利用している人
    * 普段からよく使っている人は、Watson APIサービスの基本的なスキルや、それらを現場で適用していくノウハウを既に所有しているものと思いますので、「スキルがあることをきちんと証明する」ために受験をオススメします。試験に合格すると、デジタルbadgeが付与されます。
* IBM Watson APIサービスを使ったことがあり、更に知識を体系的に深めたい人
    * いくつかのWatson APIサービスを使った経験があるが、周辺知識を体系的に学んだ覚えがない人は、この試験の受験をきっかけに勉強してみることをオススメします。人間、なかなかきっかけがないと動かないので、良い機会になると思います。
    （私はこれに該当）

なお、IBM Watson APIサービスを一度も使った事がないけれど、座学ベースで受験してみたい人。については、受験資格はあるので止めはしませんが、あまりオススメではありません。試験はCBT方式の選択問題で、プログラミングスキルがなくても大丈夫ですが、試験の出題範囲にはAPI仕様も含まれます。やはり、実践経験も含めた、どちらかというと開発者向けの試験だと思います。もし未経験から受験を目指す場合は、最低でも各APIのチュートリアルを操作し、手を動かして内容を理解しておくことをオススメします。

#試験内容
（2021年5月時点の情報をベースに記載しています。最新の情報は、公式サイトを確認するようにしてください）

* 試験形式：CBT、選択式・英語のみ、90分間
* 合格ライン：70%以上（60問中42問正解で合格）
* 出題範囲と内訳：
    * Section1：General Watson &AI Concepts（機械学習の評価手法、各Watson APIのユースケースなど）　・・・14問
    * Section2：Watson Assistant Service　・・・17問
    * Section3：Watson Discovery Service　・・・10問
    * Section4：Watson Speech Service　・・・13問
    * Section5：Watson Language Processing Services　・・・6問
    
　　上記の出題範囲からランダムに問題が出されます。中には、複数選択の問題もあり、おそらく完全正答でないと得点されません。（部分点はなさそうに見えました）

#試験対策
上記の試験内容と、実際に受けてみた感覚を踏まえて、合格ラインを突破するための学習プランを紹介します。

* まずはSample Examに目を通し、腕試し
    * https://www.ibm.com/certify/api/getpdf/sampletests/samc1000_104
    * 上記リンク先の公式ページで、全19問のサンプル問題が掲載されています。こちらでサクっと、当日の出題形式に慣れること、出題される問題のレベル感を把握することが出来ます。今の時点で、これらを余裕で全問正解できるレベルの方は、特に追加の試験対策は要らないかもしれません。
    * （余談）サンプル問題の中に、DiscoveryのCOVID-19 data kitsに関する話題が含まれてますが、これも出題範囲になっているようです。当試験のV4は2021年3月～始まったばかりなので（2月迄はV3.1が提供されていたとのこと）、試験内容も最新状況に合わせてしっかり刷新されているように感じられました。Watson APIに限らずですが、Cloudサービスは頻繁に仕様が変わったり、新しい機能もどんどん登場するので、数年前に触ったきりだな・・・というAPIに関しては、一度最新情報もチェックしておくことをオススメします。（実際に出題された問題の中でも、比較的新しめの機能に関する問いも見られました）
    
* 各Watson APIの、Docs/API Referenceに目を通す
    * まずは基本を押さえることは大原則。ユースケースの実現に適したWatson APIはどれか？という類の問題が出ますので、各APIが何が出来るのか？は理解しておくべきです。使った事がないAPIに関しては、チュートリアル等で軽くでも触っておくほうが良いです。
    * さらに、隅々までくまなく読み込むことを推奨
        * 思っていたよりも、重箱の隅をつつかれる問題が多かった印象（=私見です）。エンジニアなら経験と勘で何とかなるんじゃないか？と思って楽観的に挑みましたが、各APIの詳細な仕様に関しては、知らないと答えられないものも多くあったので、数字やメソッド名なども含めて細かく目を通しておいた方が安心です。
        * 特にAssistantやDiscoveryは、意外と奥が深く・・・汗
* 英語力を高める
    * 残念ながら、現時点では試験で選択可能な言語は英語のみでした。重度の英語アレルギーだと、受験は断念せざるを得ないかもしれません。。。
    * テクニカルな用語については、各Docsを英語で読んでおくことで、ある程度慣れることが出来ると思います。

合格ラインの突破が目標であれば、上記を行えていれば対策は十分と思います。
しかしながら、出題範囲に含まれるWatsonサービスの数がまぁまぁあるので、言うは簡単ですが実際にすべてのDocs/API Referenceを読み込むのはそれなりの時間が必要かもしれません。時間的制約がある場合は、「もし未経験のWatsonサービスがあるならそこから着手」「Assistant/Discoveryについては、出題数が多く機能も多岐に渡るので、網羅的に見ておく」など作戦を立てて効率的に勉強し、試験に臨むと良いかもしれません。

#おわりに
IBM Watson v4 Developer受験については、今のところあまり情報源が多くないように思いますが（そもそも日本語対応して欲しい）、みなさんが受験してみようかなと思うきっかけになったら嬉しいです。
一発合格目指してがんばってください。
ActiveRecord::Base.connection.column_exists? メソッドのユースケース

# はじめに

今回はActiveRecord::Base.connectionのcolumn_exists?メソッドの内部実装とユースケースについて書いてみたいと思います。

## 環境

Ruby 2.6.6
Rails 5.2.6

# 内部実装

まずは実装箇所を調べてみます。

```ruby
$ bundle exec rails c

$ ActiveRecord::Base.connection.method(:column_exists?).source_location
=> ["/bundle/gems/activerecord-5.2.6/lib/active_record/connection_adapters/abstract/schema_statements.rb", 132]
```

実装箇所はこちらでした。

https://github.com/rails/rails/blob/5-2-stable/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb#L132


```ruby
# Checks to see if a column exists in a given table.
#
#   # Check a column exists
#   column_exists?(:suppliers, :name)
#
#   # Check a column exists of a particular type
#   column_exists?(:suppliers, :name, :string)
#
#   # Check a column exists with a specific definition
#   column_exists?(:suppliers, :name, :string, limit: 100)
#   column_exists?(:suppliers, :name, :string, default: 'default')
#   column_exists?(:suppliers, :name, :string, null: false)
#   column_exists?(:suppliers, :tax, :decimal, precision: 8, scale: 2)
#
def column_exists?(table_name, column_name, type = nil, options = {})
  column_name = column_name.to_s
  checks = []
  checks << lambda { |c| c.name == column_name }
  checks << lambda { |c| c.type == type } if type
  column_options_keys.each do |attr|
    checks << lambda { |c| c.send(attr) == options[attr] } if options.key?(attr)
  end

  columns(table_name).any? { |c| checks.all? { |check| check[c] } }
end
```

第一引数にテーブル名を、第二引数にカラム名を、それ以降はオプションで指定できるようになっていました。

column_options_keysはprivateメソッドになっており、

```ruby
def column_options_keys
  [:limit, :precision, :scale, :default, :null, :collation, :comment]
end
```

マイグレーション時に指定できるオプション(7種類もあったのか、、、)を配列で返すメソッドになっていました。

# 使い方とユースケース

## 使い方

実際に挙動を確認してみました。前提として、emailというカラムを持つUserモデルが定義されていて、default値が「""」、null: falseが設定されているものとします。

```ruby
# emailカラムが定義されているかどうか
$  ActiveRecord::Base.connection.column_exists?(:users, :email)
=> true

# passwordカラムは定義されていないのでfalseが返る
$ ActiveRecord::Base.connection.column_exists?(:users, :password)
=> false

# emailカラムはstring型なので、第三引数にintegerを渡すとfalseが返る
$ ActiveRecord::Base.connection.column_exists?(:users, :email, :integer)
=> false

# emailカラムのデフォルト値は "" なので、trueが返る
$ ActiveRecord::Base.connection.column_exists?(:users, :email, :string, default: "")
=> true

# emailカラムは null: false なので、trueが返る
$ ActiveRecord::Base.connection.column_exists?(:users, :email, :string, null: false)
=> true

# default: "" と null: false の両方を指定してもOK
$ ActiveRecord::Base.connection.column_exists?(:users, :email, :string, null: false)
=> true
```

実務上で第三引数まで設定して呼び出すことは稀かと思いますが、柔軟なインターフェイスになっている印象です。

## ユースケース

個人的には、フロントから渡ってきたパラメータに応じて、走査するテーブルを変えたい時に使えるかなと思っています。

例えば、複数のテーブルを用いて表示されているデータをソートしたい、となった場合、ソート対象のデータによっては走査するテーブルを分岐させなくてはいけないかもしれません、そのような場合に、column_exists?メソッドを用いて分岐を行うのがアリなのではないかと思いました。

# まとめ

「ActiveRecord完全に理解した」い。(願望)
[MAC]aws-cliでiamアカウントの接続設定

# はじめに
awsを8年以上前に使って、再度仕事で触ったので、覚書。
個人でもそろそろ使ってみようと思ってる。

## CLIインストール

homebrewにてインストール

```terminal
% brew install awscli
```

インストールされたかの確認とバージョンチェック

```terminal
% aws --version
```

ここでバージョンが表示されたら成功

## アクセスキーとシークレットキーの取得
awsのマネージメント画面のユーザページより「認証情報」タグで「アクセスキーの作成」を押下する。
そこでキーを二つ取得できる。

## cli接続

configureコマンドで対話式に情報を登録する。

```terminal
% aws configure
AWS Access Key ID [None]: [アクセスキー]
AWS Secret Access Key [None]: [シークレットキー]
Default region name [None]: [リージョン(ap-northeast-1)]
Default output format [None]:[フォーマット(json)]
```

~/.awsにconfigとcredentialsの2ファイルができる。

```
% ls ~/.aws
config      credentials
```
configureで設定した四項目が記載されている。
credentialsにはアクセスキーとシークレットキー。

## あとは

あとはs3にコマンドでバケット作成などguiでできることができる。
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-services-s3-commands.html

ci環境でバケットに配布物を自動化で送るなどできる

## ついで
静的ページをホスティングするときに閲覧制限をかけたい場合に、バケットポリシーで出来そうかと思っていたがこれは無理だった。basic認証であれば、Lambda + CloudFrontを使うと良いらしい
Windowsで大文字小文字を区別してファイルを扱う方法

普段、WindowsPC上でWSLやVM wareを使用してLinux用のソフトウェアを開発しているのですが、しょうもないところでハマってしまい、イイやり方の記事があまり見つからなかったのでメモに残しておきます。

##Windowsではファイル名の大文字と小文字は区別"しなかった”

Windowsユーザーとしては当たり前といえば当たり前の話で、ファイル名の大文字と小文字は区別しないファイルシステムになっています。
例えば、下記2つのファイルはWindows上では区別してもらません。

* aaa.txt
* AAA.txt

もし"aaa.txt"があるところに、まったく違う内容の"AAA.txt"というファイルをコピーしてしまうと、"AAA.txt"が"aaa.txt"として上書きされるのが仕様です。
つまり、Linux環境下で作ったファイルで"aaa.txt"と"AAA.txt"という全く異なる用途のファイルを同一ディレクトリに保存していた場合、これをWindows環境に持ってくるとどちらか一方が上書きされてしまいます・・・


従来のWindowsでは上記の動作が**``仕様だった``**わけですが、
Windows10では、WSL (Windows Subsystem for Linux)などLinux環境と連携しやすいようになってきたため、Windows上でも小文字と大文字を区別できるようにする技があるようです。

###大文字と小文字を区別するように一括変更するコマンド

fsutil.exeを使って、``フォルダ単位``で大文字と小文字を区別できるように指定できます。
が、``フォルダ単位``というのがクセ物で、いちいちフォルダ毎にちまちま設定しなければいけないため、再帰的に設定するコマンドが下記です。


```コマンド
cd "設定を変更したいフォルダ"
for /R /d %a in (*) do fsutil.exe file SetCaseSensitiveInfo %a enable
```

これでフォルダ以下すべてのフォルダを大文字と小文字を区別してファイルを扱えるようになります。
GASでスプレッドシートの値をGoogleフォームに設定

## フォームの作成

```
function myFunction(){
  const form = FormApp.create('新規作成するフォームの名前')
  form.setDescription('作成されたフォームの説明')
}
```
## 既存のフォームの取得

```
const = FormApp.openById(フォームのID)
```

## フォームに値を反映

あらかじめ取得済み
```
const form = FormApp.openById('xxxxxxxxxxxxxxxxxxxxxxxxxx')
const spreadsheet = SpreadsheetApp.openById('xxxxxxxxxxxxxxxxxxxxxxxxx')
const sheet = spreadsheet.getSheetByName('シート1')
```
### ラジオボタン
#### .addMultipleChoiceItem()
##### 行数固定の場合
```

// 値の入力された列を範囲指定して取得
values = sheet.getRange("C2:C11").getValues()

// 取得した配列（２次元配列）をラジオボタンの項目としてセット
form.addMultipleChoiceItem()
    // 設問を記述
    .setTitle('ラジオボタンから選んでください')
    // 配列を引数に入れる
    .setChoiceValues(values)
    // 必須にするか否か
    .setRequired(true);
}
```

##### 行数を動的に取得する場合
sheet.getRange(2, 3).getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow()
で、実行毎に行数を取得

```
// C列２行目から連続して値があるセルを取得
let lastRow = sheet.getRange(2, 3).getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow()

// C2からCの最終行までを取得
let values = sheet.getRange(`C2:C${lastRow}`).getValues()
console.log(values2)
// 取得した配列（２次元配列）をラジオボタンの項目としてセット
form.addMultipleChoiceItem()
    // 設問を記述
    .setTitle('ラジオボタンから選んでください')
    // 配列を引数に入れる
    .setChoiceValues(values)
    // 必須にするか否か
    .setRequired(true)
}
```

### プルダウン
#### .addListItem()

```
// C2からCの最終行までを取得
let values = sheet.getRange(`C2:C${lastRow}`).getValues()

// 取得した配列（２次元配列）をラジオボタンの項目としてセット
form.addListItem()
    // 設問のタイトル
    .setTitle('枚数は？')
    // プルダウンに表示させる配列
    .setChoiceValues(values)
    // 必須か否か
    .setRequired(true);
```
terraformでコンテナに機密情報を渡す

#ECSでコンテナに機密情報を渡す方法

タスク定義のコンテナ編集の環境変数メニューでValueFromにssmパラメーターのarnを指定し、より安全にコンテナに機密情報を渡すことが可能です。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659469/17c0cec2-7c5f-7e9f-b90d-124d98ee2159.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659469/0d0889ce-0fe8-3cb7-d5cb-f596bd4b294c.png)



https://aws.amazon.com/jp/premiumsupport/knowledge-center/ecs-data-security-container-task/


#terraformでvalueFromの値を設定する方法

terraform公式サイトのtask_definitionのページにはValueの値を設定できるEnvironmentについては記載があるものの、ValueFromを設定できるパラメータの記載はありません。

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_task_definition#example-usage



しかし、AWSコンソール画面からContainedefinitionの項目を確認すると、secretsという値があり、これがValueFromの項目であることが確認できます。ちなみにEnvironmentはValueとなるため、ssmのarnを渡しても、設定したいパラメーターに変換されません。（自分はこれで一度失敗しました）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659469/0c57d96b-f9af-e535-7618-550f09883218.png)



#terraformコード
複数の値を渡す場合が多いと思うので、その際には以下のようにforを使うと楽です。


```terraform:taskdefinition.tf
resource "aws_ecs_task_definition" "example"{

container_definitions = jsonencode(
                       [
                         {
////////////////////省略//////////////////////////////////////
                           secrets = [for k, v in aws_ssm_parameter.parameter_for_ecs :
                           { name      = k
                             valueFrom = v.arn}]
////////////////////省略//////////////////////////////////////
                         }
                       ]
                     )

                   }
```
[Bootstrap]ドロップダウンメニューが隠れて表示されない問題

# 記事の概要
　bootstrapでドロップダウンメニューを実装していたところ、他のブロック要素の下に埋もれてしまいうまく表示されないことがあった。　下図のように解決できました。

解決前：　ユーザーメニューをドロップダウンで実装したところ、メニューの一部が他のブロックの下に埋もれてしまった。
![46e65a643c14afed537c72971495e745.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1430273/c1102491-2bc8-1d0e-82d9-551118d2b331.png)

解決後：　うまく表示された。
![d4c51f7264ef198d825fed99c8c89d7a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1430273/9d84b3e7-3073-d0c8-0511-90a2969d882f.png)

# 原因と解決
　他のブロック要素が存在し、それがposition:fixedなどpositionで位置決めされている場合に起こるようだ。dropdownが所属する要素の階層が、他のブロック要素より下にあると、このように隠れてしまう。 z-indexで階層の指定を考慮し、dropdownメニューを上に持ってくることで解決できた。

```css
.dropdownが所属するブロック要素{
  position: fixed;
  z-index: 2;
}

.他のブロック要素{
  position:fixed;
  z-index: 1;
}
```
Azure ML デザイナーでの画像分類サンプルで何をやっているのか確認してみる。

# Azure Machine Learning デザイナーとは
Azureの提供する機械学習プラットフォームであるAzure Machine Learningでは自動機械学習やGUIベースで機械学習を行える機能、一般的なものとしてJupyter互換のNotebookが提供されています。本記事ではGUIツールであるデザイナーを用いて画像分類(深層学習)のプロセスをどう組んでいくのか、サンプルから深堀する形で確認します。

# サンプル
デザイナーを開くとサンプルがいくつか用意されているのですが、`Image Classification using DenseNet`を対象とします。

全体の構成は以下の画像のようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/e09ca7bc-1400-7f7a-68b3-5e694f19ecd0.png)

まず、入力となる画像データセットは以下のようなファイル構造になっている必要があります。

```
Your_image_folder_name/Category_1/xxx.png
Your_image_folder_name/Category_1/xxy.jpg
Your_image_folder_name/Category_1/xxz.jpeg

Your_image_folder_name/Category_2/123.png
Your_image_folder_name/Category_2/nsdf3.png
Your_image_folder_name/Category_2/asd932_.png
```

このファイル構造を持ったローカルファイルやデータレイクなどのディレクトリをファイルデータセットとしてワークスペースに登録します。ローカルファイルの場合は.zip等の圧縮ファイル推奨。その後、登録したデータセットをキャンバス上に配置。

`Convert to Image Directory`と接続します。これはAzure ML上で画像データを扱うためのImageDirectory型への変換のようなものになっています。

https://docs.microsoft.com/ja-jp/azure/machine-learning/algorithm-module-reference/convert-to-image-directory

次に来ている`Split Image Directory`はデータを分割することができます。サンプルではTraining/Validationデータ：Testデータ=9:1に分割し、Trainingデータ:Validationデータ=9:1に分割しています。ValidationデータとTestデータは混同されがちですが、推論結果を次の学習に反映する際に用いるのがValidationデータ、汎化性能を測るために1度のみ利用する完全な未知データがTestデータというような解釈で良いと思います。

`Init Image Transformation`では、画像の前処理としてどのような変換をかけるのか指定します。ここで指定したパラメータを用いて、後の`Apply Image Transform`を実行します。サンプルでは、ImageDirectory型のデータを分割してから変換を適用しましたが、データ分割前に一括で変換してしまった方がシンプルかもしれません(実行していないので確信は持てませんが)

`DenseNet`はTrainするモデルを指定しています。理論的なところは[Densely Connected Convolutional Networks](https://arxiv.org/abs/1608.06993)をご覧ください。画像データの扱える畳み込みニューラルネットワークの一種です。選択肢としては`ResNet`も対応しています。

`Train PyTorch Model`は上記の`DenseNet`及び`ResNet`をPyTorch上で学習させるためのモジュールです。**エポック数**や**バッチサイズ**、**学習率**をここで指定します。モジュール名と異なり用途は限られています。データセットが大規模な場合は、GPU型のコンピューティング環境が推奨されるので、ワークスペース上から設定しましょう。各エポックにおける評価のためのValidationデータも入力として必要になってきます。

https://docs.microsoft.com/ja-jp/azure/machine-learning/algorithm-module-reference/train-pytorch-model

サンプルの構成には組み込まれていませんが、ハイパーパラメータの調整用のモジュールもあるようです。グリッドサーチ等の設定が可能です。

https://docs.microsoft.com/ja-jp/azure/machine-learning/algorithm-module-reference/tune-model-hyperparameters

最後にいつも通り、`Score Model`モジュールでTestデータに対して推論を行いモデルの最終的な評価をします。問題なければ推論パイプラインを作成・発行して利用を開始できます。

# データのラベル付け
画像分類は教師あり学習に当たります。それゆえ独自の学習データのラベル付けをする際に非常に手間がかかり、これがハードルになってしまうことが多々あります。AzureMLの昨日のアップデートにより、この作業をサポートするGUI機能が追加されました。

ファイルデータセット内の画像に対してラベルを付ける処理がかなり楽になります。ラベル付けの結果はそのままAzure MLデータセットもしくはCOCO形式でエクスポートすることが可能です。学習データ生成から学習までAzureMLワークスペース上でスムーズに連携することが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/de75f679-29be-5c60-9ea6-8418eb34a398.png)

画像数が多い場合はある程度手動で分類した後、**MLによるラベル付け**機能を有効化することでAIを利用することも可能です。

# さいごに
自分のデータでやってみてまた躓くポイントがあれば共有したいと思います！