OmniAICreator/Qiita-1.07M huggingface dataset:
macOS起動時にスクリプトを実行する

# やり方 (概略)
1. スクリプト作成
2. スクリプトをLaunchdに登録するための.plistを作成 (権限や配置に注意)
3. .plistを読み込む

# 具体例
### 1.スクリプト作成

```shell:~/launch_scripts/hello/hello_shell.sh
echo hello_world
```

### 2. スクリプトをLaunchdに登録するためのplistを作成 (権限に注意)

* .plistの配置場所は以下の通り
    * `~/Library/LaunchAgents`
        * 各ユーザが管理する各ユーザユーザごとに実行するエージェントの格納ディレクトリ
    * `/Library/LaunchAgents`
        * 管理者が管理するする各ユーザごとに行するのエージェントの格納ディレクトリ
    * `/Library/LaunchDaemons`
        * 管理者が管理するシステムで実行するデーモンの格納ディレクトリ（ログイン状態に依らない）
    * `/System/Library/LaunchAgents`
        * OS が管理する各ユーザごとに実行するエージェントの格納ディレクトリ（基本的に触らない）
    * `/System/Library/LaunchDaemons`
        * OS が管理するシステムで実行するデーモンの格納ディレクトリ（基本的に触らない）

```xml:/Library/LaunchAgents/hello.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <!-- launchd プロセスで一意ならOK -->
    <key>Label</key>
    <string>com.example.hello</string>

    <!-- 実行するコマンド -->
    <key>ProgramArguments</key>
    <array>
        <!-- ~が使えないことに注意 -->
        <string>/Users/ritumutaka/launch_scripts/hello/hello.sh</string>
        <string>引数1</string>
        <string>引数2</string>
    </array>

    <!-- launchd を読み込んだタイミングで実行 -->
    <key>RunAtLoad</key>
    <true/>

    <!-- ログ保存用 -->
    <key>StandardOutPath</key>
    <string>/Users/ritumutaka/launch_scripts/hello/std_out.txt</string>
    <key>StandardErrorPath</key>
    <string>/Users/ritumutaka/launch_scripts/hello/std_err.txt</string>
</dict>
</plist>
```

* hello.plistのシンタックスエラーをチェック
    * `$ plutil -lint hello.plist`
* 問題なければ以下のように出力される
    * `hello.plist: OK`

### 3. plistを読み込む
* 読み込みコマンド (実際にスクリプトが実行される)
    * `$ launchctl load ~/Library/LaunchAgents/hello.plist`
* テストしたい場合、再ロードすれば良い
    * `$ launchctl unload ~/Library/LaunchAgents/hello.plist`
    * `$ launchctl load ~/Library/LaunchAgents/hello.plist`

## 管理者権限で実行する場合
* 所有者、権限、配置を確認
    * `$ cd /Library/LaunchDaemons`
    * `$ ls -l`
    * ダメな例: `-rw-rw-r--@ 1 ritumutaka  staff   843  6 26 18:05 hello.plist`
    * 良い例: `-rw-r--r--@ 1 root  staff   843  6 26 18:05 hello.plist`

* .plistファイルの所有者をrootにする
    * `$ sudo chown root /Library/LaunchDaemons/hello.plist`
* 権限は「-rw-r--r--」 (644)
    * `$ sudo chmod 644 hello.plist`
* テスト時はsudo付きでロード
    * `$ sudo launchctl load ~/Library/LaunchAgents/hello.plist`

## Load failed: 5: Input/Output error
* ファイルの所有権
    * 管理者権限で実行する場合はroot、ユーザー実行なら対象ユーザー
* 権限
    * 管理者権限なら「644」、ユーザー実行なら「664」
* unloadかけてない
    * 再ロードする場合はちゃんと以下の順番で行うこと
        * `$ launchctl unload`
        * `$ launchctl load`
SIGNATE【第10回_Beginner限定コンペ】振り返り

先月、SIGNATEのデータ分析コンペ「【第10回_Beginner限定コンペ】携帯電話の機能データからの価格帯分類」に参加し、結果を残してIntermediateに昇格したので記事を書きたいと思います。

### 試した機械学習モデル
コンペに十分な時間が確保できなかったので、全ての学習用データをモデルで学習させて、投稿した評価を確認するという方針を取りました。
多クラス分類で有用なモデルを調べて順番に試していきました。

ソースコードはモデルの学習部分と予測部分を中心に載せていきます。 

#### ①ロジスティック回帰
```python
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(X, y)
pred = model.predict(test)
```
評価結果：0.329898387944778
「price_range」の0が分類されなくて低評価でした。 

#### ②SVM
```python
from sklearn import svm
model = svm.SVC()
model.fit(X, y)
pred = model.predict(test)
```
評価結果：0.35707209352720193
ロジスティック回帰と同様に「price_range」の0が分類されなくて低評価でした。

#### ③ランダムフォレスト
```python
from sklearn.ensemble import RandomForestClassifier as classifier
model = classifier()
model.fit(X, y)
pred = model.predict(test)
```
評価結果：0.44010013376233836
「price_range」の0もしっかり分類されていて高めの評価でした。
0.448以上でIntermediateに昇格だったので非常に惜しかったです。

#### ④XGBoost
プログラムが上手く動かなかったので断念しました。

#### ⑤ニューラルネットワーク
こちらもプログラムが上手く動かなかったので断念しました。

#### ⑥LightGBM
勾配ブースティングツリーの簡単なプログラムで調べたら出てきたので試してみました。

```python
import lightgbm as lgb
model = lgb.LGBMClassifier()
model.fit(X, y)
pred = model.predict(test)
```
評価結果：0.4591868948938814
0.448を超えてIntermediateに昇格することができました。


#### GitHub
GitHubで今回のコンペのソースコードを公開しています。
https://github.com/mtfuka/SIGNATE/tree/main/%E3%80%90%E7%AC%AC10%E5%9B%9E_Beginner%E9%99%90%E5%AE%9A%E3%82%B3%E3%83%B3%E3%83%9A%E3%80%91%E6%90%BA%E5%B8%AF%E9%9B%BB%E8%A9%B1%E3%81%AE%E6%A9%9F%E8%83%BD%E3%83%87%E3%83%BC%E3%82%BF%E3%81%8B%E3%82%89%E3%81%AE%E4%BE%A1%E6%A0%BC%E5%B8%AF%E5%88%86%E9%A1%9E



### 学んだこと
LightGBMは、データに特に手を加えず簡単に予測結果を出したい時に有用。比較的高速で、精度も出やすい。


### 反省点
時間が無かったのでモデルに学習させるだけになってしまいましたが、しっかり特徴量を分析して、適切なモデルを選択し、評価を行うという手順を踏みたかったです。


### 今後の展望
典型的な分析手法や機械学習モデルの特徴について理解を深め、問題に合わせて適切に分析が行えるように知識を吸収していきたいと思います。
また、問題に応じて、新たな特徴量の作成やアンサンブルができるように、積極的にコンペに参加して経験を積んでいきたいです。
EBSボリューム それぞれの違い

## 勉強前イメージ

プロビジョンドIOPS と スループット最適化 がややこしい

## 調査

元々EBSについては [こちら](https://qiita.com/miyuki_samitani/items/20a1d74657668578180b) で軽く触れていたのですが、
`プロビジョンド IOPS SSD` と `スループット最適化 HDD` の違いがごっちゃになるので、
再度調べてまとめました。

### そもそも種類のおさらい

- HDDボリューム
	- スループット最適化 HDD(st1)
	- Cold HDD(sc1)

- SSDボリューム
	- 汎用 SSD(gp3)
	- 汎用 SSD(gp2)
	- プロビジョンド IOPS SSD(io2)
	- プロビジョンド IOPS SSD(io1)

今回は `プロビジョンド IOPS SSD(io1)` と `スループット最適化 HDD(st1)` で比べてみます

#### スループット最適化 HDD(st1)

そもそもスループットとは機器が単位時間あたりに処理できるデータ量のことです。
どれだけ転送できるか？みたいなことを表しています。
サイズの大きな連続したデータを処理するのに適しています。
ただし起動ボリュームにすることは出来ません。

- ボリュームサイズ : 125GiB ～ 16TiB
- ボリュームあたりの最大 IOPS (1 MiB I/O) : 500
- ボリュームあたりの最大スループット : 500 MiB/秒

#### プロビジョンド IOPS SSD(io1)

パフォーマンスの高いIOPS性能を必要とするのがこちらになります。
IOPSとはInput/Output Per Secondの略で、1秒間に読み込み・書き込みできる回数のことを指しており
IOPSの値が高いほど高速にデータの読み書きができます。
provisionは供給・準備の意味なのでIOPSの準備をしているってそのままでは読めます。

- ボリュームサイズ : 4GiB ～ 16TiB
- ボリュームあたりの最大 IOPS (16 KiB I/O) : 64,000
- ボリュームあたりの最大スループット : 1,000 MiB/秒

#### スループットとIOPSの違い

- IOPS : ストレージが1秒あたりに処理できるI/O(書き込み・読み込み)アクセスの数
- スループット : 単位時間あたりでどれくらいデータを転送できたか

もっとわかりやすくすると
iopsはストレージに書き込むのが早いかどうか。
スループットは処理能力が高いかどうか。をみてる。

#### ユースケース

- スループット最適化 HDD(st1)
	- ビッグデータ処理
	- データウェアハウス
	- ログ処理

- プロビジョンド IOPS SSD(io1)
	- RDBMS
	- I/O負荷の高いNoSQLデータベースとリレーショナルデータベース

iopsが高いと、何回も何回もDBに書き込むのが有利 → リレーショナルデータベースとかで使われる
スループットの性能が高いと、大量のデータをさばける → ログ処理とかで使われる

## 勉強後イメージ

イメージわかった気がする
HDDで大量のデータをさばく→スループット最適化 HDD(st1)
SSDで書き込み読み込みを早くする→プロビジョンド IOPS SSD(io1)
って感じかな？
あまりきれいにまとめられてないけど自分的には今は納得できた。

## 参考
- [EBSの「st1」と「sc1」の性能の違いについて](https://it-kyujin.jp/article/detail/2079/)
- [Amazon EBS ボリュームの種類](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ebs-volume-types.html)
- [IOPSとスループットのちがい](https://dev-labo.com/aws/difference-iops-throughput/)
【初心者】RailsでSlimを書いてみよう

## そもそもSlimとは
**Railsのテンプレートエンジンの種類の１つ**
デフォルトでは**ERB**というテンプレートエンジンを採用しています。
※テンプレートエンジン：HTMLのテンプレートとそこに記述された動的な処理からHTMLを生成するための仕組みのこと

## Slimを使うメリット
- インデントでツリー構造を表現しているので、ERBと比較してタグの開始と終了を記述しないため簡潔で読みやすい
- 他のテンプレートエンジンに比べて高速・軽量に動作する

# Slimの導入
```ruby:Gemfile
gem 'slim-rails'
gem 'html2slim'
```

```ruby:ターミナル
$ bundle install
```

次にERB形式のファイルが存在しているので、erb2slimを用いてSlimに変更します。
あとERBファイルも削除します。

```ruby:ターミナル
$ bundle exec erb2slim app/views/layouts/ --delete
```

config/application.rbにあるconfigを以下のように記述する。

```ruby:config/application.rb
module App
  class Application < Rails::Application
    config.generators.template_engine = :slim #slimに変更
  end                                                                                                                                                                     
end
```

#基本的な記述方法
ERBがわかる方は、以下の内容を見ればなんとなく書けると思います。

| html.erb | html.slim |
|:------------:|:------------:|
| <%= %>       | =            |
| <% %>        | -            |
| id="hoge"    | #hoge        |
| class="hoge" | .hoge        |
| <!-- -->     | /            |

## htmlタグの記述

```ruby:html.slim
h1 タイトル
p テキスト
a リンク
img src="https://hogeimage"
```

```html:.html
<h1>タイトル</h1>
<p>テキスト</p>
<a>リンク</a>
<img src="https://hogeimage" />
```

*テキストについての記述はこの後に詳細を書きます。

## テキストの記述
テキストは **|(パイプ)を使います。**
メリットとして、**|より後ろはテキストとして扱われるため、タグの横ではなく、タグの下に記述することで長文の場合に見やすくなる**

```ruby:html.slim
p
  | 
　　テキストテキストテキストテキストテキストテキスト
```

```html:.html
<p>テキストテキストテキストテキストテキストテキスト</p>
```

**【＊注意点＊】**
**タグのすぐ後ろに|をいれると、|もテキストとして認識されます。**


```ruby:html.slim
p | テキスト
```

```html:.html
<p>| テキスト</p>
```

## class, idの記述
先程の表を参考に「.」「#」を使ってclassとidを指定した記述をしてみます。

```html.slim
div.container
  div.content1
    h1#title タイトル
    p.text1 テキスト1
  div.content2
    p.text2 テキスト2
```

```html
<div class="container">
  <div class="content1">
    <h1 id="title">タイトル</h1>
    <p class="text1">テキスト1</p>
  </div>
  <div class="content2">
    <p class="text2">テキスト2</p>
  </div>
</div>
```

## if文の記述
endの記述忘れがなくなるから助かります。

```ruby:html.erb
- if current_user.nil?
  li 新規登録
- else
  li ログイン
```

```html:html.erb
<% if current_user.nil? %>
  <li>新規登録</li>
<% else %>
  <li>ログイン</li>
<% end %>
```

## 終わりに
私自身がまだまだSlimを触り始めたばかりですので、基礎的な記述方法しか扱えません。
今後も内容追加していきますので、お願い致します。
GoogleMapAPIの注意点

これはメモのために書いたものである。
#GoogleMapでの処理
　　XMLHttpRequestを非同期処理にさせたことで、Wordpressのページがリロードの度に、Google Map のピンが消えてしまうエラーが起きていた。まずは、全体的に現在地を取得するために、非同期関数を作成して、それをバックグランドで実行させていた。次に、マーカー（ピン）を挿すために、CSVファイルから情報を取得して、その情報をもとに作成した。
　　markerwithlabelというライブラリを使っていた。このライブラリはかなり有能なので、共有しておく。
https://github.com/googlemaps/js-markerwithlabel
　　Map開発やピンを加工したい人は使うとだいぶ作業が楽になる。

#エラー・問題点
　　そもそも、最初に読み込めたのに、なぜ保存していたcsvの中身が消えるのかが謎だった。理由としては、キャッシュやクッキーがかかわっているかなと思って、それらを削除してもう一回実行しても同じだったので断念した。次に、実行する順番がおかしいと思って、csvを取得するコードを、非同期処理に入れた。これもうまく結果が出ず、やめることになった。
　　ここから、同期と非同期ってなんだについて説明する。

##同期・非同期処理
　　同期処理は、最初のコードから次のコードへと順次処理されていくこと。非同期処理は、ある処理が終了するのを待たずに、別の処理を開始すること。いわば、バックグランドで実行するかどうかが同期と非同期の違い（個人の見解）。
　　だから、csvの取得は非同期処理でいいんだなって思った。それが最も違うことだろうな。非同期XMLHttpRequestを使用すると、データが到着したときにコールバックを受け取る。これにより、リクエストが処理されている間に、ブラウザは通常通り動く。逆に言えば、再度取得した場合（リロード）、コールバックが動かない。これにより、csvデータを取得した変数の中身は前の情報のままになる。これを同期処理させれば、エラーが起きなくなった。CSVを取得する処理が同期か非同期かは今回のエラーが起きた原因といえる。

エラー文：

```javascript:Error
Uncaught (in promise) TypeError: Cannot read property '2' of undefined
//この2は二番目の情報を取得するものである。似ていいるようなエラーが起きた人は同期・非同期について詳しく調べてみるとよい。
```
Node-REDでHello World!

#Node-REDとは

> Node-REDはフローベースドプログラミング(flow-based programming)ツールであり、元はIBM Emerging Technology Servicesチームによって開発され、JS Foundation配下のプロジェクトを経て、2019年3月よりNode.js FoundationとJS Foundationが合併して設立されたOpenJS Foundationにホストされています。

[Node-RED User Group Japan - 概要](https://nodered.jp/about/)


- ブラウザ上のエディタを使って、ノーコード、ローコードで開発できるOSSです。
- デザイナ上で、[ノード]を作成・処理を記載、[ノード]間を接続し、データを受け渡して処理を行うフローベースのプログラミングです。
- Node.js上で動作しています。IoT機器、PC端末などのエッジデバイス、フロントエンド、バックエンドまで動作させる事が出来ます。

#実行環境
- WSL上のUbuntu 18.04 LTS 
- Dockerインストール済み

#Dockerで起動。

- 以下コマンドを実行
	- /home/user1/dev/node-redでコマンドを実行
	- /home/user1/dev/node-red/.node-red を永続化しています。

```
docker run -it -p 1880:1880 -v /home/user1/dev/node-red/.node-red:/data --name mynodered nodered/node-red
```

- 正常に実行されると以下のメッセージが表示されます。

```
26 Jun 07:47:08 - [info] Server now running at http://127.0.0.1:1880/
26 Jun 07:47:08 - [info] Starting flows
26 Jun 07:47:08 - [info] Started flows
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/4c2f1feb-967a-49b6-0575-2e7e043d34a0.png)



- ブラウザで ``` http://localhost:1880/ ``` にアクセスします。
- エディタに無事アクセス出来ました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/3359a4db-c318-5804-ac86-eb0e5a3ccddb.png)


#チュートリアルを実施

- [公式のチュートリアル - 初めてのフロー](https://nodered.jp/docs/tutorials/first-flow)を実施します。

- Injectノード・Debugノードを追加、2つのノードをワイヤーでつなぎます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/dead44cf-7a1b-03ab-db7a-b4cdfcd1f62d.png)

- デプロイボタンをクリックし、デプロイします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/10d5c889-8efb-1988-67a2-71ea38888a08.png)


- デバッグタブを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/16cc981f-73e2-834b-099c-a7108cc8c592.png)

- プログラムを実行したいと思います。
- [Inject]ノードのボタンをクリックしましょう。タイムスタンプがメッセージ出力されるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/98ec1f9d-9689-9341-2355-cb403922da1b.png)

- 想定通り、タイムスタンプが出力されました。

# Hello Worldを作成

- 少し、改良して"Hello World"の文言を出力してみます。

- [Injection]ノードを削除、[Function]ノードを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/aa790092-2e22-47eb-a95f-d9d68418b456.png)

- [Function]ノードをダブルクリックし、[コード]に以下入力します。

```
msg.payload = "Hello! World";
return msg;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/ab34d42d-38c0-bd7e-bbee-688d8c19289e.png)

- [完了]ボタンをクリックします。

- [Injection]ノードを追加し、以下編集します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/3016dbb8-28db-9df8-916a-a1ce57c18aed.png)


- 再び、[Injection]ノードと[Function]ノードと[Debug]ノードをワイヤーでつなぎます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/ad8c0c5c-9b72-3021-6f7f-7db3e24a5d90.png)


- 先ほどの手順と同様に[デプロイ]ボタンをクリックします。

- [Injection]ノードをボタンをクリックし、プログラムを実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/b7825c57-06e9-8635-d9b0-1314430d680b.png)

- 以下、無事に"Hello World"が出力されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/dab95f2b-5022-f775-a494-012fca045c07.png)
JavaScript エラー

フリマアプリの実装で販売手数料、販売利益の表示が変わるようにJavaScriptを使用し
コンソールログで確認したところ早速エラーに遭遇。

```
Uncaught Error: Cannot find module './price'
```

最初に立てた仮説としてはpriceというモジュールが見つからないと言われていると思ったが
結論としてはディレクトリの構造が違っていたためエラーが発生してしまった。

```
require("../item_price");
```

作成したJSファイルが読み込めるように上記の記述をしていたが
コードの..の意味を理解できいない状態で進めていたのが問題だった。

この..は記述したディレクトリの上の階層の/item_priceを参照して下さいと言った意味で使うようで
JavaScriptではよく使う記述のようだ。

皆様も上記の記述をされる際はディレクトリの階層気をつけてみて下さい。
[Rails] deviseにActiveStorageを用いてユーザーのアイコンを設定する

# はじめに
本記事に従えば、deviseでのユーザーのアイコンを設定できます。
保存先としてAWSのS3を利用しています。

# 手順
① ActiveStorageをインストールする
② 保存作の変更(AWS S3)
③ Userモデルとの関連付け
④ アップロードと表示

# ActiveStorageをインストールする

```
$ rails active_storage:install
$ rails db:migrate
```

このコマンドでActiveStorageがインストールされ、データベースに```active_storage_attachments```, ```active_storage_blobs```, ```active_storage_variant_records```が追加されます。

# 保存先の変更
保存先にはAWSのS3を使います。
AWSのアクセスキーIDとシークレットキーを環境変数にするため、Gemfileに以下を追加します。
アクセスキーとシークレットキーを取得する方法は、下記を参考にしてください。

https://tech-blog.s-yoshiki.com/entry/135#%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%82%AD%E3%83%BCid%E3%81%A8%E3%82%B7%E3%83%BC%E3%82%AF%E3%83%AC%E3%83%83%E3%83%88%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%82%AD%E3%83%BC

``` Gemfile.
gem 'dotenv-rails'
```

```
bundle install
```

次に.envファイルを用意し、環境変数を設定していきます。

``` env.
MY_ACCESS_KEY_ID='アクセスキーID'
MY_SECRET_KEY_ID='シークレットキー'
```

GitHubを利用している方は、このファイルをリポジトリに上げないために、

``` gitignore.
/.env 
```

を追記してください。

次に保存先を変更します。

``` config/storage.yml
test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>

local:
  service: Disk
  root: <%= Rails.root.join("storage") %>

amazon:
  service: S3
  access_key_id: <%= Rails.application.credentials.dig(:aws, "ENV['MY_ACCESS_KEY_ID']") %>
  secret_access_key: <%= Rails.application.credentials.dig(:aws, "ENV['MY_SECRET_KEY_ID']") %>
  region: リージョン名
  bucket: バケット名
```

``` config/environments/development.rb
# :localから:amazonに変更することで、先ほど定義したamazon:を読み込みさせる。
config.active_storage.service = :amazon
```

AWS用のGemを追加します。

``` Gemfile.
gem 'aws-sdk-s3', require: false
```
```
bundle install
```

# Userモデルとの関連付け
``` user.rb
#省略
  has_one_attached :avatar # 追加
```
# アップロードと表示
avatarをアップロードするため、deviseのストロングパラメーターを変更します。

``` application_controller.rb
  def configure_permitted_parameters
    # devise_parameter_sanitizer.permit(:sign_up, keys: [ :avatar] )  signupするときも設定したい場合はコメントアウトを消してください
    devise_parameter_sanitizer.permit(:account_update, keys: [ :avatar])
  end
```

``` registration_controller.rb
  def update
    super
    if account_update_params[:avatar].present?
      resource.avatar.attach(account_update_params[:avatar])    
    end
  end
```
これでユーザー情報を編集する際にavatarを設定できるようになりました。
実際にavatarを設定するためにviewを変更します。

``` views/registrations/edit.html.erb
#追加

<div class="field">
　　<%= f.file_field :avatar %>
</div>
```

表示したい時は

``` 
<%= image_tag rails_blob_path(@user.avatar) %>
```
を任意のviewに追加してください。
ggplot2を使用して棒グラフ＋エラーバー＋ドットプロットを描く

(2021.7.2修正 データフレームを2つ使用してプロットを重ねる手法を示していましたが、ggplotのstat_summaryで求めた統計値を用いる手法に変更しています)

近年、生物科学分野ではデータの透明性が求められており、実験結果の平均値や分布を示す棒グラフとエラーバーだけではなく、個別データをプロットした図が求められるようになりました。

こういった図はGraphPad Prism (https://www.graphpad.com) などのアプリケーションを使用すれば比較的容易に描くことができますが、有料ですし、使用できるとしても研究室の共用端末でしか使用できないことも多いでしょう。

本記事ではRのggplotを使用し、下記のような棒グラフ＋エラーバー＋ドットプロットを描出する手法ついて述べます。

![plot.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670918/4bc1a2aa-ccbf-b08d-385b-b942eb223855.jpeg)


本記事の手法では、可能な限りそのまま論文に使用できるビジュアルにすることを目指しました。

## 準備
まずパッケージを読み込みます。

```{r}
library(ggplot2)
```

今回使用するテストデータを作成します。
野生型(WT)とノックアウト(KO)の測定値(value)として、次のようなデータフレームがあるとします。

```{r}
# シードを固定
set.seed(1234) 

# factor型で並び順を指定
genotype <- factor(c(rep("WT", 10), rep("KO", 10)), 
                   level = c("WT", "KO")) 

# 正規分布乱数生成。KO群の平均値と標準偏差を大きめに設定
value <- c(rnorm(10, mean = 10, sd = 2), 
           rnorm(10, mean = 15, sd = 3))
 
# データフレーム作成
df <- data.frame(genotype = genotype,
                 value = value) 
df
```

## 図の描出

```{r}
p <- ggplot(df, aes(x = genotype, y = value, fill = genotype))+
 # stat_summaryで得られた平均値を用いて棒グラフを描出
  stat_summary(fun = "mean", geom = "bar", width = .6) +
  scale_fill_manual(values = c("lightgrey", "darkgrey"))+
 # stat_summary で得られた平均値と標準偏差を用いてエラーバーを描出
  stat_summary(fun.max = function(x) mean(x) + sd(x), 
               fun.min = function(x) mean(x) - sd(x), 
               geom = 'errorbar', width = .3)+
 # dfの個別データをドットプロットで描出
  geom_jitter(aes(shape = genotype), width = .2, size = 3)+
 # y軸の範囲を設定、プロット領域の拡張をゼロに設定することで棒グラフが浮かないようにする
  scale_y_continuous(expand = c(0, 0), limits = c(0, max(df$value)*1.5))+ 
 # 体裁を整える。classicだけではいくつかの部品の色が黒ではないため、修正。凡例はお好みで。
  theme_classic()+ 
  theme(axis.title = element_text(size = 10),
        axis.text = element_text(size = 10, color = "black"),
        axis.ticks = element_line(color = "black"),
        legend.position = "none")+
　# ラベル
  labs(x = NULL, y = "value")
```

```{r}
p
```
![plot.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670918/4bc1a2aa-ccbf-b08d-385b-b942eb223855.jpeg)

少し上にスペースを広めにとっているのは必要に応じて凡例やP値などを追加するためです。


## 図の保存

作成した図を保存します。PDFをIllustratorで読み込めば、埋め込み後に部品にバラして体裁を整えることが可能です。

```
ggsave("plot.pdf", p)
```


## まとめ

本記事はggplotを用いて棒グラフ＋エラーバー＋ドットプロットを描く方法を示しました。より良い方法があればぜひフィードバックをいただけると幸いです。
OLE DBを使ってOracle、Access、MySQLへのSQL接続のラッピング

データベースがいくつかの種類がある時に、データベースを意識せずに業務ロジックを書けるようにする。

1.Excel VBAや.NETの場合は、OLE DBを使用してデータベース接続を共通化する。
2.共通関数を用意して業務ロジックとデータベースへのアクセスを分離する。


#ソース
https://github.com/tosisasa/dbaccess
初心者がVScodeでESLintを導入してみる

#Lintとは
決められたルールに基づいて、自動的にコードのチェックを行うツールです。
この記事では、VScodeをあまり使ったことがない人に向けて、VScode初心者の私が説明をします。

#インストール
###拡張機能：VS Code ESLint extensionをインストールする
VS Code ESLint extensionをインストールする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/764409/0ac63aae-f258-1a04-6dbb-c052f9e1cb4c.png)

###VScodeでターミナルを開く
ESLintを導入したいプロジェクトのフォルダを開いた状態で、
VScodeの「view」→「terminal」を選択して、ターミナルを開く

###ESlintをインストールする
```command:terminal
npm install -g eslint
```
上記コマンドにてインストールを完了します

```command:terminal
eslint -v
v7.29.0
```
インストールがされている場合には、上記コマンドからversionの確認ができます。

###package.jsonファイルを作成する
```command:terminal
npm init
```
設定に関しての質問がありますが、全てEnterで良いです。

###プロジェクト内にeslintの設定ファイルを作成する
```command:terminal
eslint --init
```
設定についての質問があります。こちらはご自身のプロジェクトに適した形で質問に答えましょう。

```command:terminal
✔How would you like to use ESLint? 
訳：ESLintをどのような目的で使いますか？
　　　 To check syntax only　　訳：構文チェックのため
　　 　To check syntax and find problems　　訳：構文チェックと問題発見のため
　　　 To check syntax, find problems, and enforce code style　　訳：構文チェック、問題発見、コーディングスタイルの統一のため
✔ What type of modules does your project use? 
訳：プロジェクトではどのタイプのモジュールを使っていますか？
　　　 JavaScript modules (import/export)
　　　 CommonJS (require/exports)
　　　 None of these
✔ Which framework does your project use?　
訳：プロジェクトではどのフレームワークを使っていますか？
 　 React
 　 Vue.js
　　　 None of these
✔ Does your project use TypeScript?
訳：プロジェクトでTypeScriptを使っていますか？
　　　 y/N
✔ Where does your code run? 
訳：実行環境はどこですか？
  Browser
  Node
✔ How would you like to define a style for your project?
訳：スタイル定義をどのようにしますか？
  Use a popular style guide.  訳：人気のスタイルガイド
  Answer questions about your style　　訳：スタイルについての質問へ進む
  Inspect your JavaScript file(s)　　　訳：JavaScriptファイルを検査する
✔ Which style guide do you want to follow?
訳：どのスタイルガイドに従いますか？
　　　　Airbnb: https://github.com/airbnb/javascript
  Standard: https://github.com/standard/standard
  Google: https://github.com/google/eslint-config-google
✔ What format do you want your config file to be in? 
訳：コンフィグファイルはどのフォーマットにしますか？
　　　　JavaScript
  YAML
  JSON
```

これにて適用完了です。
Rspecで複数のモデルのカウントが増加しないことを検証する

会社でRspec書いてて、「createアクションを動かしたときにAモデルとBモデルのカウントがともに増加しないこと」を検証する必要があった。その時

```ruby
expect {
  post :create, params
  }.not_to change(Hoge, :count).and change(Fuga, :count)
```

のように書くと以下のエラーが発生

```
NotImplementedError:
`expect(...).not_to matcher.and matcher` is not supported, since it creates a bit of an ambiguity. 
Instead, define negated versions of whatever matchers you wish to negate with
`RSpec::Matchers.define_negated_matcher` and use `expect(...).to matcher.and matcher`.
```

ような`not_to change ... and change ...`みたいな書き方はできませんよ、という話。

これを解消するにはエラー文にある通り以下の1行をはさむ。`change`の否定として`not_change`というのを定義しますよという意味。

```ruby
# change マッチャの否定を定義する
RSpec::Matchers.define_negated_matcher :not_change, :change
expect {
  post :create, params
  }.to not_change(Hoge, :count).and notchange(Fuga, :count)
```

なんで`not_to change ... and change ...`使えないの？って感じだけどまぁ1行挟むくらいならいいか…

Rspecのマッチャは奥が深いわねー

参考
https://qiita.com/harashoo/items/a4f1e01d300b6d329dee
PythonとExcel VBAでのWeb API比較（T&D おんどとり Web Storage）

PythonとExcel VBAの両方で、同じWeb APIを呼び出してコードの違いを確認した。

なお、Web APIはT&Dのおんどとり Web Storageを使用した。おんどとり Web Storageの利用にはT&Dの製品購入が前提となる。

# おんどとり WebStorage API
WEB API仕様は次の通り。

https://ondotori.webstorage.jp/docs/api/index.html


今回はその中から現在値の取得と指定期間・件数によるデータの取得を試した。

https://ondotori.webstorage.jp/docs/api/reference/devices_device.html

https://ondotori.webstorage.jp/docs/api/reference/devices_data.html

#リクエストヘッダ

```python
header = {'Host':'api.webstrage.js:443','Content-Type': 'application/json','X-HTTP-Method-Override':'GET'}
```

```vb
Dim httpReq As New XMLHTTP60   '「Microsoft XML, v6.0」を参照設定
httpReq.Open "POST", "https://api.webstorage.jp/v1/devices/current"
httpReq.setRequestHeader "Host", "api.webstrage.js:443"
httpReq.setRequestHeader "Content-Type", "application/json"
httpReq.setRequestHeader "X-HTTP-Method-Override", "GET"
```

#リクエストボディ

```python
paylord = {'api-key':api_key,"login-id":login_id,'login-pass':password}
```

```vb
Dim sRequestBody As String
sRequestBody = "{"
sRequestBody = sRequestBody + """api-key"":""" & apikey & """"
sRequestBody = sRequestBody + ",""login-id"":""" & loginid & """"
sRequestBody = sRequestBody + ",""login-pass"":""" & loginpass & """"
sRequestBody = sRequestBody + "}"
    
httpReq.send sRequestBody
```

#レスポンス
Excel VBAではレスポンスのJSONをそのまま解釈できなため、VBA-JSONを利用した。

https://github.com/VBA-tools/VBA-JSON/releases/tag/v2.3.1


#ソース
https://github.com/tosisasa/ondotori
【イラスト】 Javascriptのundefinedとnullの違い

この記事では、undefinedとnullの違いをコップに入った水に例えてお話します。

## コップの中身が入っている状態

![名称未設定のアートワーク 4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166484/93bf5de0-23dc-5812-191e-9864cb864aaf.png)

あるところにコップがあり、液体が100入っていたとします。
このコップを変数`cup`として表したとします。
これをコードで書くと、

```javascript

let cup = 100

<- 100
```

となります。

そして、もし液体の量が0のときは、

![名称未設定のアートワーク 5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166484/0bdbddc4-fcfe-358d-4ee9-c84710c981a1.png)

```javascript

let cup = 0

<- 0
```

`cup`には、0という数量を示す数字が入っています。

ここまでは簡単ですね。

## 【null】 コップの中身が空の状態

では本題に入りましょう。

nullとは、中身が`空`であることを示す、言わばラベルです。

![名称未設定のアートワーク 7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166484/e8187d27-ef4f-541a-7b63-6e87ba568422.png)

仮に先程のコップを飲み干して中身が空になったとしましょう。
このコップは`空`なんだ、もう何も入ってないんだ、ということを明確に示したいとき、nullを使います。
nullを使うと以下の様に書くことができます。

```javascript

let cup = null

// 結果
<- null
```

nullが代入されることで、`cup`の中身が`空`であることがハッキリしました。

nullは、他にも検索を行う関数で結果が見つからなかったこと示す返り値として使用されることもあります。

## 【undefined】 コップの中身が何だかわからない状態

![名称未設定のアートワーク 6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166484/b7b06edf-d9c1-44a6-519a-e0e9c3edec9d.png)

それに対してundefinedは、ある値がまだ定義されていない状態を示します。
定義されていない状態をあえて言い換えると、そもそも無いという状態ということです。

そもそも無いとは、具体的にはどんな状態でしょうか？
実際によくみられるパターンは、以下の３種類です。

- 初期化されていない
- 定義されていないプロパティやメソッド
- 戻り値の無い関数の結果

順番に説明します。

### 初期化されていない

初期化されていないことをコードで表すと以下の様になります。

```javascript

let cup

cup

// 結果
<- undefined 

```

この`cup`という変数は宣言はされていますが、残念ながら中身となる値が入っていません。
この状態で`cup`を参照するとundefinedが返ってきます。

### 定義されていないプロパティやメソッド

また下記の様に変数`cup`に用意していないプロパティやメソッドを呼び出した場合も、undefinedが返されます。
そもそも、そういったプロパティやメソッドが用意されていない無いためです。

```javascript

cup.size      // サイズは？

// 結果
<- undefined 

cup.price()  // 値段は？

// 結果
<- undefined

```

### 戻り値の無い関数の結果

最後に戻り値の無い関数の`結果`も、undefinedとなります。
例えば下記のコードの様に、関数に`return`が無い場合、実行結果はundefinedとして返ってきます。

```javascript

const func = function() {
  console.log('hello world.')
}

func()

// 結果
hello world
<- undefined

```

## おわりに

いかがだったでしょうか？
nullとundefinedの違い、理解して頂けたでしょうか？

最後まで読んでくれてありがとうございました。
Django: onlyとdefer

最近学習したアウトプットとしてこの記事を書きました。

例えばこんなmodelがあるとします。

```py:models.py
class Hoge(models.Model):

    title = models.CharField('タイトル', max_length=40)
    description = models.CharField('説明', max_length=100)
    created = models.DateTimeField('作成日時', auto_now_add=True)
    updated = models.DateTimeField('更新日時', auto_now=True)

```

`all()`や`filter()`を使ってデータを取得すると思うのですが
基本的に全てのフィールドが取得されますよね？
`only()`を使うことで指定したフィールドのみの取得
`defer()`を使うことで指定したフィールド以外の取得が出来ます。

```py
Hoge.objects.only('title', 'description')
```
基本的にはこれで`title`、`description`のみ取得出来ます
かと思いきやそうではなく他のデータもテンプレートで指定すると取得出来ます。

ただしその場合SQLが乱発されて遅くなるので注意が必要です。

```py
Hoge.objects.defer('created', 'updated')
```
これも基本的には`created`、`updated`以外の取得が出来る
テンプレートで`created`や`updated`指定すると取得出来ます。
その場合もやはりSQLが乱発されて遅くなるので注意が必要です。

膨大なデータがあるときに使用を検討してもいいかもしれませんが誤った使い方をすると却って遅くなることがあるので注意して使うといいかもしれませんね。

もっと詳しい方がご覧になったらご指摘とかいただけたら嬉しいです！

参考URL: [QuerySet API reference | Django](https://docs.djangoproject.com/ja/3.2/ref/models/querysets/)
[Ruby] 数値の四捨五入・切り捨て・切り上げ

## 環境
Ruby 2.6.3

## はじめに
本記事はRubyの四捨五入、切り捨て、切り上げについて解説したものです
Rubyでは標準で数値を扱う、色々なメソッドが用意されているので、それを利用して実行していきます。

## 本題

####1. 四捨五入

四捨五入する場合は、`Float`クラスの`round`メソッドを使用します。

```
1.4.round #=> 1
1.5.round #=> 2
-1.4.round #=> -1
-1.5.round #=> -2
```

`round`に引数を指定すると、指定した数字の桁数に対して四捨五入を実行します。
また、整数部分を四捨五入したい場合は、引数に負数を指定します。

```
1.23456.round(2) #=> 1.23
1.23456.round(3) #=> 1.235
123456.round(-2) #=> 123500
123456.round(-3) #=> 123000
123456.round(-4) #=> 120000
```

#### 2. 切り捨て
切り捨てを行う場合は`floor`メソッドを使用します。

```
1.4.floor #=> 1
1.5.floor #=> 1
-1.4.floor #=> -2
-1.5.floor #=> -2
```

小数点N桁の切り捨てを行いたい場合は引数に桁数を指定することで実行することができます。
`floor`の場合も、整数部分を四捨五入したい場合は、引数に負数を指定します

```
1.23456.floor(2) #=> 1.23
1.23456.floor(3) #=> 1.234
123456.floor(-2) #=> 123400
123456.floor(-3) #=> 123000
```

#### 3. 切り上げ
切り上げを行う場合は`ceil`メソッドを使用します。

```
1.4.ceil  #=> 2
1.5.ceil  #=> 2
-1.4.ceil #=> -1
-1.5.ceil #=> -1
```

小数点N桁の切り上げを行いたい場合は先ほど同様数に桁数を指定することで実行することができます。
こちらも整数部分を四捨五入したい場合は、引数に負数を指定します

```
1.23456.ceil(2) #=> 1.24
1.23456.ceil(3) #=> 1.235
123456.ceil(-2) #=> 123500
123456.ceil(-3) #=> 124000
```

## 参考
[Float#floor](https://docs.ruby-lang.org/ja/latest/method/Float/i/floor.html)
[Float#ceil](https://docs.ruby-lang.org/ja/latest/class/Float.html#I_CEIL)
[Float#round](https://docs.ruby-lang.org/ja/latest/method/Float/i/round.html)

https://uxmilk.jp/43388
adverb と conjunction ― J 言語入門

# modifier の性質

verb は noun を引数にとり、noun の結果を返します。noun は、数値や文字列などの いわゆる「データ」のことです。つまり、verb は「データの処理」を表しています。

一方、modifier (adverb と conjunction) は異なる性質をもっています。

|被演算子|結果|
|---|---|
|noun (`m` / `n`) または verb (`u` / `v`)|noun, verb, adverb, conjunction いずれも可 [^1]|

modifier は、noun や verb をパラメータとする「テンプレート」のようなものです。

# adverb

adverb は、被演算子が 1 つの modifier です。被演算子は左側に置きます。

```j
   NB. (,) ~
   ,~
,~
```

3 行目は REPL の出力で、結果の verb が表示されています [^2]。

# conjunction

conjunction は、被演算子が 2 つの modifier です。被演算子は左側と右側の両方に置きます。

```j
   NB. (0) & (,)
   0&,
0&,
```

## 部分適用

conjunction の どちらか一方の被演算子を省略して、adverb を作ることができます。その adverb に被演算子を与えると、省略された部分が埋まります。

```j
   -@
-@
   +(-@) 
-@+
   +(&1)
+&1
```

# 値の区分

ここまで、modifier として ひとまとめにして扱ってきましたが、adverb と conjunction は独立した区分です。J で扱う値には以下の 4 つの区分があります。

- noun
- verb
- adverb
- conjunction

verb は更に、monad と dyad を含んでいて、monad / dyad 両方の使い方ができる verb (`+` など) もあります。一方、adverb と conjunction は別物なので、*両方を兼ねることはできません*。

modifier は値の区分ではなく、adverb と conjunction の総称です。

# 優先順位

verb と verb の間には優先順位の差はなく、常に右結合 (右から左の順) でしたね。

```j
   NB. - (2 * (3 - 1))
   -2 * 3 - 1
_4
```

modifier どうしの間にも、優先順位の差は**ありません**が、modifier は常に **verb よりも優先**されます。また、実行の順序も、modifier が先です。

```j
   ,&2 -3   NB. (, & 2) (- 3)
_3 2
   ] -3     NB.    ]    (- 3)
_3
   - 1&, 4  NB. - ((1 & ,) 4)
_1 _4
   - ] 4    NB. - (   ]    4)
_4
```

`]` を使った例と比較すると、`&` の結果が 1 つの verb として解釈されているのが分かりますね。verb を優先させるには、括弧を使います。

```j
   ,&(2 - 3)
,&_1
   (-1)&,
_1&,
```

# 結合性

verb とは異なり、modifier は左結合 (左から右) です。言葉では分かりにくいと思うので、実際に例を見てみましょう。

```j
   NB. ((+ /) @ i.) 10
   +/@i. 10
45
```

`+/` を以前に紹介した際に少し触れましたが、`/` も adverb です。この例では、0 から 9 までの整数の総和を求めています。左側にある `/` が、右側の `@` よりも先に解釈されています [^3]。

複雑な式でも、同じです。どんな modifier でも左から右の順序に統一されているので、慣れれば難しくありません。

```j
   NB. ((1 & +) @ i.) 10
   1&+@i. 10
1 2 3 4 5 6 7 8 9 10
   NB. 2 ((% @ -) ~) 3
   2 %@-~ 3
1
```

順序を変えるには、括弧を使います。

```j
   NB. (- @ (+ /)) 2 3 5
   -@(+/) 2 3 5
_10
```

優先順位と結合性について、簡単にまとめておきます [^4]。

- modifier は verb よりも優先して**左から右**の順
- verb は**右から左**の順

---

\[ 前 : [高階関数](https://qiita.com/unsigned-wrong-wrong-int/items/77cb04ee82b856c52622) \] \[ [目次](https://qiita.com/unsigned-wrong-wrong-int/items/e15a87999cedfc6b9ced) \] \[ 次 : [代入](https://qiita.com/unsigned-wrong-wrong-int/items/e175f45607e407bb0973) \]

[^1]: ただし、modifier の多くは verb を返します。
[^2]: REPL は、verb や modifier を そのままの形で表示します。慣れないうちは読みにくいかもしれません。
[^3]: 逆に `+ (/ @ i.)` と右から解釈した場合エラーになります (`/` は noun でも verb でもないため)。
[^4]: 単純なルールですが、全ての verb / modifier に例外なく当てはまります。
Amazon ElastiCache (Redis) のservice updateをやってみた / elasticache-20210615-002 の適用

# やったこと
掲題の通りではあるのですが、1年以上ElastiCacheを運用してきて初めて遭遇したのと、実際どういう操作になったり、どういう挙動になるのかが分からなかったので、次来た時のメモとして残します。また、作業を予定しているが全貌を掴めていない方がいらっしゃった場合の一助になれば幸いです。利用クラスターエンジンはRedisです。

# 注意点
今回あくまでRedisの話でしてMemcachedの場合だったりすると全く異なる可能性がありますし、Redisのバージョンや設定によっては挙動が変わり得ると考えています。私が見ている範囲で安全に配慮して作業した記録、というだけですので、実際の更新にリスクがある場合は都度サポートに問い合わせるなどの対応を強く推奨致します。


# 結論
・Redisは数秒繋がらなくなる
・Redisのデータは消失しない
・リハーサルはしましょう


# ご案内が来ます
メールで案内が届きます。

今回の更新がどういったものか、などは [このあたり](https://aws.amazon.com/elasticache/elasticache-maintenance/?nc1=h_ls) のドキュメントを併せて確認するとよさそうです。

# どういう手順で更新するのか調べる

## 様子
コンソール画面を開くと親切な案内が来ています。
おおーなるほど、と思う一方で、これを見て私は**「押したら確認画面なしで全クラスタアップデート走らんよな？？？」**と心配してしまう人類なので、いろいろ見てゆきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68734/cdc11ff9-0d2d-7b5b-5b53-9421c369c9c1.png)

## 解決策
クラスターをチェックし、アクションを見ると「サービスの更新を適用する」という項目があるので、こちらから個別対応ができそうです。よかった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68734/cb6c541e-1407-90e2-83dd-be83f555f14c.png)



# 影響範囲を調べる

先ほどと同じく、[このあたり](https://aws.amazon.com/jp/elasticache/elasticache-maintenance/?nc1=h_ls) のドキュメントを見ます。
先ほどの更新案内に関しては、判断基準となる案内メールが英語で届くので英語版を見たほうがよく、影響範囲などは日本語版を、ただ念のため交互に見たほうが良いと感じました。

> Redis クラスターは引き続きトラフィックを処理します。数秒のダウンタイムが予想されます

引き続きトラフィックを処理する、というのが文脈上少しだけ解釈に確信が持てないと感じましたが単に「データは消えないが、一時的に繋がらなくなって、その後すぐ復旧する」と受け取って先に進みます。


# 開発環境でリハーサルをする

操作方法と影響範囲が分かったものの、実際やってみないと流石に怖すぎます。
というわけで開発環境で実施ました。

まず、Redisのデータが消えないことを確認しました。これは一安心です。
次に、一時的に繋がらなくなる時間帯が出ることを確認できました。これも想定通りではあるのですが、イメージしていたエラーと少し違いました。確認の観点として例えばコネクションをどのように扱っているかなどがあり、アプリケーションの設計次第では挙動チェックは必須かと思います。

また、上記で解釈した通り、適用完了後は普通に接続可能となっていました。これも安心ですね。

# どんな感じで適用されていくかもチェック

キャプチャを取り忘れましたが、実行前に「想定される作業時間」みたいな項目が表示されます。私が操作したものは「30分」でした。適用を開始すると「アクションステータスの更新」が「in-progress」になります。ノードに対して1つずつ適用がされてゆき、実際には20分弱で完了しました。
もちろん20分弱落ち続けるわけではなく、この20分弱の流れの中で、数秒繋がらない時間があるという形です。目視ベースだったので具体的にどのプロセス（前半、中盤、後半とか）で何回、というのは把握できておりません。

# 雑感
上記のような流れでサービス更新(service update)を初めてやってみました。

ちなみに冒頭で書いた「今すぐ適用」ボタンを押すと、ポップアップウインドウが現れ、そこからも更新が可能なようです。その導線から一気にやる、というより残りクラスター数の確認、みたいな感じに有用かもしれません。
Pythonで株の個別銘柄ベータ値(β値)を計算する

#0.はじめに
今週は記事にするネタが思い浮かばなかったので、株関連の記事。
今回はトヨタ自動車とTOPIXのβ値をpythonで算出する方法を2種類記載します。


#1.ベータ値って・・何？

β値とは、株の個別銘柄が指数にどれだけ感応度があるかっていうのを調べる指標で、**株式市場(指数)が1％変化したときに、任意の株式のリターンが何％変化するかを表す係数**。
それはすなわち**「リスク」を測る指標**と言える。

つまり、βが1を超える株式はより指数に比べて動く銘柄となるのでリスクが高くなる。

#2.準備

今回はトヨタ自動車(7203.T)とTOPIXの比較を行い、期間は2020/1/1～2020/12/31までとする。
そして今回の株価取得は簡単の為pandas_datareader + [stooq](https://stooq.pl/)経由で行う

※**本記事はβ値の算出の解説**なので、株価取得部分は解説しない
※**stooqは指数はあってるが、下記トヨタ含め株価データが微妙に間違っていることがあるので注意**

```Python:
import numpy as np
import pandas as pd
import datetime
from pandas_datareader import data as wb
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn import linear_model

#Topixとトヨタをstooqからデータフレームとして取得
start = datetime.date(2020,1,1)
end = datetime.date(2020,12,31)
tickers = ['^TPX','7203.JP'] #TOPIXとトヨタ ※stooq経由でのトヨタの株価は微妙におかしい
data = pd.DataFrame()
for t in tickers:
    #終値だけ取得
    data[t] = wb.DataReader(t, data_source='stooq', start=start, end=end)['Close']

data = data.iloc[::-1] #順番並び替え

data.head(2) #2行表示
```


|Date  |^TPX  |7203.JP  |
|---|---|---|
|2020-01-06|1697.49  |7435.85  |
|2020-01-07|1725.05  |7583.29  |


#3.対数利益率の計算

前日比どれくらい上昇しているか？を対数利益率で計算する

```Python:
log_returns = np.log(data/data.shift(1)) #shift(1)で1日データシフトさせている
log_returns = log_returns.dropna() #1/6は前日がないのでNaN。よって取り除く
log_returns.head(2) #2行表示
```
|Date  |^TPX  |7203.JP  |
|---|---|---|
|2020-01-07|0.016105  |0.019634  |
|2020-01-08|-0.013805  |-0.012784 |


#4.散布図をplotしてベータ値を算出

```Python:
#共分散plot
X = log_returns.iloc[:,0] #topix
Y = log_returns.iloc[:,1] #toyota

from sklearn import linear_model
clf = linear_model.LinearRegression() #線形モデル
X2 = [[x] for x in X]
clf.fit(X2, Y) # 予測モデルを作成

print("ベータ値(回帰係数,傾き)= ", clf.coef_)
print("切片= ", clf.intercept_)
print("決定係数= ", clf.score(X2, Y))

# 散布図
plt.scatter(X2, Y)

# 回帰直線
plt.title('Linear regression')
plt.plot(X2, clf.predict(X2))
plt.xlabel(log_returns.columns[0])
plt.ylabel(log_returns.columns[1])
plt.grid()
plt.show()
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373060/e9e69826-b16a-23f4-229e-f33347890f0d.png" width=50%>

これでベータ値の算出が出来た。ベータ値とは回帰直線の傾きそのものであり、1.09となっているので市場が1%上がるとトヨタは1.09%上昇するということになる

#5.線形回帰を使わない方法

ベータ値は共分散を求めることで算出でき、こちらの方が記述が短く済む。
参考：[共分散とは](https://integraldx.info/covariance-5761)

```Python:
cov_matrix = log_returns.cov() #covは共分散を計算
cov_matrix
```

|Date  |^TPX  |7203.JP  |
|---|---|---|
|^TPX	|0.000204  |0.000223  |
|7203.JP|0.000223|0.000342|

共分散(マーケット・個別)：右上、左下
分散(マーケット)：左上

```Python:
"""ベータ値 ＝ 共分散(マーケット・個別)／分散(マーケット)"""
toyota_beta = cov_matrix.iloc[0,1] / cov_matrix.iloc[0,0]
print(toyota_beta)
```

```:実行結果
1.0942257680186884 ※線形回帰の傾きと同じ
```

#6.おわりに

今回はベータ値をpythonで算出した。
高ベータ値の銘柄は市場が上昇基調にあるときはより大きく上昇する一方、逆に市場が下落基調に転じるというリスクもある。よってこれを活用して例えば上げ相場は高β、下げ相場は低βにするなどして銘柄選択に役立ててみては如何だろうか？
julia でスクレイピング


以下のような感じでスクレイピングできます．
存在しないURLを使っているので，適宜URLを変更しましょう．

```julia
using HTTP, Gumbo, Cascadia

url = "https://hoge.example"

req = HTTP.request("GET", url)
doc = parsehtml(String(req.body))

hogelist = eachmatch(Selector(".Hoge"), doc.root)
```

HTTP.jl で web ページの情報を取得して， Gumbo.jl　の `parsehtml()` で HTML をパースします．
Cascadia.jl を使えば，指定したセレクタにマッチする `HTMLNode` を取得できます．例えば以下のような感じです．`HTMLNode` は `text()` を使って文字列に変換できます．

```julia
julia> doc = parsehtml("<p id=\"hoge\"> Hello, world! </p>")
HTML Document:
<!DOCTYPE >
HTMLElement{:HTML}:<HTML>
  <head></head>
  <body>
    <p id="hoge">
      Hello, world!
    </p>
  </body>
</HTML>

julia> eachmatch(Selector("#hoge"), doc.root)
1-element Vector{HTMLNode}:
 HTMLElement{:p}:<p id="hoge">
  Hello, world!
</p>



julia> eachmatch(Selector("#hoge"), doc.root)[1] |> text
"Hello, world!"
```
eclipse spring devtools ホットデプロイ試した

springのdevtoolsの自動再起動機能を試した。
気づいたのはdevtoolsのrestartの設定はデフォルト:trueだったこと。

# リロード速度

* クラスの変更は再起動に3秒ぐらい(クラスの数に影響しそう)
* Thymeleafの変更は再起動なしですぐ反映される

# dependenciesにdevtools設定

```gradle:build.gradle
dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	developmentOnly 'org.springframework.boot:spring-boot-devtools' // ここ追記した
}
```

# application.ymlにrestart設定

restart設定のデフォルトは **true**
あえてfalseにしないなら設定不要。

```yml:application.yml
spring:
  devtools:
    restart:
      enabled: true
```

# リロード確認

|確認対象|devtoolsなし|devtools利用|restartあえてfalse|
|---|---|---|---|
|Controllerメソッド処理変更|:no_entry_sign:|:ok:|:no_entry_sign:|
|Controller`@RequestMapping`のついたメソッドを追加|:no_entry_sign:|:ok:|:no_entry_sign:|
|Controllerクラス追加|:no_entry_sign:|:ok:|:no_entry_sign:|
|Thymeleaf内容編集|:no_entry_sign:|:ok:|:ok:|
|Thymeleafファイル追加|:no_entry_sign:|:ok:|:ok:|

# 参考

* [spring.pleiades.io - 8. 開発ツール](https://spring.pleiades.io/spring-boot/docs/current/reference/html/using.html#using.devtools)
* [SpringBootでホットデプロイを行う2つの方法](https://qiita.com/kohei_sasaki/items/93b32177df46b4c450f3)
* [Spring Boot devtoolsのAutomatic restartについて](https://qiita.com/rubytomato@github/items/6f5dc142f32d9e9c1e2a)
console.logの文字をグレーにする方法

##結論
[使える色](#使える色)で紹介しているものを__組み合わせる__ことでさまざまな色を表現できます。

グレーは以下の組み合わせです。

```
FgGray = "\x1b[1m\x1b[30m"
```

それぞれ`\x1b[1m`はBright、`\x1b[30m`はblackを表しています。

##使える色

```
Reset = "\x1b[0m"
Bright = "\x1b[1m"
Dim = "\x1b[2m"
Underscore = "\x1b[4m"
Blink = "\x1b[5m"
Reverse = "\x1b[7m"
Hidden = "\x1b[8m"

FgBlack = "\x1b[30m"
FgRed = "\x1b[31m"
FgGreen = "\x1b[32m"
FgYellow = "\x1b[33m"
FgBlue = "\x1b[34m"
FgMagenta = "\x1b[35m"
FgCyan = "\x1b[36m"
FgWhite = "\x1b[37m"

BgBlack = "\x1b[40m"
BgRed = "\x1b[41m"
BgGreen = "\x1b[42m"
BgYellow = "\x1b[43m"
BgBlue = "\x1b[44m"
BgMagenta = "\x1b[45m"
BgCyan = "\x1b[46m"
BgWhite = "\x1b[47m"
```

- ベースの色を明るくしたいのであれば`\x1b[1m`
- ベースの色を薄暗くしたいのであれば`\x1b[2m`

などが使えます。

ご自身で組み合わせてみて、作りたい色を見つけてみてください。

##補足
色を元に戻すときは`\x1b[0m`でリセットできます。

##参考

stack overflow: [How to change node.js's console font color?](https://stackoverflow.com/questions/9781218/how-to-change-node-jss-console-font-color)
魅惑のbqコマンド&shell

#魅惑のbqコマンド



###GCP環境をCLIで操る魅惑のコマンド
GCPをCLIで操る魅惑のshellやBQコマンドは、GUIでいわれる痒いところまで手が届かないという言葉が嘘のように届かせることが可能となります。


###使用できる詳細を記したhelpコード
```bq:BQコマンド
 $ bq --help
```
使用コきるコードはこちらを参照すれば取得可能。
GCSのCSVデータやJSONデータを他プロジェクトに移送させたりローカルにデータをダウンロードする方法ことも可能である。


###そもそもGCSにアクセスする方法とは
接頭辞に「gsutil」をつけてアクセスする

```bq:BQコマンド
$ gsutil help
```
##よく使う目的別のbqコマンドとshell
◼︎sqlファイルを実行する方法

```shell:shell
$ bq query --use_legacy_sql=false -- format json < ./同ディレクトリ内のSQLファイル.sql | jq -r
```
sqlファイルをjsonファイルとして出力させてjqコマンドで整形して出力させている内容。
なお途中で表示が切れている場合は「--use_legacy_sql=false」の前に「--n 2000」と入力させると2000行までは表示される。
表示範囲を拡張させてやる必要あり。

◼︎ディレクトリを削除したい

```shell:shell
$ rm -r -d ディレクトリ名
```
ディレクトリ内にファイルを作成した場合に全て削除してからディレクトリを削除しなくて良い方法が、こちらのコマンド

◼︎特定ファイル直下まで表示させる方法

```shell:shell
$ ls -ltR ./指定ファイル
```
指定ファイル直下のファイル内容などを一括表示させることが可能


◼︎JSONファイルをCSV形式で表示させたい

```shell:shell
$ cat ./jsonファイル　| jq -r ',[] | [.column_name, .description] | @csv'
```
ディレクトリを指定したJSONファイルwp表示する項目を設定してcsv形式で表示。jqコマンドで読みやすいように整形も実施。


◼︎テーブルをJSONファイルの内容をもとにアップデートする方法

```shell:shell
$ bq update データセット.テーブル名 ./変更したい内容を記載したJSONファイル
```
JSONファイルに変更したい内容を記載した場合、JSONファイルをもとにテーブルに直接変更することが可能となる。
意外と難しい「ありがとう」とサーバントリーダーシップ

## ありがとう or よくやった or よかったね

まだわたしが駆け出しのPMの頃、いやむしろガンガンにプログラムを書きたかったのに無理やりPMもやらされていた頃。小さな会社で他にやる人もおらず仕方なくやっていたのだけれども、あまり感謝を口にされたことはありませんでした。お金もあんまりもらえたことはありませんでした。

その当時、大炎上でどうしょうもないプロジェクトをまとめました。
その時に言われたのは **「ありがとう」** でも **「よくやった」** でもなく **「よかったね」** でした。
薄っすらと不満を持ちつつも成果を噛み締めていたのですが、振り返ってみると、これはサーバントリーダーシップみたいなことを体現されてたんだなぁと、折に触れて考えさせられてることを記事にしました。


## 誰のために働くの？

当時のわたしは、炎上しているプロジェクトをまとめるのは「会社のため」だと思っていたので、薄っすらと不満を持ったわけですが、そうではないという示唆に富んだセリフが **「よかったね」** だったと思います。

そもそも日頃から **『会社のため』** と思って働いている人はそんなにいないと思います。
**『お時給の分はしっかり働きます』** という品格のある想いの方が多いかは分かりませんが、お時給の分働いていない方は正社員として定年まで勤め上げるのは難しい世の中なのかなとは想います。

大炎上したプロジェクトが納品までこぎつけなかった場合、プロジェクトチームのメンバーが苦労して積み上げた物が無に帰します。数ヶ月～数年の間、わたしだけではなくプロジェクトメンバー全員がお時給の分働かなかったことになります。

「会社のため」というと社畜っぽく聞こえますが「同じプロジェクトのメンバーのため」と言うと随分印象が違います。結果は同じなのですが、不思議ですね。
さらには「大炎上しているプロジェクトをまとめる能力」を身につける事はPMとしては必要な能力であり、それを身につけるために働いたと考えると「自分のため」に働いたとも言えます。
ですが、自分のキャリアパスとして興味ないことを「自分のため」と自発的に自覚して努力するのは相当難しいものです。

これを **「おまえのためだからやれ」** などと直接的に言われても **「は？仰る意味が分かりません」** という話になって大乱闘なブラザーになります。


## 任せるということ

駆け出しPMのわたしが大炎上しているプロジェクトを確実にまとめられる保証があったかというと、そんなものはどこにもなかったわけですが、わたしに任せるというのは勇気のいる決断だったのかなと、今にしてみると思います。

プチ炎上させる度に、報連相や見積もりについて指導を頂くことはありましたが、任されている仕事に対して手出しをされたことはなかったと思います。

プロジェクト中に盛大にやらかした事があり、菓子折り持ってお客先に一緒に謝りに行って頂きましたが、この時も無駄に叱責される事もありませんでした。
叱責された方が楽だよなぁと普通に思いましたが、大変反省しました。


## まとめ

感謝の気持ちは伝えるべきだし「ありがとう」が溢れるプロジェクトは良いプロジェクトだと思います。

ただ、きちんと仕事を任せて、任せた相手の成果と成長を評価する「よかったね」。
このケースでは「よくやった」や「ありがとう」は、相手の成果や成長を小さなモノになってしまうのではないかと思いました。

ということで、ありがとうございました。
【Rails】マイグレーションファイルを削除する手順と方法

#対象者
マイグレーションファイルの確認・削除・モデルとの紐付けの方法

#手順目次
1.データベースとモデルが紐付いているのか確認しよう！

2.down or upを確認

3.rails db:migrate:statusで再確認


#実際の手順
###1.データベースとモデルが紐付いているのか確認 →　**rails db:migrate:status**

```````
$ rails db:migrate:status
```````
実行するとこうなる↓

``````

database: /home/ec2-user/environment/bookers3/db/development.sqlite3

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20210624050145  Devise create users
   up     20210626043822  Create books
  down    20210626044439  Add profileimagedid to users
  down    20210626044515  Add introduction to users
`````````````

###2.down or upを確認
①down　→　削除してOK
②Up　　→　コマンドを打ち込んでdownにする（紐付けを解く）
**rails db:migrate:down VERSION=(作成日時)**

````
$ rails db:migrate:down VERSION=20210626044439
`````

````
== 20210626044439 AddProfileimagedidToUsers: reverting ========================
-- remove_column(:users, :users, :string)
   -> 0.0100s
== 20210626044439 AddProfileimagedidToUsers: reverted (0.0148s) ===============
``````
⚠作成日時は下記画像の赤線部分
![スクリーンショット 2021-06-26 15.17.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1681213/56f66c51-5d22-4b12-88ea-490c97e10574.png)


###3.再度紐付いているかどうか確認　→　**rails db:migrate:status**
```````
$ rails db:migrate:status

database: /home/ec2-user/environment/bookers3/db/development.sqlite3

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20210624050145  Devise create users
   up     20210626043822  Create books
   up     20210626052506  Add introduction to users
   up     20210626052540  Add profileimagedid to users
```````

全部アップになっていることを確認
Remove old files following the designated directory and number

## source

```sh
#!/bin/sh

NL=`ls -ldt $1/* | wc -l`
TLTR=`expr $NL - $2`
echo $NL,$TLTR
if test $TLTR -gt 0 ; then
  echo $NL,$TLTR
  for x in `ls -ldt $1/* | tail -n $TLTR | awk '{print $9}'`
  do
    rm -rf $x
  done
fi

```

* $1 means the designated directory
* $2 means the number of files you want to leave
ウィトゲンシュタインのパラドックス由来(?)の多項式

最初にお断りしておきますと，この記事はなんの実用性も新規性もありません:sweat_smile:．
なにかを検索していて，たまたま，[数学って面白い！？](http://blog.livedoor.jp/enjoy_math/archives/50637026.html "ウィトゲンシュタインのパラドクス")というブログにいきあたり，その中でウィトゲンシュタインのパラドックスを数列で表現してみたらどうなるか，という記事があったので，それにちなんで久しぶりにMaximaの復習でも，と思ってやってみた結果です．確認してはいないですが，ウィトゲンシュタイン自身が提出した数列というわけではなく，上記ブログ内の話題の中で書かれていたものだと思います．

お題を簡単にいうと，「2 4 6 8 10 12 14 16 18 20」という数列の次の数は? というもので，多くの場合，次は「22」だけど，「24」とも言えるよ，という話です．「素直」には，

```math
a_n = 2n
```
と考えて「22」だけど，n=10までは上記で，n>=11では，

```math
a_n =  2n + 2
```
だというルールを主張すれば「24」でもいいじゃないか，という主旨のようです．まぁ，下敷きの哲学的な話はこの記事の主眼ではないので，その辺りは参照したブログの方をご覧いただくとして，同ブログのコメント欄でのやりとりで，n点を通るn-1次の多項式を作れば場合分けしなくてもできますよね，という議論があって，それはまぁ当然作れるわけですが，実際やってみようか，とMaximaを立ち上げてみました．
やり方としては素朴に，

```math
f(x) = \sum_{k=1}^n \prod_{i\neq k}^n a_k (x-i)
```
を作り，与えられたn点の数(上の例では「2 4 6 8 10 12 14 16 18 20 24」の11点)で一致するように連立方程式を解くだけです．
Maximaのプログラムは次の通り．

```c
kill(all);
declare(x,scalar);

v: [2,4,6,8,10,12,14,16,18,20,24];
n: length(v);

e: genmatrix(lambda([i,j], 1), n,1);
t: genmatrix(lambda([i,j], log((x-j))*signum(i-j)^2), n, n);

array(a,n);
k: genmatrix(lambda([i,j],a[i]),n,1);

define(f(x), transpose(k).exp(t.e));

globalsolve:true;
linsolve(makelist(f(j)=v[j], j, 1, n), makelist(a[j], j, 1, n));
globalsolve:false;
```

で，これを使って解かせると，以下のようになります(ratsimp(f(x))，で表示．tex(ratsimp(f(x)))でTeXソース表示)．

```math
{{x^{10}-55\,x^9+1320\,x^8-18150\,x^7+157773\,x^6-902055\,x^5+
 3416930\,x^4-8409500\,x^3+1275
3576\,x^2-6999840\,x+3628800}\over{
 1814400}}
```

実際にやってみると，

```c
(%i14)	makelist(f(j),j,1,15);
(%o14)	[2,4,6,8,10,12,14,16,18,20,24,46,158,600,2032]
```

のように，確かに要求は満たしています．予想通りというか，合わせたところから先は…ですが:sunglasses:．なお，n点の整数点で整数値を取るn-1次式なので，よく知られているようにすべての整数点で整数値をとりますね．

ちなみに，[同じブログの別の記事](http://blog.livedoor.jp/enjoy_math/archives/50634268.html "こんな数列だって存在します")で，「2 4 6 30 32 34 36 40 42 44 46 50 52 54 56 60 62 64 66」の次は? という問題も紹介されていて，こちらは「2000」のようです(「1000」じゃないの?，というコメントもあり)．理由は引用先を…．

で，これの方は，「2000じゃないよ」というために，66までで合わせると以下のようになり，

```math
-{{8500\,x^{18}-1532052\,x^{17}+128031573\,x^{16}-6584685480\,x^{15
 }+233284747740\,x^{14}-6038346948984\,x^{13}+118175485443886\,x^{12}
 -1785197864455200\,x^{11}+21064352131885920\,x^{10}-
 195192274659715476\,x^9+1420490898303552309\,x^8-8077028291381027160
 \,x^7+35501847655780908040\,x^6-118521701610680081088\,x^5+
 292497294681767297232\,x^4-511716089590838444160\,x^3+
 592777099994009644800\,x^2-401255294811127142400\,x+
 117547581237166080000}\over{8002967132
16000}}
```
これで計算すると

```c
(%i3)	makelist(f(j),j,1,24);
(%o3)	[2,4,6,30,32,34,36,40,42,44,46,50,52,54,56,60,62,64,66,-134062,-2416492,-23109162,-155686312,-828247892]
```
となって，どうやら次は「-134062」のようです:sunglasses:

しょうもない記事ですみません…
（レポート） Scrum Fest Osaka 2021 Day 2 「チームでものづくりするときに、心のなかで起こっていることを上手く使うには？」


# Scrum Fest Osaka 2021 Day 2 「チームでものづくりするときに、心のなかで起こっていることを上手く使うには？」

2021/06/26に開催されたScrum Fest Osaka 2021での発表です。
https://confengine.com/conferences/scrum-fest-osaka-2021/proposal/15331

# チーム参加してきました

[aslead Agile](https://aslead.nri.co.jp/solution/aslead_agile.html) のチーム「[オキザリス](https://speakerdeck.com/viva_tweet_x/huesudeyong-qi-wode-taxin-gui-timugashi-yan-wozao-rifan-sitejin-nizhi-rumadefalsewu-yu?slide=3)」にて参加してきました。
チーム7人で参加して、その場で実況しつつ、記事も作っています。

# 共調、協働
- 楽しく、元気になる（生物的な仕組み）
- 様々なリソースの共有、同期と非同期で補い合える（特に表象を使って）

# 活動を支える認知過程
- 人の生活を単位として、様々な活動から構成されたものとしてとらえる。
- 人は活動することで、
自分もその構成要素である世界に働きかけ、望ましい世界の状態を作り出す。
- 人の世界を体の中に存在する内部世界（環境）とそれを取り巻く外部世界（環境）に分けてとらえることができる。

# 多様な認知過程
次の引き算を実現する認知過程はどんな表象がどのように表象され実行される活動だろうか
 13
- 9
ーーー

10-9=1+3=4
13-9=4
3-9=-5+9=4

# アナログ表象と記号（言語）表象
*構成性*
現実世界にないものをモジュールへの分解と再合成できる

*痕跡性*
かるい（必要な時に、実際の構造を再現する）
特に音声記号と文字記号


# 感想
-あたりまえのことでも、人によって行動や考えの過程は異なり、そのことを認知して自分の考えや行動を人に伝えるべきか考え直してみようと思いました。
シングルタスク学習モデルからマルチタスク学習モデルへの移行

#マルチタスク学習とは
マルチタスク学習モデルとは、１つのネットワークで複数のタスクを解くモデルです。
今回は、1入力1出力のシングルタスク学習モデルから1入力2出力のマルチタスク学習モデルへ変更を行ったため、備忘録としてこの記事を残します。

#実行環境
+ Python 3.6.10
+ Keras 2.2.4
+ tensorflow 1.14.0

#変更前のモデル構造
![model_before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693301/f2b57d3b-c59a-0284-58c6-ec9913899935.png)


#変更後のモデル構造
![model_after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693301/7128649a-77da-dd03-0e61-aca3b5b7342e.png)

#コードの変更点
###Sequential vs Functional API

シングルタスク学習モデルでは基本的にSequentialを使うことが多いが、マルチタスク学習モデルではFunctional APIを使う。そのため、コードはかなり変更する必要がある。
詳しくは以下の公式ドキュメントチェック。

https://keras.io/ja/getting-started/functional-api-guide/

###Sequentialを使ったモデル(変更前)
```python
model = Sequential()
model.add(Bidirectional(LSTM(n_hidden, return_sequences=False, batch_input_shape=(None,799,1))))
model.add(BatchNormalization())
model.add(Dense(3))
model.add(Activation("linear"))
model.compile(loss="mean_absolute_error", optimizer="Adam", metrics=["accuracy"])
history = model.fit(X_train, y_train, batch_size=256, epochs= 120, validation_split=0.05)
```


###Functional APIを使ったモデル(変更後)
```python
input1 = Input(shape = (799, 1))
layer1 = Bidirectional(LSTM(n_hidden))(input1)
layer2 = BatchNormalization()(layer1)
layer3_1 = Dense(2)(layer2)
out1= Activation("linear", name = 'out1')(layer3_1)

layer3_2 =  Dense(1)(layer2)
out2= Activation("linear", name = 'out2')(layer3_2)

model = Model(inputs=input1, outputs=[out1, out2]) 
model.compile(optimizer='Adam',
              loss={'out1': 'mean_absolute_error', 'out2': 'mean_absolute_error'},
              loss_weights={'out1': 0.7, 'out2':0.2},
              metrics=['accuracy'])

history = model.fit(X_train, [y_train1, y_train2], batch_size=256, epochs= 5, validation_split=0.05)
```

###変更するにあたって
+ Functional APIを使うに当たって、新たにimportするものがいくつかあった(Input, Modelなど）
+ モデルの出力を２つにするにあたり、学習データの出力も2つ`(y_train→[y_train1, y_train2])`にする。
+ outputの名前をつけないと(コードのActivationのところ）、lossの定義のところでエラーが出るので注意。
+ ロスのウェイトについては、チューニングが必要。今後また記事を出すかも。
+ １行目の`Input(shape = (799,1))` をinput1に代入後、shapeを確認すると`(?, 799, 1)`となる（次元が一つ増える)。これでかなりの時間格闘したので、今後これについても記事にするかも。