OmniAICreator/Qiita-1.07M huggingface dataset:
EM法まとめ（備忘録）

# まず
ただの備忘録に近く全然まとまってません（ごめんなさい）。これは大事と思ったポイントの羅列です。
機械学習については完全に生まれたてのひよこで、確率統計も高校レベル＋$\alpha$で止まってる人なので、理解とか用語の誤用とかどしどしご指摘くだされば助かります。
私と同様にクラスタリングからおさえちゃおーとしてk-means法とかEM法のアルゴリズムを見て面くらって「なんでこれで収束するんじゃい」と思った人向け

# 目標（未達成）
階層および非階層クラスタリングの詰まりどころをおさえてクラスターマスターになれるようにする。
※まだ階層クラスタリングについては何も書けていない

## EM法のポイントをものすごく乱暴にキャッチフレーズすると
変分法と下限を活用した非常に解析的なテクニック！！

## なんでk-meansじゃ駄目なの、EM法の何がいいの
やっぱり区間推定ってのは大事で、平均しか見ないで点推定しちゃうk-means法より、この点はだいたい何％の確率でこのクラスターにいるでしょうって予言してくれるほうが安心できる。
例：平均年収だけ見てもよくわからんが、年収の分布にすると得られる情報量は段違いに大きいのと一緒

## EM法のテクニックをものすごく乱暴にキャッチフレーズすると
混合ガウス分布の場合が典型例（$\rm{log}\sum{}$の形になるため）だが、一般的には解析的に解くのが難しい対数尤度そのものではなく解析的な下限を求め、下限のほうを底上げしていく方法

## EとMはそれぞれ何してるのか、何を繰り返しているのか
E法とM法は、それぞれ2変数関数の極値を求める際に$x$方向の極値を出してから$y$方向の極値を出すっていう2段階の探索に相当し、ただしE法が変数の微分ではなく汎関数の変分というところが味噌

## 謎の新しい確率qをわざわざサンドイッチすると何かいいことがあるのか
新しい確率測度$q$を間にはさむことで対数尤度を期待値化することによりイェンセンの不等式が使える状況に持ち込み、解析の難しい$\rm{log}\sum$が解析しやすい$\sum{}\rm{log}$の形になる

## E法は要するにこういうことをしている
対数尤度と変分下限の差は事後分布の確率$p(Z|X)$と新しい確率$q(Z)$のカルバックライブラー情報量$KL(q||p)$、これを最小化する⇔パラメータ$\theta＝(\pi, \mu, \Sigma{} : 混合ガウス分布の構成要素)$一定のもと$q$を動かして対数尤度を極大化することがE法で、このプロセスは$X$と$\theta$（毎回M法で更新される）から事後分布を更新する
つまり、M法で更新した新しい$\theta$を使って、データを観測した後に、各点が属していたと思われるクラスターの（事後）分布を更新する

## なんかk-means法のくだりとだいぶ違う？
そんなことはない、むしろパラレル。
k-meansの、新しい重心$\mu$（M法に相当）を使って歪み尺度$r_{nk}$を更新する工程（E法に相当）も、あまくだりに$\rm{arg\,min}$が出てくるとなんじゃこりゃって感じになるけど、あれも損失関数を$r_{nk}$で偏微分すると出てくるので、汎関数の変分と全く同様の工程。

## M法は要するにこういうことをしている
こっちのがE法よりシンプルでわかりやすい。
事後分布を使って変分下限を極大化するパラメータ$\theta$を最尤法で求める。こうすることで下限は底上げされ、結果的に同じパラメータでつくられている対数尤度も大きくなるって寸法
k-meansで重心$\mu$を計算するプロセスも、損失関数を$\mu$で偏微分すると自然に重心が出てくるので、同様の考え方。

## k-means法の弱点はEM法で完璧に克服された感じ？
k-meansでのクラスタリングだろうがEM法を使った混合ガウス分布だろうがクラスターの数$k$を外から与えてあげなくちゃいけないという弱点は変わらないので、$k$の合理的な決め方、何らかの必然性なり最適化といえる$k$の決め方については別途検討する必要がある。

# 超絶参考にさせていただいた記事
[1. EMアルゴリズム徹底解説 @ Kenmatsu4](https://qiita.com/kenmatsu4/items/59ea3e5dfa3d4c161efb?fbclid=IwAR32TadxJUJXZXRYr-afYnn-0DyP_NBUdRXZJHXt57P6clfPhHUjNjykwfI)
2. Bishop本の 9. Mixture Models and EM の章
Flutter：起動実績のあるプロジェクトが起動しなくなった時の備忘録

久々にAndroid StudioとかVS Codeとか起動したらアップデートの通知が来ていたので、なんも考えずやってしまったら、Flutterプロジェクトが起動しなくなってしまった。
Android Studio、VS Codeともに同じ現象が発生する。

以下、エラー内容。

```
FAILURE: Build failed with an exception.

* What went wrong:
Could not create service of type ScriptPluginFactory using BuildScopeServices.createScriptPluginFactory().
> Could not create service of type ResourceSnapshotterCacheService using GradleUserHomeScopeServices.createResourceSnapshotterCacheService().

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 1s
  Command: D:\work\sampleProject\android\gradlew.bat app:properties
Please review your Gradle project setup in the android/ folder.
Exited (sigterm)
```
gradle がどうとかいうてるので、Android Studio のインストールフォルダを見てみると、「gradle-5.1.1」なるフォルダが見受けられた。プロジェクトで参照している gradle とのバージョン不一致ということらしい。
以下のように変更して起動確認。

```gradle-wrapper.properties 
（変更前）
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip

（変更後）
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
```
PHP x Laravel  x VSCode を Docker 上に構築 (1)

PHP と Laravel の開発環境も Docker で整えてしまうと楽です。今回の記事では、VSCodeもDockerに含めてみました。開発環境をまるごとDockerで管理できるので、管理がしやすいのでオススメです。

# 登場人物
### Dockerとは
Linux上でコンテナーでアプリを動作させる環境です。アプリケーションとライブラリーを同一のコンテナーで固めて、使い回すことができます。
https://ja.wikipedia.org/wiki/Docker

### VSCode
https://ja.wikipedia.org/wiki/Visual_Studio_Code
Microsoft製のEditorです。Dart Pluginを入れると、補間機能などが使えて便利です。

### Code-Server
VSCodeをWebサービスとして動作させることができる凄いやつです。
https://github.com/cdr/code-server


# 環境を作ってみる

https://github.com/kyorohiro/my-code-server/tree/master/php_laravel

### (1) dockerfile を書く

```dockerfile
FROM php:7
RUN apt-get update -y && apt-get install -y openssl zip unzip git
RUN apt-get install -y curl wget gnupg less lsof net-tools git apt-utils
RUN apt-get install -y emacs
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
RUN docker-php-ext-install pdo mbstring
WORKDIR /app
COPY . /app
#RUN composer install

#CMD php artisan serve --host=0.0.0.0 --port=8181

#
# CODE-SERVER
RUN wget https://github.com/cdr/code-server/releases/download/1.939-vsc1.33.1/code-server1.939-vsc1.33.1-linux-x64.tar.gz
RUN tar xzf code-server1.939-vsc1.33.1-linux-x64.tar.gz -C ./ --strip-components 1


```

### (2) docker image を走らせる
 
```
docker build -t php_laravel_vscode .
docker run -p 8443:8443 -p 8080:8080 -it php_laravel_vscode bash
# docke の中で
mkdir /app/w
/app/code-server /app/w --allow-http --no-auth
```

### (3) and 'http://127.0.0.1:8443/' を ブラウザーで開く

![root_page.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54192/8aefed41-e82e-ef99-6fa6-70ce03dc957e.jpeg)


# 試しに何か作ってみる

### (1) Terminal -> New Terminal on VSCODE

### (2) Terminal 上で以下を入力

```
root@8e5699b9caa4:/works/w# composer create-project --prefer-dist laravel/laravel blog
root@8e5699b9caa4:/works/w# cd blog
root@8e5699b9caa4:/works/w# php artisan  serve --host 0.0.0.0 --port 8080
```

### (3) 'http://127.0.0.1:8080/' を ブラウザーで開く

![welcome.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54192/bb9a8290-fdee-af10-77e1-24bee627c96f.jpeg)




以上です。

Code-Serverがとても便利でしたね。
https://github.com/cdr/code-server

終わり。

今回のコードは以下にまとめました。
https://github.com/kyorohiro/my-code-server/tree/master/php_laravel


#PS 


[a] 再開したい場合

```
$ docker ps -a
check id and
$ docker start < id > 
$ docker exec -it < id > bash
```

[b] 設定を変更したい場合
$ docker commit < id > php_laravel_vscode_xxx
$ docker run -p 8443:8443 -p 8080:8080 -it php_laravel_vscode_xxx bash

[c] マウント
$ docker run -p 8443:8443 -p 8080:8080 -v /Users/kyorohiro/w/xxx:/app/w -it php_laravel_vscode_xxx bash
Vue.jsつかってみた  #GWアドベントカレンダー7日目


 #GWアドベントカレンダー[「使いたかったもの使ってみたカレンダー（1人アドベントカレンダー）」](https://gw-advent.9wick.com/calendars/1)の7日目、5/3記事です。


# Vue.jsつかってみた

フロントエンドも触る人間として、気になってたけどできてなかったVue.jsを使ってみました。
やってみたのは**半年前の技術書展**で購入した「基礎から学ぶ Vue.js」の本を途中までやってみました。


## 良さそうなところ/面白かったところ

ちょうどこの前触ってみた、[Edgeテンプレートエンジン](https://edge.adonisjs.com/)に似た概念がたくさんあり、理解しやすかったです。どちらもコンポーネントを再利用しよう、再利用するためにはどうしたらよいか　という考えがベースになっているように感じます。

- コンポーネントごとにリサイクルができる
- computedで変動数値も簡単にかけるのが良い
- エラー時挙動も書きやすい



## あんまりイケてないところ

- 解説なしで他人のコードを見るとどこがどうなっているかわからない
- 実運用時に速度が気にならないか不安
- SEOがよくなさそうで怖い
- ときどき状態が変になって結局リロードする　ということが起きる（勉強不足の麺もあるかも）

## 総合評価

みんなが使っているだけあって、解説サイトも多いし、使いやすいと思います。
なによりもリサイクルできるのがいいですね。
多人数プロジェクトで使うときはルールがもう少し必要な気がするので、実運用どうしてるのか気になります。

サーバーサイドレンダリングまでできるとより使いやすそうなので、次回やってみたいです。
Slackの通知設定には気をつけよう（注意喚起）

## Slackの通知設定には気をつけよう（注意喚起）
どのようなプロジェクトに参加しているのであれ、コミュニケーションツールとしてSlackが採用されている可能性は高いと思います。

**そこで注意して欲しいのが、Slackの通知設定です。**

Slackの通知設定は各チャンネルごとに変えることができたり、スマホとデスクトップ版で変えることが出来たりと、かなり高機能です。
また、夜中のメッセージには通知が来ないようにするDo not disturbも意図せずONになっているケースも見受けられます。

メッセージにいち早く気づくためにも、通知の設定を確認してみてください。

僕もちゃんと設定しているつもりが、たまにメッセージに気がつくのが遅くなってしまう時がたまにありました。
最近は設定のおかげで減ってきましたが、皆さんもお気をつけください。
## 終わりに
私は現在、Web3のサービスの開発をしています。詳しくはこちらの記事をご覧下さい。
        [無料でイーサリアムが当たる、Web3時代の寄付サイトを作った話](https://note.com/kenroda/n/n814347fbdcd7)
NSPasteboardでsetStringした際に戻り値をtrueにできた話

# 共有したいこと
インフラエンジニアである自分がコピペで楽したいので[macOSアプリを自作した](https://github.com/ShinyaFukumura/cliputiex)のですが、その際にクリップボードへ文字列を格納する際に解決した点を共有します。

## 具体的に
1. macOSのクリップボードを操作するClassである[NSPasteboard](https://developer.apple.com/documentation/appkit/nspasteboard)には[func setString](https://developer.apple.com/documentation/appkit/nspasteboard/1528225-setstring)があることを確認。
2. よーし、setStringでstringをsetしちゃうぞ、ということで```NSPasteboard.general.setString(anyString, forType: NSPasteboard.PasteboardType.string)```なイメージで実装。
3. Boolを返すそうな、ということで```print(NSPasteboard.general.setString(anyString, forType: NSPasteboard.PasteboardType.string))```なイメージで実装アップデート。ブレイクポイントも設定したけど。
4. 実行！
5. 結果falseが返る・・・。[func setString](https://developer.apple.com/documentation/appkit/nspasteboard/1528225-setstring)によると*otherwise false if ownership of the pasteboard has changed.*とのこと。
6. うん。分からん！（ダメ人間）
7. クリップボードにsetできない理由って何だろう・・・妄想しつつ[NSPasteboard](https://developer.apple.com/documentation/appkit/nspasteboard)を眺めてみる。
8. んー、[func clearContents()](https://developer.apple.com/documentation/appkit/nspasteboard/1533599-clearcontents)ってある。中身をクリアしてからsetしたら動くかなという直感。
9. ```NSPasteboard.general.clearContents()```してから```print(NSPasteboard.general.setString(anyString, forType: NSPasteboard.PasteboardType.string))```な感じで実装。
10. 実行！
11. 結果trueが返る！幸せ。
12. 改めて[func clearContents()](https://developer.apple.com/documentation/appkit/nspasteboard/1533599-clearcontents)を読んでみるとDiscussionに、*Clears the existing contents of the pasteboard, preparing it for new contents. This is the first step in providing data on the pasteboard.*って、ちゃんと書いてある。
13. 結論、公式のドキュメントはよく読めと・・・。
Koalasの概要紹介

## この記事について

Databricks社が開発したpandas likeにSparkを動作させるライブラリ、[Koalas](https://github.com/databricks/koalas)についてのメモ書きです。 ~~ほぼ公式ドキュメントの日本語訳~~
koalasは更新が速いライブラリなので、2019年5月4日時点での情報であることをご留意ください。

## Koalasって?

pandasとPysparkデータフレームでインタフェースが違うところ、
例えばこういうやつら↓、

* データ結合
    * pandas -> `merge`
    * Pyspark -> `join`
* 列選択
    * pandas -> `df[["col1", "col2"]]`
    * Pyspark -> `df.select("col1", "col2")`

を覚えるの大変だから、pandasのような操作感でSpark動かせたら良いよねっていう思想で作られたライブラリ。すでにPysparkをある程度触ってる人がkoalasに乗り換えるというより、今までpandasメインで使ってきた人が、スムーズにSparkを動かせたら良いなーとのこと。
思想としては、Daskに触発されたらしい。
Sparkは2.4以降をサポートするとのこと。古いバージョンでも動くかもしれないけど保証はしないとのこと。
(Spark 2.4ってこの前出たばっかなのにずいぶん男前だな…w)

プロジェクトとしては **鋭意開発中** で、週単位でリリースしていくよ!とのこと。

## 実際に使ってみる

Databricks(Databricks Runtime 5.3)上で試しに使ってみる。
koalasをインストールする。ついでにnumpyがちょっと古いよって怒られたのでバージョンを上げる。

```.py
dbutils.library.installPyPI("Koalas")
dbutils.library.installPyPI("numpy", "1.12.0")
dbutils.library.restartPython()
```

koalasをインポートしてみる

```.
import databricks.koalas as ks
```

しかし、ここで残念ながらエラーが出てしまった。

```.py
 File "/local_disk0/pythonVirtualEnvDirs/virtualEnv-4735ad99-9fc8-4ac4-b1f9-de2e04aeb1b5/lib/python3.5/site-packages/databricks/koalas/frame.py", line 1073
    self._sdf: spark.DataFrame = kdf._sdf
             ^
SyntaxError: invalid syntax
```

うーーーーん。。
ちょうど今日コミットされたところだから、すぐ直るんだろうけども、。、
あとでissue上げとこう。。

## 2019/05/07追記: 今度こそ試してみる

@harupy様のコメントを参考に、 `koalas` のバージョンを0.1.0に戻して試してみた。
無事動作。
ちなみに、0.3.0は上記とは別のエラーが出てしまいまたもや動作せず・・・。
前回同様Databricks上でチャレンジ。

```.py
dbutils.library.installPyPI("Koalas","0.1.0")
dbutils.library.installPyPI("numpy", "1.12.0")
dbutils.library.restartPython()
```

```.py
import databricks.koalas as ks
import pandas as pd
import numpy as np

print(ks.__version__)

>>>0.1.0
```
バージョン0.1.0でトライ。

適当なデータフレームを作ってみる。

```.py
kdf = ks.from_pandas(pd.DataFrame({"A":[x for x in range(100)], "B":[x**2 for x in range(100)], "C":np.random.randint(0,5,100)}))
print(kdf.shape)
print(len(kdf))
```
上手く伝えられないのが残念ですが、このコードを実行すると、Databricksのプログレスバーが出ます。確かにSparkが動いてる。

groupbyしてみる

```.py
agg_kdf = kdf.groupby('C').agg({'B': 'max', 'A': 'sum'})
agg_kdf.toPandas()
```

インタフェースは完全にpandasですね。
`.head()` はサポートされていないようなので、DataFrameの中身を見るためには、 `toPandas()` がとりあえず有効です。

ちなみに、未実装のメソッドも当然ながら多く、未実装のメソッドを実行するとこんな感じのエラーが出てしまいます。

```.py
kdf.query("A == B")
```

ありのまま感がすごい。

```.py
PandasNotImplementedError: The method `pd.DataFrame.query()` is not implemented yet.
```

## まとめ

絶賛開発中で不安定ではありますが、Sparkが活躍するような大規模データをpandas-likeに処理できることができました。
pandasはpythonでデータ分析を行う人であれば誰でも触るライブラリですし、koalasでもっと柔軟な処理ができるとお手軽に大規模データを扱うことができて良さそうですね。定期的に見守っていきたいと思います。
【異常検知と変化検知】ホテリングのT2法を実践した

井出先生、杉山先生著の「異常検知と変化検知」の技術を身に着けたく、
適当なkaggleのデータセット見つけて実行してみました。
まずは手始めにホテリングのT2法から。

詳細は下記にipynb上げてます。

https://github.com/nagiton/anomaly_detection/blob/master/T-sq_method.ipynb


見られない場合はnbviewer使ってください。（すいません許してくださいなんでもしますから）
https://nbviewer.jupyter.org/github/nagiton/anomaly_detection/blob/master/T-sq_method.ipynb
（なぜロードに失敗する場合があるんだ・・・・）

実際の問題に適用するととても身につきますねえ。
今後も（この本のネタを使うかわからないけど）続けていきたい。
[Unity]Post Processing Stack v1からv2への移行手順

# はじめに

UnityでPost Processing Stackを使うと絵がめちゃくちゃかっこよくなるので使いまくってました。V2が出たときにさらに使いやすくなったので喜んだものの、それまでV1で作ったプロジェクトを再利用したい場合などに互換性がなくていろいろ苦労したのでメモ。

# v1とv2の違い

## ライブラリインストール手順
|  | v1 | v2 |
|-----------|------------|------------|
|ドキュメント[^1] |https://docs.unity3d.com/ja/current/Manual/PostProcessing-Stack.html |https://github.com/Unity-Technologies/PostProcessing/wiki |
|インストール方法[^2] |Asset StoreからPost Processing Stackを検索してインストール |Windowメニュー → Package Manager → Post Processing |
|インストール先 |Assets/PostProcessing |Packages/Post Processing |

## シーンへの導入手順

|  | v1 | v2 |
|-----------|------------|------------|
|1. プロファイル作成[^3]|Assetsメニュー → Create → Post-Processing Profile|Assetsメニュー → Create → Post-Processing Profile|
|2. メインカメラ設定|・Post Processing Behaviour追加<br>・1.で作成したプロファイルを指定|・Post Processing Layer追加<br>・Post Processing LayerのLayerでPostProcessingを選択|
|3. オブジェクト設定|（不要）|・シーンに空のオブジェクトを配置<br>・オブジェクトのLayerをPostProcessingにする<br>・オブジェクトにPost Process Volume追加<br>・Is Globalにチェックを入れる<br>・1.で作成したプロファイルを指定|
|4. パラメータ設定|プロファイルを選択して設定|・プロファイルを選択して設定<br>・3.で追加したオブジェクトを選択しても同じものが表示される<br>・AntialiasingはメインカメラのPost Processing Layerで設定|


# どっちを使うべきか

v2一択。
上に書いたdocs.unity3d.comのドキュメントが2019/5/4現在 v1ベースなのでv1を使いたくなりますが、Asset Storeのv1のページには、「Deprecated for new projects; please use V2 instead.」とあるので、特に理由がない限りv2を使うべき。

# v1とv2は共存可能か？[^4]

- 同じプロジェクトに両方のライブラリをインストールして、シーンごとにv1かv2か使い分けてもほぼ問題なし
- ただし、Assetsメニュー → Create → Post-Processing Profile としてプロファイルを新規作成しようとすると同じ名前のメニューが二つ出てわかりづらい
- 以前、同じシーンにv1とv2を入れちゃったとき、わりとそれっぽく動いたけどキモいのでおすすめしない

# v1導入済みプロジェクトをv2に置き換える手順

## そもそも最新のUnityでv1がビルドできなくなったんだけど？
> Assets/PostProcessing/Editor/PropertyDrawers/MinDrawer.cs(6,34): error CS0104: 'MinAttribute' is an ambiguous reference between 'UnityEngine.MinAttribute' and 'UnityEngine.PostProcessing.MinAttribute'

のエラーが出る場合、MinDrawer.csを開いてMinAttributeとなっているところ（3か所）をUnityEngine.PostProcessing.MinAttributeと書き換えて保存すればOK。
参考：https://forum.unity.com/threads/post-processing-stack-error.554926/

## 移行手順

1. （事前準備）とりあえずプロジェクトごとバックアップしておく
2. v1のプロファイルを選択してスクリーンショットをとっておく。実行画面もスクショをとっておく
3. メインカメラのPost Processing Behaviourを削除
4. Assets/PostProcessingフォルダ削除
5. Windowメニュー → Package Manager → Post Processingでv2をインストール
6. Assetsメニュー → Create → Post-Processing Profileでv2のプロファイル作成[^5]
7. メインカメラにPost Processing Layerを追加
8. Post Processing LayerのLayerでPostProcessingを選択
9. シーンに空のオブジェクトを追加
10. 空のオブジェクトのLayerでPostProcessingを選択
11. 空のオブジェクトにPost Process Volumeを追加
12. Post Process VolumeのIs Globalにチェックを入れる
13. Post Process VolumeのProfileでv2のプロファイルを選択
14. Post Process Volumeで「Add effect」を押してv1で使用していたエフェクトを追加、v1のスクショを見ながらパラメータ調整[^6]
15. v1でAntialiasingを使用していた場合、メインカメラのPost Processing Layerで設定する



[^1]: 2019/5/4現在、docs.unity3d.comのドキュメントは日本語版も英語版もv1の内容が表示されるので注意。v2へのリンクあり
[^2]: v2がAsset Storeにないのも落とし穴
[^3]: v1とv2のプロファイルはファイル名は同じだが別のもの（アイコンが違う）。バイナリファイルなので直接編集も難しい
[^4]: 公式ドキュメントには情報がないので経験則です
[^5]: ファイル名はv1と同じだけど、カラフルなアイコンだったらv2プロファイル作成成功
[^6]: パラメータもいろいろ変わっているので完全に同じにはならない。そのため最終的には目で見て比較して合わせる
静的サイトジェネレータhexoつかってみた   #GWアドベントカレンダー6日目


 #GWアドベントカレンダー[「使いたかったもの使ってみたカレンダー（1人アドベントカレンダー）」](https://gw-advent.9wick.com/calendars/1)の6日目、5/2記事です。

5/4に投稿しますが、5/2分記事です。時空がゆがんでいるのはアドベントカレンダーあるあるなので仕方のないことです。

# 静的サイトジェネレータhexoつかってみたつかってみた 

[hexo](https://hexo.io/)は静的はブログを作成するツールです。
マークダウンからHTMLを生成し、HTMLのみで構成されたブログを作ることができます。


## 何に使ったのか

[個人ブログ](https://9wick.com)に使っています。
Qiitaばかり投稿してあんまり更新できていないブログのため、メンテナンスが
めんどくさい
とても簡単にできるように、静的ページにしようと思いました。


## 作るとき参考にしたサイト
[公式サイト](https://hexo.io/)
[のびすけさんの記事](https://liginc.co.jp/web/programming/server/104594)


## 良さそうなところ/面白かったところ

ざっと使ってみた感想です。

- メンテ不要なのが良い
- HTMLホスティングだけで完結するのが良い（ローカルでHTML生成を実行）
- マークダウンで記事をかけるのが良い
- スパムを気にしなくて良い
- パーマリンク設定が結構自由に変えられる
- ローカルでもビルドせずに試せる



## あんまりイケてないところ

- カテゴリとかタグとかがキャッシュされているため、記事を書いて消してを繰り返すと変になる
- プラグインの使い方がよくわからないものが多い
- 記事が多くなると劇的に重くなるらしい（？）


## 総合評価

普段からnode.jsを使ってるならありじゃないでしょうか。
そうでない場合は、わざわざnode.js環境を入れてまで使う理由はないと思います。
それぞれの言語で静的サイトジェネレーターがあると思うので、そちらが良いかなと思います。
マイクロサービスについてのメモ書き

マイクロサービスをちゃんと調べたことがなかったので、以下のサイトを参考に調べた内容をメモに起こしました。

- [microservices.io](https://microservices.io/)<br>
マイクロサービスについての説明、パターンやサンプルコード
- [Microservices anti-patterns in Melbourne](http://chrisrichardson.net/post/antipatterns/2019/01/28/melbourne-microservices.html)<br>
マイクロサービスのアンチパターン

---
- マイクロサービスのざっくりまとめ
    - ビジネスケーパビリティなどの単位でサービスを分割する<br>分割の仕方はビジネスケーパビリティ以外にも、DDDのサブドメイン単位などいろいろな戦略がある
    - 分割サイズで小さいチーム（数人？）で開発可能な規模とする
    - それぞれのサービスを独立したーチームが開発・運用する
    - それぞれのサービス間を疎結合とする<br>それによって他のサービスの変更の影響をなくす
    - それぞれ独立してデプロイを可能とする<br>それによりデプロイ時に他のチームを気にしなくて済む
    - それぞれのサービスで独立したDBを持つ
    - Sagaパターンでデータの一貫性を確保する

- メリット
    - メンテナンス性が高い
    - 独立してデプロイ可能
    - スケールしやすい
    - 障害切り分けがしやすい
    - テストしやすい
    - 新機能の実験をしやすい
- デメリット
    - 以下などいろいろと複雑になるところもある
        - 開発面：IPC、データの分散、部分的なfailの対応
        - テスト面：インテグレーションテスト、E2Eテスト
        
- アンチパターン
    - サービスへの分け方がまずく、処理時間や可用性が悪化<br>->疎結合化、非同期化
    - DBの共有<br>->サービス毎にDBを
  - カプセル化できずAPIの変更がクライアント側に影響する<br>->APIを小さく、実装を大きくしてカプセル化
  - 共有ライブラリなどでサービス間が結合してしまう<br>->CCPの原則で対応する(一緒に変更するものは一緒にパッケージ)
  - マイクロサービス化がゴールではない<br>->速く・頻繁に信頼性のあるソフトウェアを提供するのをゴールとする
  - チーム間の統制・共有がなく同じことを複数チームで実施してしまう
  - キースキルがないうちに実践して失敗する

- その他
    - [マイクロサービスアセスメントプラットフォーム](http://chrisrichardson.net/post/antipatterns/2019/01/28/melbourne-microservices.html)
Railsでf.labelを日本語化する (i18n)

```new.slim
= f.label :first_name
= f.text_field :first_name

= f.label :family_name
= f.text_field :family_name
```

デフォルトではフォームに`FirstName` `FamilyName`と表示されてしまいます。
これらを日本語化したいときは以下の2ステップ。

# 1.config/application.rbに設定
以下のように変更&追記

```config/application.rb
config.i18n.default_locale = :ja #jaに変更
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s]
```

# 2.config/locales以下にmodels/ja.ymlを追加
config/locales以下にmodelsファイルを作成し、その中に以下のようなja.ymlファイルを配置

```config/locales/models/ja.yml
ja:
  activerecord:
    models:
      user: ユーザー
      admin: 管理者
    attributes:
      user:
        id: ID
        first_name: 名
        family_name: 姓
      admin:
        id: ID
```

これで無事、日本語表示されます。
Leetcode #80: Remove Duplicates from Sorted Array II


```swift
func removeDuplicates(_ nums: inout [Int]) -> Int {
    if nums.isEmpty {
        return 0
    }
    var index = 1
    var pre = nums[0]
    var duplicate = 1
    var length = nums.count
    var removedIndex = -1
    while index < nums.count {
        if nums[index] == pre {
            duplicate += 1
        } else {
            if removedIndex != -1 {
                nums[removedIndex...] = nums[index...]
                length -= (index-removedIndex)
                index = removedIndex
                removedIndex = -1
            }
            pre = nums[index]
            duplicate = 1
        }
        if removedIndex == -1 && duplicate > 2 {
            removedIndex = index
        }
        index += 1
    }
    if removedIndex != -1 {
        nums[removedIndex...] = []
        length = removedIndex
    }
    return length
}
```
KerasでCycleGANを組んでボイチェン声真似おじさんになれそう

# はじめに
　[前回の記事](https://qiita.com/lefirea/items/dc99c9b8975efac70938)から大幅な更新があったのでその報告を。
　声マネおじさんになれそうで嬉しい。

# 更新点は？
　Generatorのモデルを、Conv1Dを使うモデルから、全結合のみのモデルに変えた。
　Discriminatorはそのまま。他の部分もそのまま。

##　なんで？
　よくある参考書とかで、MNISTの学習がチュートリアルなのが多いと思う。で、それを見てると、最初は28*28の2次元データを784の1次元データにしてから学習させてるのが多い(個人的な感覚)。
　で、今回の方法も、STFTした結果(2次元、直交座標)を極座標に変換して、その大きさZと偏角θを、1本ずつ(1次元ずつ)入力して変換している。
　ってことで、モデルを本に書いてあったやつを参考に組んでみたら上手く行ったっぽいって話。
　多分、前回使っていたConv1Dは、今回の入力方法と相性が悪いんでしょうね。よく分からんけど。Conv1Dはいつ使うんやって疑問は浮かんだけど今は放置。そのうち調べると思う。多分。

##　モデルはどうなった？
　こうなった。

```python
input = Input(shape=self.input_shape)
d = Dense(units=self.dim // 2)(input)
d = Dropout(0.5)(d)
d = LeakyReLU(alpha=0.2)(d)
d = Dense(units=self.dim // 4)(d)
d = Dropout(0.5)(d)
d = LeakyReLU(alpha=0.2)(d)
output = Dense(units=self.dim, activation="sigmoid")(d)
```

　要は、Conv1Dを使う畳み込み層の部分を消して、全結合層の部分だけ残した感じ。
　self.dimが入力するデータの長さ。~~今回はFFT長さの半分である512。FFTすると、FFT長さの半分が得られるようで、それに合わせた結果。~~ 勘違いしてました。コードを見ると、自分でFFT長さを512にしてました。
　処理速度めっちゃ速くなったし、結果も良くなったしで良いことばっかり。各層のノード数を調整すればもっと良い結果になりそう。多分。そのうち調整するかも。

##　変換結果は？
　変換が進んでいると断言できる程度の結果にはなってる。現在(2019/05/04)、407kイテレーションほど進んだけど、半分半分って感じかな。
　

#　今後の展望とか
　とりあえず経過を見て、順調そうならStarGANっていう、CycleGANを拡張したようなやつを試したい。これができると色々面白そう。
　でも文字列から音声生成できるような機械学習もやりたい。WaveNetができるらしいけど、解説が少なくてよく分かんない。
　とりあえず、自然言語処理あたりに手を出してみたい。アニメキャラっぽい感じの会話botとか作れたら面白そう。
Node-RED で変更されたファイルを読み込む

#目的
FTPで送信されてくるCSV形式のデータをエッジデバイス(RaspberryPi)で検出＆処理したい。

#環境
Ubuntu : 18.04.2
Node.js : 10.15.3
Node-RED : 0.20.5

#ファイルの変更を監視する
watch ノードを使用してファイルとディレクトリの変更を監視します。
![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240467/65cd6dd8-0cea-bab4-44b4-abcb3f8a6f49.png)
変更されたファイルのフルパスやサイズが取得できます。

#変更されたファイルを読み込む
file in ノードを使用してファイル内容を読み込みます。
![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240467/9e48aed3-76a6-3b1b-98af-0b8e2dcd118c.png)
watch ノードが msg.filename をセットしてくれるので、ファイル名は指定しません（ここ重要）。

#CSVテキストをJSONオブジェクトへ変換
CSV ノードを使用します。
![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240467/f493595a-2ed1-42ec-d914-1d270139af12.png)
msg.payload の string を object へ変換してくれます。

変換前
![image4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240467/50371f91-27d7-8b35-76f7-0653d183942d.png)

変換後
![image5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240467/0997a25f-e812-794b-8896-f1fdde55c0fe.png)

Node-RED 超便利！！！
Unityで人工知能の本を読んだときのメモ

# 2-1 開発環境の準備
- [本に合わせてUnity2017を使用](https://unity3d.com/jp/get-unity/download/archive?_ga=2.167259386.55446549.1556966064-253761851.1556966064)
- [unity ML-AgentsのDL](https://github.com/Unity-Technologies/ml-agents)
- [TensorFlowSharpのプラグイン](https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Basic-Guide.md)
- [Anaconda<Python3](https://www.anaconda.com)
- ●「pip install .」を行う場所
- 「/ml-agents-master/python」→「/ml-agents-master/ml-agents」に変更

# 2-2 プロジェクトの設定

- ●プロジェクト名
- 「/ml-agents-master/unity-environment」→「/ml-agents-master/UnitySDK」に変更
-
Alexa Reminder skillのリマインダー作成時のtriggerについて

Alexaで利用可能なリマインダー作成において、JSONで設定可能なtrigger値がわかりませんでした。どこかに記載されているのかな？
色々試してみた結果に基づき、まとめておこうと思います。

#triggerで設定できるフィールド
Alexa Skills Kitの[AlexaリマインダーAPIリファレンス](https://developer.amazon.com/ja/docs/smapi/alexa-reminders-api-reference.html
)によれば、triggerはSCHEDULED_ABSOLUTEとSCHEDULED_RELATIVEで設定可能な要素が異なるようです。

##SCHEDULED_ABSOLUTEの場合
```
"trigger": {
  "type"
  "scheduledTime"
  "timeZoneId"
  "recurrence": {
    "freq"
    "byDay"
  }
}
```

|フィールド|取りうる値|説明|
|:--|:--|:--|
|type|SCHDULED_ABSOLUTE, SCHEDULED_RELATIVE|絶対時間で設定する場合、SCHDULED_ABSOLUTEにします。|
|scheduledTime|有効なISO 8601形式で、TimeZoneはなしのもの。|2019-05-01T00:00:00のような形。最後にZとTimeZoneがついていると、UNSUPPORTED_SCHEDULED_TIME_FORMATとなるようです。ここで設定する年月日は意味がありません。recurrenceの設定値に依存します。|
timeZoneId|"Asia/Tokyo"|とりあえず左記。すべてのリストは、[Time zone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)の記載の通りのようです。|
|recurrence.freq|DAILY, WEEKLY|毎日、もしくは週単位で設定。個人的には隔週も設定したい。|
|recurrence.byDay|SU, MO, TU, WE, TH, FR, SA|recurrence.freqをWEEKLYに設定する場合、何曜日に設定するかを指定します。各曜日のイニシャルをつけるようです。また、ここで複数設定（例えば、"MO", "TU"）するとエラーUNSUPPORTED_TRIGGER_RECURRENCEになるようです。|

###注意事項
scheduledTimeは、タイムゾーンがない時間を設定します。
そのため、Date関数のtoISOString()を使って設定すると、最後にタイムゾーンを示す「Z」が含まれるため、「UNSUPPORTED_SCHEDULED_TIME_FORMAT」エラーが発生します。他のサイトでは、「INVALID_TRIGGER_SCHEDULED_TIME_FORMAT 」となると記載されていました。少し私の環境とエラーメッセージが異なる理由はわかりません。
[Alexa Skills Kit](https://developer.amazon.com/ja/docs/smapi/alexa-reminders-api-reference.html#error-messages)では、「INVALID_TRIGGER_SCHEDULED_TIME_FORMAT」になるような記載がありました。
いずれにせよ、scheduledTimeの時間設定は最後の「Z」は不要そうです。

```
new Date().toISOString();  // 2019-05-01T00:00:00.000Zとなる。「Z」は不要。
```

recurrence.byDayは、配列で曜日を設定できますが、現時点では複数設定するとエラーUNSUPPORTED_TRIGGER_RECURRENCEが発生し、設定できません。
###サンプルソース
```
const date = new Date();
date.setTime(date.getTime() + 1000*60*60*9 + 1000*60);  //1分後に設定

const body = {
  requestTime : date.toISOString().substr(0, 23),
  trigger : {
    type : "SCHEDULED_ABSOLUTE",
    scheduledTime : date.toISOString().substr(0, 23),
    timeZoneId : "Asia/Tokyo",
    recurrence : {  //毎週月曜日
      freq : "WEEKLY",
      byDay : ["MO"]
    }
  },
  alertInfo : {
    spokenInfo : {
      content : [{
        locale : "ja-JP",
        text : "時間です"
      }]
    }
  },
  pushNotification : {
    status : "ENABLED"
  }
};
```

##SCHEDULED_RELATIVEの場合
```
"trigger": {
  "type"
  "offsetInSeconds"
}
```

|フィールド|取りうる値|説明|
|:--|:--|:--|
|type|SCHDULED_ABSOLUTE, SCHEDULED_RELATIVE|相対時間で設定する場合、SCHDULED_RELATIVEにします。|
|offsetInSeconds|秒数|リマインダーが鳴らされるまでの時間（秒）を指定します。|

###サンプルソース
```

const body = {
  requestTime : date.toISOString().substr(0, 23),
  trigger : {
    type : "SCHEDULED_RELATIVE",
    offsetSeconds : "60"
  },
  alertInfo : {
    spokenInfo : {
      content : [{
        locale : "ja-JP",
        text : "時間です"
      }]
    }
  },
  pushNotification : {
    status : "ENABLED"
  }
};
```
Ubuntu 18.04でwifi子機を使う

## はじめに
Linuxの新しいバージョン(kernel 4.15など)に公式で対応をうたってるwifi子機アダプターはなかった。そこでamazonで買った[このアダプタ](https://www.amazon.co.jp/gp/product/B07PHMMY98/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1)にgithubで公開されているドライバーをインストールして使うことにした。
調べてわかったがこの手のアダプタはいろんな種類があるが、中身はrealtek社のものがほとんどだから、違う商品でもわりとドライバーの種類は限られているみたい。今回はその中でも`rtl88x2bu`の方法を紹介する。

## ドライバーのダウンロード
ドライバーは[公式ページ](https://github.com/its-izhar/rtl88x2bu-driver)からダウンロードし、事前に作っておいた`Driverディレクトリ/home/Driver`に格納する。
ターミナルで
```
cd /home/Driver/rtl88x2bu-driver-master
```
と入力してダウンロードしたrtl88x2bu-driver-masterフォルダーがホームディレクトリとなるように移動する。
続いて以下のコマンドを順に実行する。
```
make clean
make -j8
sudo modprobe cfg80211
sudo insmod 88x2bu.ko
```

## wifiアダプタの接続
wifiアダプターをPCに接続してみる。wifiアダプタが認識されるはずだ！！！

## 再起動しても、自動でアダプタがロードされるようにする
ここまでで一応使えるようになったが、今のままだと再起動するたびにこの作業をすることになってしまう。そこでアダプタのロードを起動時に自動でやってくれるように設定していく。
再びターミナル上で
```
sudo nano /etc/rc.local
```
と入力し、何も書かれていないテキストエディターが現れたら
```
#!/bin/sh
sudo modprobe cfg80211
sudo insmod /home/(username)/Driver/rtl88x2bu-driver-master/88x2bu.ko
exit 0
```
と入力し、`ctrl+Shift+x`で保存して終了する。また以下のコマンドで、実行権限を追加しておく。

```
chmod u+x /etc/rc.local
```
次に以下を入力ししエディターが現れたら、
```
sudo nano /etc/systemd/system/rc-local.service
```
今度はここに以下を追記する。
```
[Unit]
Description=/etc/rc.local

[Service]
ExecStart=/etc/rc.local
Restart=always
Type=simple

[Install]
WantedBy=multi-user.target
```
これも`ctrl+Shift+x`で保存して終了。
最後の最後に
```
sudo systemctl enable rc-local.service
```

これで全部の設定が終わったはず。
windowsとかmacとか古めのlinuxに比べてwifiドライバー使えるようにするだけでも一苦労！

## wifiアダプタが使えるようになるまでの回線
Ubuntuをインストールしてから、wifiアダプタを認識させるまでにもインターネット接続が必要になる個所がいくつかあった。有線LAnがあれば問題ないけどwifiしかない環境って場合には携帯のテザリングがおすすめ。ドライバーなしでUSB接続するだけですぐに使える。

## 参考記事
* [github](https://github.com/its-izhar/rtl88x2bu-driver)
* [似てる記事](https://qiita.com/diescake/items/2370dc67a0ed40b089ba)
* [chmodの使い方](http://motw.mods.jp/UNIX/chmod.html)
* [起動時に自動でコマンド](http://atomiyama.com/linux/page/rc-local-systemd/)
Ubuntu Server 18.04 でのkubernetesクラスタ構築

#0. 何の目的か
- ソフトウェアデザイン2019年４月号の「Ubuntu Monthly Report（Ubuntu Serverでkubernetesを動かす）」を参考にk8sを構築する！（写経して学ばせていただきます:bow:）
- CKA（Certified Kubernetes Administrator）の合格しよう！（試験環境がUbuntu）
- RHEL以外にUbuntuも習得しよう！

#1. Ubuntuでの固定IPアドレス設定
DHCP設定にしてたのでOS再起動したらk8sが動かなくなりました。
OSインストール時に固定IPアドレスを選択することもできるのですが、定義ファイルを以下のように変更しました。

```/etc/netplan/50-cloud-init.yaml 
network:
    ethernets:
        enp0s3:
            addresses:
            - 192.168.1.100/24
            gateway4: 192.168.1.1
            nameservers:
                addresses:
                - 192.168.1.1
    version: 2
```

以下のコマンドで定義ファイルを有効化させます。

```
$ sudo netplan apply
```

定義ファイルはyamlファイルになってまして、記載方法の詳細は以下のサイトに書かれています。
[netplan](https://netplan.io/)

#2. VirtualBoxのネットワーク設定
それから、以下の設定変更を行うことでssh接続ができるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280358/7ea1debf-1118-c561-79d9-29f86d0c310f.png)

#3. CPUは2個以上
1個だと以下の様にエラーとなります...

```
$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16
[sudo] password for shinj: 
[init] Using Kubernetes version: v1.14.1
[preflight] Running pre-flight checks
	[WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/
error execution phase preflight: [preflight] Some fatal errors occurred:
	[ERROR NumCPU]: the number of available CPUs 1 is less than the required 2
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
```

#4. マスターノードでPodのデプロイを許可
ここだけ手順の通りに出来なかったので、どうやったかを残しておきます。

```
$ kubectl get node
NAME            STATUS   ROLES    AGE   VERSION
ubuntu-server   Ready    master   30m   v1.14.1

$ kubectl describe node ubuntu-server | grep Taints
Taints:             node-role.kubernetes.io/master:NoSchedule

$ kubectl taint nodes ubuntu-server node-role.kubernetes.io/master:NoSchedule-
node/ubuntu-server untainted

$ kubectl describe node ubuntu-server | grep Taints
Taints:             <none>
```

#5. デモアプリケーションの動作確認！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280358/36d1ca0a-554d-029e-5445-ff31127298dc.png)

記事通りに操作を行っても、途中で疑問に感じたり、あれっ？となって調べたり、学べることは多いです:pray:
Python OpenCVで画像を検索、判定結果を返してみた

## 背景
画像の一部に、検索したい画像が含まれているかどうかを
判定したい思いにかられたのでやってみました。
元画像の一致した部分を四角で囲んで表示／保存する先例はあったのですが、
判定結果を数値で返す例があまりなかったので、投稿。

こんなイメージ↓↓↓
（左：検索先画像、右：検索したい画像）
（左の画像をトリミングして、右の画像を作っています）
![スクリーンショット 2019-05-04 22.53.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288322/52ee7c91-211b-b276-be33-c37aef2fa6eb.png)


## 環境
MacOS Mojave ver10.14.4
Anaconda Navigator 1.9.7
　※Anacondaのインストールは、[こちら](https://qiita.com/satoshi-iwaki/items/e431b4182e50a2918a17)を参考に
JupiterNotebook 5.4.0
OpenCV 3.4.2
※OpenCVのインストールは[以前の記事](https://qiita.com/anzanshi/items/a88df7db49f77f65fbbf)を参照ください
「初心者がpython Anaconda GUIで、簡単にOpenCVをインストールしてみる」
　https://qiita.com/anzanshi/items/a88df7db49f77f65fbbf

## 手順
#### 方針
　元画像と、元画像をトリミングした比較画像を部分一致検索をかける！
　最も高い類似度が閾値を超えているかどうかを判定する！
　判定結果を返す
#### 実装

まずは、OpenCVを使うためにライブラリをインポート

```python
import cv2  #OpenCVをインポート
```
画像の一致率を判定するための関数を設定

```python
def Judge_Matching(num):
    if 0.99 < num:
        return True
    else:
        return False
```
画像を読み込みんで、画像の一部が含まれているかを検索
※OpenCVのmatchTemplate関数の仕組みは[こちら](http://pynote.hatenablog.com/entry/opencv-template-matching)が分かりやすかったです。
※TM_CCORR_NORMEDは、類似度の計算方法の一種。他にも色々あるみたいです。

```python
# 検索元／先画像を読み込み
image = cv2.imread('./imagesFolder/temp/temp_moto.png') #検索先画像のファイルパスを指定
template = cv2.imread('./imagesFolder/temp_template/temp_saki.png') #検索元画像ファイルパスを指定

#OpenCVで画像部分一致を検索
result = cv2.matchTemplate(image, template, cv2.TM_CCORR_NORMED)

# 最も類似度が高い位置と低い位置を取得します
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(result)

#類似度が閾値を超えているか判定（上で作った関数を使用）
Judg = Judge_Matching(maxVal)

#結果を出力
print(Judg)
# （実行結果→）True or False

```
実行例↓↓↓
![スクリーンショット 2019-05-04 22.55.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288322/537b338e-ba69-6b35-dec2-b25d2874d11d.png)

## 終わりに
画像の一部検索の結果を出力することができました。
次は、指定したフォルダ内の複数の画像に対して検索をしてみたいと思います。

## 参考
http://pynote.hatenablog.com/entry/opencv-template-matching
http://thr3a.hatenablog.com/entry/20150727/1437973061
Leetcode #77: Combinations

Use backtracking to find all the possible combinations

```swift
func combine(_ n: Int, _ k: Int) -> [[Int]] {
    if k == 0 {
        return [[]]
    }
    var answer = [[Int]]()
    var combination = [Int]()
    helper(Array(1...n), 1, k, &combination, &answer)
    return answer
}

private func helper(_ ar: [Int], _ start: Int, _ k: Int, _ combination: inout [Int], _ answer: inout [[Int]]) {
    if k == 0 {
        answer += [combination]
        return
    }
    if start > ar.count {
        return
    }
    for i in start...ar.count {
        combination += [i]
        helper(ar, i+1, k-1, &combination, &answer)
        combination.removeLast()
    }
}
```
はじめてFlutterでアプリをリリースした感想

# はじめてFlutterでアプリをリリースした感想

以前、[iOSのアプリをリリース](https://qiita.com/dyson-yamashita@github/items/8dca332c0e09f8fde13d)しました。今回は[Flutter](https://flutter.dev)でiOS向けアプリを開発、リリースをしたのでその感想です。
※iOSアプリを作った経験に基づき、あくまで個人的な感想です。

- 作ったアプリ: [StarsMix](https://itunes.apple.com/gb/app/starsmix/id1461653199?mt=8&ign-mpt=uo%3D2) [[Webサイト]](https://dyson-yamashita.github.io/winkry-site/)

<img width="450" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20217/bb1e4ebe-50fe-ff59-8b72-707d3cc0a7d8.png">


# Flutterとは
> Flutter allows you to build beautiful native apps on iOS and Android from a single codebase.
https://flutter.dev

[Flutter](https://flutter.dev)は単一のコードをiOSとAndroidのアプリを開発できるフレームワークです。Flutterの開発元はGoogleで、Dartという言語でコーディングします。

# なぜFlutter？
モバイルのクロスプラットフォームもフレームワークとしてはReactNativeなどもありますが、Googleが開発中の新OSであるFuchsiaのアプリはFlutterでという噂もあり、興味が湧いたのでFlutterでの開発を行いました。

# Flutterでよいと思うこと
- すべてをコードで管理する
Flutterでは画面の構成も含めてすべてコードで記述します。
そのためiOSのようにストーリボードでデザインするか、
コードで書くかを迷うことはないです。
また、[FlutterStudio](https://flutterstudio.app)というツールが公開されており、
GUIで画面をデザインできるツールがあります。
今回はFlutterStudioで大まかにデザインして、
そこからカスタマイズしていきました。

- ホットリロード
コードの変更を再ビルドすることなくシミュレータに反映することができます。全ての変更がホットリロード可能ではないですが、変更をすぐに確認できる点はメリットです。

- パッケージが豊富
すでにいろいろな機能が[パッケージとして公開](https://pub.dartlang.org/flutter)されています。
pubspec.yamlというyamlファイルにパッケージを指定し、更新することで利用できます。iOSのCocoaPodsに似ていますが、Flutterでは標準でパッケージ管理の機能があります。

# Flutterで困ったこと
- ネイティブ側コードの制限    
パッケージがなく、ネイティブの機能を利用したい場合は、ネイティブのコードを書く必要があります。ネイティブのコードを書く場合は、
MethodChannelという仕組みを使ってNative側の機能を呼び出します。Native側に渡すデータの型の制限などもあり、試行錯誤が必要な場合があります。

# まとめ
Nativeでの実装を減らしていくことで、
Flutterの良さが出せると感じです。

# 参考サイト
- [iOSネイティブアプリ開発者から見たFlutter](https://medium.com/flutter-jp/flutter-ios-5b2178018d3e)
- [FlutterStudio](https://flutterstudio.app)
Win10でPyTorch C++API ExamplesのDCGANを動かす

# はじめに
普段はPythonを使って学習させているのですが、何となくC++APIを使ってみたくなりました。しかし、WindowsでMSBuild使うと(当たり前ですが)、チュートリアル通りでは動きませんでした。
これ以外の方法もあるかと思いますが、私はこの方法で成功したので残しておきます。

# 環境
Windows 10
CUDA 10.0
NVIDIA Driver 430.39
MSBuild ver. 15.9.21+g9802d43bc3
cmake ver. 3.13.3

# libtorchをダウンロード

PyTorchの公式サイトから自分に合ったlibtorchをダウンロード
展開して/path/to/libtorchに配置
私はCドライブ直下に入れてしまったので今回はそれで進めます。

# ビルド方法
pytorchのexamplesをcloneするところから始めます。
lsを使えているのはcmdの代わりにcmder使っているからです。

**注意**
今回の方法でcloneしたまま行うと、エラーが出ずに"CUDA is available! Training on GPU."とだけ
Logに出力されて終了します。
これはdataディレクトリが適切な場所に置かれていないためです。
なので以下の方法の**どちらか**をとってください。

- dcgan.cppファイルの17行目のkDataFolderの値を"./data" から "../data"に変更

```cpp:dcgan.cpp
17   const char* kDataFolder = "./data" // => "../data"に変更
```
- 以下に示す流れで生成されたdcgan.exeと同じディレクトリ(dcgan/build/Release)に生成されたdataディレクトリ(dcgan/build/data)を入れる。

というわけで流れを示します。

```
$ git clone https://github.com/pytorch/examples.git
$ cd examples/cpp/dcgan
$ ls
CMakeLists.txt  dcgan.cpp  display_samples.py  README.md
$ mkdir build
$ cd build
$ cmake .. -DCMAKE_PREFIX_PATH=C:\libtorch -Ax64 -DCMAKE_BUILD_TYPE=Release
... (長いのでカット)
$ msbuild dcgan.sln /p:Configuration=Release
... (非常に長いのでカット warningがいっぱい出ます)
$ cd Release
$ dcgan
CUDA is available! Training on GPU.
define Generator.
Defined Generator.
Define Discriminator.
Defined Discriminator.
Define MNIST
Defined MNIST
[ 1/30][ 10/938] D_loss: 0.8263 | G_loss: 1.6410
[ 1/30][ 20/938] D_loss: 0.6547 | G_loss: 2.2157
[ 1/30][ 30/938] D_loss: 0.6314 | G_loss: 2.3801
[ 1/30][ 40/938] D_loss: 0.5518 | G_loss: 3.0052
[ 1/30][ 50/938] D_loss: 0.4735 | G_loss: 3.4814
[ 1/30][ 60/938] D_loss: 0.4381 | G_loss: 3.8758
.
.
.
Training complete!
```

# 参考
pytorchのissueを参考にしたのですが、どのissueだったか忘れてしまいました...。
https://github.com/pytorch/pytorch/issues
書類やドキュメントの確認に無駄をなくすようテンプレート化する

## 雛形に時間を喰われていないか

* 真っさらな入力画面を前にすると、やたら構成を考えるのに時間がかかる
* いざ文章レビューを出してみれば、「内容」に対してのレビュー・評価ではなく<br />文章の流れ・体裁に対し「こうすべきでは」と言い合いをしている

時間の無駄。少し時間がかかっても良いのでテンプレート化する。

組織内の標準があればそれでもよいし、無いなら作る。

## 考えられる具体例

github であれば `ISSUE_TEMPLATE`, `PULL_REQUEST_TEMPLATE` がある。

個々人の技量で振れやすい「調査結果」の文面は以下のようになるだろう。

そして、開発者が誰でも参照できるところに貼り「この雛形に従って投稿するように」と促せば良い。

```
## タイトル(ex. 設定値xxx を利用するロジック修正ステップの調査)

### 結論

一言二言で記載する。

ex.) 1 ステップは修正する。1 ステップは削除の方向で検討したい。

### 概要

リストアップ形式で記載する

* ステップ yyy の制御処理を修正する
* ステップ zzz は削除する

### 詳細

> * ステップ yyy の制御処理を修正する

設定値xxx を利用した制御処理をしている為。

修正方法は ... とする。

> * ステップ zzz は削除する

設定値xxx を利用していない。

利用していない = コメントアウトされているのでステップ自体削除する。

### 補足事項

関連の #nnnn は口頭での相談結果、工数の関係上 #mmmm で調査する。
```

## その他

個人的な経験を書くと、開発者 兼 管理者でいる立場の人は

毎回確認するものは「型にハマったもの」で出して貰った方が、頭の切り替え少なくて済みます。

言い方を変えれば 「こういう書き方で出してもらった方がありがたい」 と開発者に伝えれば、

自分の頭にフィットする文章を貰える可能性が高まります。

## 参考文献

* [Gales, Christopher. The Product is Docs: Writing technical documentation in a product development group (p.63). Splunk. Kindle 版.](https://www.amazon.co.jp/Product-Docs-technical-documentation-development-ebook/dp/B078G5PV3Q/)
  * Topics and objectives より
* [Morgan, Kieran. Technical Writing Process: The simple, five-step guide that anyone can use to create technical documents such as user guides, manuals, and procedures . Better On Paper Publications. Kindle 版. ](https://www.amazon.co.jp/dp/B00UA3YX46)
  * Check for templates or style guides より
* [Pringle, Alan S.. Technical Writing 101: A Real-World Guide to Planning and Writing Technical Content . Scriptorium Publishing Services, Inc.. Kindle 版. ](https://www.amazon.co.jp/gp/product/B004NEW1M4/)
  * Template-based authoring より
38日目、Ruby on Railsはじめました。


今日からRuby on Rails編です。
ようやくWebサービスを作れる・・・のかな？ という気がしてきました。

なかなか先が見えてこなくて、モチベーションが下がってきたので、この本を買ってみました。

[【電子版】個人開発がやりたくなる本 \- クリエイター13人の実録エッセイ](https://booth.pm/ja/items/1313332)

経験ゼロから作るとすると、やっぱり３ヶ月くらいはかかるみたいですね。。。
あともうちょいで半分です。ぼちぼちがんばろうと思いました。

さて、昨日の復習です。
RubyⅤ クラスの継承 (20分)
昨日はいまいちよく分かりませんでしたが、今日はなんとなく分かる感じがします。
復習がいい理由がもう１つあって、Progateのレベルがむちゃくちゃ上がる！
特に後半は経験値の割り当てが+200と前半の倍となっており、復習だと１回目の半分以下の時間でクリアできるので、いつのまにめっちゃレベルが上がってびっくりしました！

さて、本題です。

###Railsをはじめる

```
1)rails アプリを作る。
rails new tweet_app

2)rails サーバーを起動する
rails server

3)ブラウザで確認する
localhost:3000
```

###トップページを作る
`rails generate controller home top`

###ビュー、コントローラー、ルーティングを作る

####ビュー（見た目）
`app/views`フォルダ
`rails generate controller home top`→`home`フォルダと`top.html.erb`がつくられる。
`top.html.erb`の中身はHTMLなので、表示したいようにどんどん書いてく。

###コントローラー
ブラウザに返すビューを見つける。
rubyで書いてある。

```ruby

class HomeController < ApplicationController
  def top
  end
end
```

####ルーティング
ブラウザでURLを入力すると、ルーティングがURLを見て、適切なコントローラのアクションを呼び出す。
`config/routes.rb`で定義する。
ルーティングに記述されていないURLはエラーになる。

```
Rails.application.routes.draw do
  get "home/top" => "home#top"
end
```

`get "home/top" => "home#top"` を変更するとルーティングを変更できる。

###新しいページを追加するには
1)ルーティングにコードを書き足す
2)コントローラにコードを書き足す
3)ビューを追加する

###CSSをかく
`rails generate controller home top`実行時に
`app/assets/stylesheets`以下に`home.scss`ができているので、これを編集する。

###画像を追加するには
`public`フォルダに画像を置くと、`/ファイル名` で呼び出せる。

###デフォルトのトップページを変える
シンプルに`"/"`だけで指定する。
`get "/" => "コントローラ名#アクション名"`

###リンクを作る
hrefの中身をルーティングのURL部分とする

###完成！
Webサービスに必要なセットがコマンドひとつで展開される感じなのかな？
このくらいのサイトなら１つづつ手作りした方が早いけど
きっとたくさんページのあるサイトを作るとなるとRailsを使った方がいいんだろうな・・・
だんだんWebサービスが作れそうなきがしてきました！

（所要時間 60分）
CloudRun で Firefox ヘッドレスブラウザを動かしてスクリーンショットを撮る

最近話題の CloudRun で Firefox ヘッドレスブラウザを実行して、スクリーンショットを返すサーバレスを試してみます。なぜ Chrome ではなく Firefox かというと、Web フォント（日本語）の unicode-range がうまく動かないので仕方なく Firefox にしています。Firefox はちゃんと動く。最高。

### Docker

```Dockerfile
FROM selenium/standalone-firefox

WORKDIR /app
ADD /app .

EXPOSE 8000

CMD ["python", "server.py"]
```

`selenium/standalone-firefox` という Firefox が入っている良い感じのコンテナがあるので、これを使います。このコンテナには Python2.7 が入っているので、Python で Web サーバを構築します。僕は Python は初心者です。

### Web サーバ

```server.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import SimpleHTTPServer as s
import BaseHTTPServer as b
import subprocess
class MyHandler(s.SimpleHTTPRequestHandler):
    def do_GET(self):
        self.make_screenshot()
    def make_screenshot(self):
        subprocess.call(['firefox', '-screenshot', '/tmp/screenshot.png', 'http://example.com/'])
        self.send_response(200)
        self.send_header('Content-type', 'image/png')
        self.end_headers()
        self.wfile.write(open('/tmp/screenshot.png', 'rb').read())
host = '0.0.0.0'
port = int(os.environ.get('PORT', 8000))
httpd = b.HTTPServer((host, port), MyHandler)
print('ポート:%s' % port)
httpd.serve_forever()
```

`firefox` に `screenshot` オプションを渡すとスクリーンショットを保存してくれます。便利。あとは CloudRun 実行時に環境変数で提供されるポート番号を利用して Web サーバを起動するだけ。

## CloudRun へデプロイ

```bash
gcloud components install beta
gcloud components update
gcloud auth login
gcloud config set project [PROJECT_NAME]
gcloud builds submit --tag gcr.io/[PROJECT_NAME]/firefox-headless-container
gcloud beta run deploy --image　gcr.io/[PROJECT_NAME]/firefox-headless-container
```

これだけで OK 。非常に簡単。正常にデプロイできれば URL が発行されるので、そこにアクセスするとスクリーンショットの画像が返ってきます。
ハッシュ値を計算して被っていない画像を取得する

参考のは２重ループ回していて万単位の画像群で試すと結構待ったので、もうちょい効率よく。

```python
import hashlib
from glob import glob

fpaths = glob("./imgs/*.png")  # 画像ディレクトリのパス

# ハッシュ値のリストを作成
fmd5 = []
for fpath in fpaths:
    with open(fpath, 'rb') as fin:
        data = fin.read()
        m = hashlib.md5(data)
        fmd5.append(m.hexdigest())

# ハッシュをキー、パスを値にもつ辞書型を作成
dic = {}
for fpath, md in zip(fpaths, fmd5):
    if md not in list(dic.keys()):
        dic[md] = fpath
        
# これが求めたい画像のパスのリスト
list(dic.values())
```

参考
[Pythonで、フォルダ内の重複する画像を自動的に削除する方法](https://utgwkk.hateblo.jp/entry/2014/04/05/235859)
Leetcode #74: Search a 2D Matrix

Use binary search. 

```swift
func searchMatrix(_ matrix: [[Int]], _ target: Int) -> Bool {
    let row = matrix.count
    if row == 0 {
        return false
    }
    let column = matrix.first!.count
    if column == 0 {
        return false
    }
    let ar = matrix.map { $0.first! }
    var start = 0
    var end = row - 1
    if binarySearch(&start, &end, ar, target) {
        return true
    } else {
        if end >= 0 {
            start = 0
            var rowEnd = column - 1
            return binarySearch(&start, &rowEnd, matrix[end], target)
        } else {
            return false
        }
    }
}

private func binarySearch(_ start: inout Int, _ end: inout Int, _ ar: [Int], _ target: Int) -> Bool {
    while start <= end {
        let mid = (start + end) / 2
        if ar[mid] == target {
            return true
        } else if ar[mid] > target {
            end = mid - 1
        } else {
            start = mid + 1
        }
    }
    return false
}
```
`npm publish` するとエラー4048になる

# `npm publish` するとエラー4048になる

npm パッケージをリリースしようと思って、 `npm publish` をしたところ、以下のようなエラーが表示されました。

```bash
$ npm publish
npm ERR! path hogehoge\package.tgz
npm ERR! code EPERM
npm ERR! errno -4048
npm ERR! syscall unlink
npm ERR! Error: EPERM: operation not permitted, unlink 'hogehoge\package.tgz'
npm ERR!  { [Error: EPERM: operation not permitted, unlink 'hogehoge\package.tgz']
npm ERR!   cause:
npm ERR!    { Error: EPERM: operation not permitted, unlink 'hogehoge\package.tgz'
npm ERR!      errno: -4048,
npm ERR!      code: 'EPERM',
npm ERR!      syscall: 'unlink',
npm ERR!      path:
npm ERR!       'hogehoge\\package.tgz' },
npm ERR!   isOperational: true,
npm ERR!   errno: -4048,
npm ERR!   code: 'EPERM',
npm ERR!   syscall: 'unlink',
npm ERR!   path:
npm ERR!    'hogehoge\\package.tgz' }
npm ERR!
npm ERR! Please try running this command again as root/Administrator.
```

npm のバージョンを最新にしてみましたが、効果はなさそうです。

# 原因はログインしていないから

原因を調査したところ、以下のサイトに行きつきました。
https://stackoverflow.com/questions/48964247/nexus-npm-publish-failed-with-error-4048

どうやらnpmへのログインが必要のようです。
当然ですよねｗ すっかり忘れていました。

以下のコマンドでログインします。

```bash
$ npm login
Username: 
Password:
Email: (this IS public) 
```

必要な情報を入力すれば、ログインができます
ログイン後に、 `npm publish` をしたところ、無事に成功しました。


# さいごに
普段あまりしない作業というのは、手順をすぐに忘れてしまうので、将来の自分のためにも、こうやって記事に残すようにします。
letter-spacingを使って文字を両端揃えにする（レスポンシブ対応）

2019年5月4日現在、「CSS　両端揃え」とググるとその方法について紹介したページがいくつも出ます。そこで紹介されている方法は大体次の方法です。

```css:CSS
p {text-align-last: justify;}

もしくは

p {text-align: justify;}
```
けど、これだとChromeやFirefoxでしか適用されない（[text-align-lastのcaniuse](https://caniuse.com/#search=text-align)）。だから次の``text-justify``プロパティも追加する。

```css:CSS
p {
  text-align-last: justify;
  text-justify:inter-ideograph; 
}

もしくは

p {
  text-align: justify;
  text-justify:inter-ideograph; 
}
```
よし、これでクソIEとEdgeにも対応した（[text-justifyのcaniuse](https://caniuse.com/#search=text-justify)）。けど、ここまでのプロパティはすべてSafariに対応していない。何してんだおい。
ということで考え出された荒業がこちら。

```html:HTML
<p>
  <span>ふ</span>
  <span>ざ</span>
  <span>け</span>
  <span>る</span>
  <span>な</span>
</p>
```
```css:CSS
p {
  display: flex;
  justify-content: space-between;
}
```
ふ
ざ
け
る
な

これは文字数が多くなると地獄ですね。とここまで書いて思ったけど、正規表現を使った置換をすれば案外簡単にできるのかな？

とまぁ、僕は新しい方法を提案させていただきます。

##とりあえずコードを
```html:HTML
<p>お試し両端揃え</p>
```
```css:CSS
p {
  font-size: 20px;
  letter-spacing: calc((300px - 20px * 7) / (7 - 1));
  white-space: nowrap;
  width: 300px;
}
```
コードは必要最低限のコードだけ載せています。すべてのコードは[こちら](https://codepen.io/Mryoo/pen/MdgPXe)から。下の画像のようになります。ちゃんと両端揃えになっていますね。
![101527.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358159/44bad190-af6e-3591-52a4-622022cd7631.jpeg)

##仕組み
- ``letter-spacing``はどうやら文字の右側に余白を作るみたいです。``letter-spacing``の値になぜあんな一見複雑な数式を使うのかというと、話はいたって単純。下の画像を見せられて、「グレーの幅の大きさを求めよ」という問題への回答と一緒です。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358159/df8d02fd-e2b9-947a-99cf-b259e11482ad.png)
- ``white-space: nowrap;``をいれないとこうなります。
![101527.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358159/c96b3551-4cfc-2ea5-7763-bf5c7751957f.jpeg)
なぜかというと、「え」の右側にも``letter-spacing``の値分だけスペースができるから。``white-space: nowrap;``を指定することで改行をさせないようにしている。

##注意点
- ``width``や``font-size``は**``px``**や**``vw``**や**``vh``**の方がいいかもしれないです。``rem``や``%``だとうまくいかないかもしれません。
- 文字は**等幅フォント**がいいかもしれません。

##レスポンシブ対応
```html:HTML
<p>お試し両端揃え</p>
```
```css:CSS
p {
  font-size: 5vw;
  letter-spacing: calc((90vw - 5vw * 7) / (7 - 1));
  white-space: nowrap;
  width: 90vw;
  overflow: hidden;
}
```
![1556974597218.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358159/3b31c381-bde7-500a-7418-7ff5cf95777b.gif)
必要最低限のコードのみ載せています。すべてのコードは[こちら](https://codepen.io/Mryoo/pen/VOZqYv)から。``px``の部分を``vw``に変えて、水平スクロールバーが出てしまったから``overflow: hidden;``を指定しただけです。
初心者Pythonでパスワード管理をしよう※脆弱性しかないので使用厳禁

# 背景
親がパスワードを毎回忘れるので毎回リセットするのにいい加減腹がめんどくさいのでパスワード管理プログラムを作った
.exeで実行できるようにしたのでパスワードは実行して呼び出すように指導した
バッチファイルにしといた
.pyファイルいじらせるとめんどいことになるのでいじらせるのは.txtのみにした
#内容
まずカレントディレクトリにpass_word.txtというファイルを作ります
とりあえず例で

```pass_word.txt
※呼び出すキーワードとパスワードの間は:で区切る
mail:mail_pass
google:google_pass
facebook:facebook_pass
```
そして　パスワードを呼び出すときのキーワード : パスワード　という風に(上の例のように)１行ずつ.txtファイルに入力していきます
ここで重要なのは1行ずつで改行するということと、パスワードを呼び出すキーワードとパスワードの間に半角:をいれることです
パスワードを呼び出すときのキーワード、パスワードと:の間に空白を入れても別に問題ないです(正規表現でそれらは除外して認識しています)      
ターミナルで

```
$python pass_mana.py パスワードを呼び出すときのキーワード 
```
と打ち込めばクリップボードにコピーされます

```pass_mana.py
import os,sys,pyperclip,pathlib,re,pprint

def main():
    if len(sys.argv) != 2:sys.exit()
    need_pass = sys.argv[1]
    pass_txt = open('pass_word.txt')
    pass_txt = pass_txt.read()
    pass_txt=pass_txt.strip('※呼び出すキーワードとパスワードの間は:で区切る')
    pass_regex = re.compile(r'\s*(\S*)\s*:\s*(\S*)\s*\n*')
    pass_findall = pass_regex.findall(pass_txt)
    pass_dict = {}
    for pass_t in pass_findall:
        pass_dict.update({pass_t[0]:pass_t[1]})
    if need_pass in pass_dict:pyperclip.copy(pass_dict[need_pass])

if __name__ == '__main__':
    main()
```

#注意
このプログラムは脆弱性しかないので使っちゃダメです