OmniAICreator/Qiita-1.07M huggingface dataset:
WebDAVをnginxだけで作る備忘録

# はじめに

この記事はdebian系列(Ubuntu系列)をベースに解説しています。

WebDAVのメソッドはnginxの標準debパッケージにも搭載されていますが、一部機能のメソッド(PROPFIND,OPTIONS)がなく、一部アプリではうまく動作しなかったりするのでそのメソッドを追加するための記事を書いてます。

※nginx公式のリポジトリを追加していることが前提です。

記事に書いてある＊にはバージョンが入ります。

# ビルド

デフォルトのモジュールには搭載されていないため、モジュールを追加してnginxをビルドをする必要があります。

## ソースコードを入手

aptコマンドでnginxのソースコードを取り寄せます。
ディレクトリは特に問いませんが、```/usr/src/```あたりに置いておくといいでしょう。

```
# apt source nginx
```

取り寄せが終わるとカレントディレクトリにソースコード(```nginx-*.*.*```)が置かれます。

# ビルド依存パッケージのインストール

ソースルートディレクトリの```debian/control```っていうファイルのBuild-dependsに依存パッケージが書かれているのでそれを頼りにインストールします。
なお、今回インストールしたバージョン（1.16.1）の依存パッケージは以下のとおりです。

```
# apt install debhelper dh-systemd dpkg-dev quilt lsb-release libssl-dev libpcre3-dev zlib1g-dev
```

※```build-essential```も入れておくと無難です。

## WebDAV拡張モジュールの取り込み

ソースルートディレクトリで以下のコマンドを実行します。

```
# git clone https://github.com/arut/nginx-dav-ext-module.git
```

そのあと、debパッケージにするために少しだけ内容を変更します。

```bash:debian/rules
# 省略
# 39~41行目付近
config.status.nginx: config.env.nginx
        cd $(BUILDDIR_nginx) && \
        # 最後の方に" --add-module=/path/to/nginx-*.*.*/nginx-dav-ext-module "を追加。
        # ディレクトリは適宜変更。
        CFLAGS="" ./configure --prefix=/etc/nginx ... --add-module=/path/to/nginx-*.*.*/nginx-dav-ext-module
        touch $@

# 44~46行目付近
config.status.nginx_debug: config.env.nginx_debug
        cd $(BUILDDIR_nginx_debug) && \
        # 上と同様のものを追加。
        CFLAGS="" ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx ... --add-module=/path/to/nginx-*.*.*/nginx-dav-ext-module
        touch $@
# (省略)
```

## ビルドタイム

これを実行してあとは待つだけです。

```
# dpkg-buildpackage -uc -b
```

無事に終わるとdebパッケージがソースルートディレクトリの１つ上にできます。

## インストールして確認

あとはできたものをdpkgでインストールするだけです。

```
# dpkg -i nginx_*.*.*_*.deb
```

インストールが終わったら以下のコマンドを実行して確認します。

```
$ nginx -V
```

```configure arguments```に```--with-http_dav_module```と```--add-module=/path/to/nginx-*.*.*/nginx-dav-ext-module```が入っていれば完了です。

# 設定する

大まかな設定は割愛します。任意で変更してください。

```nginx
location / {
  # 必要であれば設定
  # auth_basic "Authorize dialog message";
  # auth_basic_user_file /path/to/.htpasswd;

  # 標準搭載のメソッドと追加モジュール分のメソッドの設定
  dav_methods PUT DELETE MKCOL COPY MOVE;
  dav_ext_methods PROPFIND OPTIONS;

  # ファイル一覧を表示する設定
  autoindex on;
  autoindex_exact_size off;
  autoindex_localtime on;

  # 読み書きの権限設定
  dav_access user:rw group:rw all:r;

  # 一時ファイル・ディレクトリ作成の許可
  client_body_temp_path /var/www/.webdavtmp;
  create_full_put_path on;
}
```

nginx再起動して、おしまい。

# 参考文献

- [Ubuntu (Debian) で nginx に WebDAV拡張モジュール(ngx-dav-ext-module)を組み込むで使ってみる](https://server-setting.info/ubuntu/ubuntu-nginx-webdav-module.html)
- [nginx で WebDAVを使ってファイル共有してみる](https://server-setting.info/centos/nginx-webdav-howto.html)
Colaboratoryを使う上での参考になるサイト


Colabの設定やテクニック
https://medium.com/deep-learning-turkey/google-colab-free-gpu-tutorial-e113627b9f5d

Colabについてのkaggleでの議論
https://www.kaggle.com/getting-started/47096#post271139

GPUの確認
https://qiita.com/sao_rio/items/4ef5604d685f04669f74

!と%の違い
https://stackoverflow.com/questions/48298146/changing-directory-in-google-colab-breaking-out-of-the-python-interpreter

cell magicとline magic
https://dichika.hateblo.jp/entry/20160613/p1


https://electric-blue-industries.com/2019/10/29/deep-learning-google-colab-%E3%83%81%E3%83%BC%E3%83%88%E3%82%B7%E3%83%BC%E3%83%88/

GPUの種類の確認

```
!sudo apt-get install pciutils
!lspci | grep -i nvidia
```
【Kotlin】MyBatisでヒアドキュメント内のPARTITIONを動的に指定する方法

Kotlin × MyBatisでPARTITIONを使ったSelectをしようとしたらハマったのでメモがわりに記事にしました。

# 最初に結論

Kotlin × MyBatisで`@Select`アノテーションなどの中でヒアドキュメントを使用してシングルクォートの付かない`${変数}`を挿入する場合は`${'$'}{変数}`のような形にする。

```kotlin
@Mapper
interface UsersMapper {

    @Select(
        """
            <script>
                SELECT
                    id,
                    name
                FROM users
                PARTITION (${'$'}{targetPartition})
            </script>
        """
    )
    fun getUserList(targetPartition: String): List<User>
}
```

# 起こったこと＆過程
よくあるPARTITIONを指定してデータを引っ張ってくるSelect文を用意しました。

```kotlin
@Mapper
interface UsersMapper {

    @Select(
        """
            <script>
                SELECT
                    id,
                    name
                FROM users
                PARTITION (#{targetPartition})
            </script>
        """
    )
    fun getUserList(targetPartition: String): List<User>
    // targetPartition=p202001
}
```

しかしこれをこのまま実行すると「おいおい、ちゃんとマニュアル読めよ？」と怒られてしまいます。

```
 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''p202001') 
```

実際に実行されたSQL文を確認してみると、どうやら変数`targetPartition`を`#{}`で挿入していたため、シングルクォートがついてしまったようです。

```sql
SELECT id, name FROM users PARTITION (`p202001`);
```

いやぁうっかりうっかり。
[MyBatisの公式ドキュメント](https://mybatis.org/mybatis-3/ja/sqlmap-xml.html)を読むとシングルクォートを付けずに値を挿入するには`${}`を使用するようです。

さてこれで一件解決かと思いきや、今度は構文エラーに…

```kotlin
@Select(
    """
    // ~~~
        PARTITION (${targetPartition}) //構文エラー
        PARTITION (\${targetPartition}) //構文エラー
    // ~~~
    """
)
fun getUserList(targetPartition: String): List<User>
```

どうやらヒアドキュメント（トリプルクォート）の場合は`$`はそのまま使えず、エスケープも効かないらしい。

調べてみると`${'$'}`もしくは`${doller}`というように文字列として`$`を挿入してやればいいようです。
そんなのありか…

```kotlin
@Mapper
interface UsersMapper {

    @Select(
        """
            <script>
                SELECT
                    id,
                    name
                FROM users
                PARTITION (${'$'}{targetPartition})
            </script>
        """
    )
    fun getUserList(targetPartition: String): List<User>
}
```

これで無事SQLを実行することができました。

```sql
SELECT id, name FROM users PARTITION (p202001);
```

## 参考資料

[MyBatis: Mapper XML ファイル](https://mybatis.org/mybatis-3/ja/sqlmap-xml.html)
[Kotlinでヒアドキュメント中の文字をエスケープ](https://www.yo1000.com/kotlin-heredoc-escape/?no-cache=1)
【PHP】PHPの超基礎をここに(パート1)

#PHPの基礎をここに

###昔かじったPHPを完全に忘却したので復習を兼ねてPHPの超基礎

PHPはHTMLの中にぶっこむことができる

```phpkiso.php
<html>
<body>
<?php
echo "Hello world";
?>
</bod>
</html>
```
※メモ※ファイルの最後がPHPのプログラムで終わるときは?>は省略可！

##コメントアウト
```comment.php
<html>
<body>
<!-- HTMLコメント -->
<?php
echo "Hello world";
//一行用
/*  複数行用の
コメント */
?>
</bod>
</html>
```

##文字列の表示
文字列出力の際は"echo"を使う
文字は「'」か「"」で囲む必要がある

```mojiretsu.php
<?php echo 'Hello world' ?>
```

##変数
変数とは、、、一時的に値を保存する箱？的な存在
※$を頭につけて半角英数と「_」を使用して名前をつける
※変数名の頭に数字は使用不可
※変数には「=」を使って値を入れる
※値を入れることを「代入」という

```hensu.php
<?php 
$fruit = 'りんご';
echo $fruit; //「りんご」と出力される
?>
``` 

##配列
```hairetsu.php
<?php 
$vegies = array('たまねぎ', 'ほうれん草', 'じゃがいも');
echo $vegies[0]; //「たまねぎ」と出力される
echo $vegies[2]; //「じゃがいも」と出力される
?>
``` 
0番目があるのがポイント
新規プロジェクトの作成

少なくとも、どんなにunityハジメマシテでも、新規プロジェクト作成は自分でできるようになろう。

---

unityHubを起動する
<img width="34" alt="a1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/e39f35b5-3528-a48c-8b17-314454a810d0.png">←これ
下図のような画面が表示される
<img width="971" alt="a2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/28ad4636-afe0-f10a-e455-babb41415ec1.png">
画面右上の　新規作成　をクリックする
<img width="952" alt="a3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/059b3712-73a9-52fc-7a5e-37b401f1f64d.png">
ウィンドウ上部のunityのバージョンが正しいこと。わからない人は近くの詳しい人に確認する。
保存先は確認しておく。同じ端末を他の子と使っている場合、ちゃんとした場所に保存されているか、自分でも確認をする。ここに書かれていることがわからない場合、近くの詳しい人に確認する。
<img width="849" alt="a4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/cafc4b97-b217-5018-09d5-a1e6ddb3ed86.png">
プロジェクト名は、自分の作品だとわかる名前にすること。
ふあのれせふあのせばのとじりせはちてい゛り　とか
af,weq@[,qrwe:fac:/fill ~-25 ~ ~-25 ~25 ~10 ~25 air 0 replace lava;　とか
デタラメに入力するような幼稚な名称は避けること。
あと日本語だめ、ぜったい。
domino0125とか、zuttomo11とか、日付とか連番など、自分で管理できるもの、あるいは周りの人のルールに従うこと。
<img width="166" alt="a5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/5d67760c-7f64-8a3b-0151-1c91f2e9af48.png">
<img width="149" alt="a6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/798e0d1e-c549-9d65-2b81-c40c821f5ba0.png">
phper用 vscodeでダブルクリックで、$を含んで変数を選択したい

環境 mac

~/Library/Application Support/Code/User/settings.json
を開いて次を追記する。

```
"editor.wordSeparators": "`~!@#%^&*()-=+[{]}\\|;:'\",.<>/?",
```

もしくは、「command + ,」 でsettingを開いて窓に「wordSeparators」と入れて検索し出てきた設定から"$"を抜く。
設定はリセットできるので、うまくやろう。


参考
[Make Visual Studio Code to correctly select PHP variables on double\-click \| Igor Kromin](https://www.igorkromin.net/index.php/2018/04/12/make-visual-studio-code-to-correctly-select-php-variables-on-double-click/)
初めて全力で取り組んだ機械学習コンペを振り返る


#はじめに
先日、とある機械学習コンペに参加した。週末を何度もつぶす程全力でやってみた。その結果、入賞には至らなかったものの上位3%に入ることができ、自信につながった。まだまだコンペ経験が少ないため、今後考えが変わるかもしれないが、まずは現時点でこの経験を振り返り、メモとして残しておく。

#参加の動機
機械学習については本を読んだり動画を見たりして勉強はしているものの、自分のスキルがどの程度か客観的に知りたいと思ったため。

#前提
コンペの内容は詳しくは言えないが、テーブルコンペである。以下の戦闘環境で戦った。

### ハードウェア(1台)
- CPU i7-8700 3.70GHz
- メモリ 16GB
- GPU NVIDIA GetForce GTX 1060 6G

### ソフトウェア
- Windows 10
- Python 3.6 
- scikit-learn 0.21.2
- tensorflow 1.13.2
- keras 2.3.1
- xgboost 0.9
- lightgbm, catboost etc..
- PyCharm(開発環境)

# 振り返り
機械学習手法については素晴らしい本がたくさんあるため、ここでは実際に自分がコンペに取り込んでみて感じた泥臭いことを列挙してみたい。

## 作成したスクリプト
コンペを戦うにあたり特徴選択と予測モデル作成の2つの作業については、汎用性の高いコマンドラインスクリプトを作成し、他(可視化やちょっとした前処理など)は使い捨てのコマンドで対応した。例えば予測モデル作成については、学習アルゴリズムの選択、乱数シード、クロスバリデーション数など可能な限り、引数で指定できるようにした。また、新しいアルゴリズムが追加になっても最小限の修正で追加できる作りとした。これにより、自分のやりたいことをコマンドの引数を変えるだけで変更できたり、バッチでまとめて流したりすることができ、生産性を高めることができたと考えている。

## 再現性
コンペでは入賞して賞金等をもらう場合に、モデルの作成や予測について再現できるスクリプトを提供が義務づけられていることが多い(と思う）。スコアがあがって入賞が見えてきたときに初めて再現方法を調べるようでは、かなりの手戻りになる可能性がある。このため、できるだけ早い段階で再現性を担保する方法を確立しておく必要がある。結果にランダム性が入るアルゴリズムには、"random_state" のようなパラメータがあることが多いので、それを調べて指定する等心掛けた。もっともGPUで計算した場合、固定させることが難しいようだ（今回、GPUはKerasだけの利用だったため、あまり深く調べなかった)。

乱数シードを固定させる対象は以下が考えられる。

- Boruta等の各特徴選択アルゴリズム
- Random ForestやXGBoost等の各機械学習アルゴリズム
- クロスバリデーション時の分割処理

## ログ
ある特徴選択手法の結果を使って、そこそこよい結果が得られたのだが、最初の特徴選択をどうやって作成したか分からなくなり、結局１からやり直したことがあった。こんなことがないよう、各スクリプトではログを残しておくことが重要になる。

以下全てを実装したわけではないが、今振り返ってみると、ログに残すべきものとして以下が考えられる。

- 実行したスクリプトそのもの（これはスクリプトの修正が頻繁にあるため）
- スクリプトへの入力情報。例えば予測モデル作成の場合、以下のものが考えられる。
  - 入力ファイルパス
  - 出力ファイルパス
  - 予測アルゴリズム
  - クロスバリデーションの手法、分割数、評価指標
  - ハイパーパラメータの探索手法、探索範囲など
  - 乱数シード
- スクリプトの実行状況。例えば予測モデル作成の場合、グリッドサーチの途中経過等になる。これは途中でやめてパラメータ探索範囲を見直すかどうか等の判断にも非常に役に立つ。

特徴選択等、他のスクリプトも同様である。なお、ログは1つのファイルである必要はなく、1つの実行あたり1つの出力フォルダ作成し、その下に予測結果も含め、複数の種類のログファイルを出力すれば十分である。

## 時間を有効に使う
特徴選択のBorutaは、コンペのデータでは500イテレーションで丸1日かかった。結果によっては何度かやり直すこともあった。Borutaを何も指定せずに実行するとCPUを占有してしまい他の作業が一切できなくなることがある。このようにCPUを占有する処理の場合、引数が用意されている場合、CPU数を明示的に指定することで、他の作業の余地を残しておく。こうすることでBoruta実行中にも、他の作業(例えば別の特徴選択結果でハイパーパラメータの探索を行うなど)ができ、時間を有効に活用することができる。

##予測アルゴリズムの実行速度を考慮する
今回は複数の予測アルゴリズムの出力結果を組み合わせて、最終的な予測モデルを作成するというアンサンブル学習で精度をあげることができた。アンサンブル学習では、組み合わせるものの多様性が高い程、精度があがるとされている。今回はスクリプトを汎用的に作成し、様々な予測アルゴリズムを追加することができたため、可能な限りのアルゴリズムを組み合わせた。各アルゴリズムの速度について、感覚になるが以下の通りだった。

- LightGBM, DeepLearng(Kearas)はかなり高速であり、他手法が苦戦する中、特徴選択しないデータでもかなり高速であった。
- XGB、CatBoostやExtra Treeもまずまずの速度であった。
- 線形手法(PLSやExtraNet等)は単純なアルゴリズムなためか、比較的速い。
- Support Vector Machine, Random Forestは非常に遅かった。

時間がかかるということは、パラメータ探索の組み合わせが多いと、その組み合わせの分さらに時間を要するということである。このようなことから、特徴選択をせずに使うアルゴリズム、特徴選択をした上で使うアルゴリズムを使い分けた。これによって各予測アルゴリズムの高精度のモデルを効率よく探すことができたと考えている。

## クロスバリデーションを信じる
コンペの終盤、クロスバリデーションのスコアは上がるにもかかわらず、パブリックテストのスコアが上がらないという状態に見舞われた。色々悩んだが、コンペ終了時に公表される全データによるパブリックテストでは、クロスバリデーションとほぼ同じ結果になった。結局のところ、信頼できると思える評価方法を見つけたら、それを信じて精度を上げることに専念することが大切なのだと分かった。

## 見切りをつける
コンペ中は、色々頑張った割に効果がないこともある。例えば今回遺伝的プログラミングによる特徴量生成は全く効果がなかった（やり方の問題かもしれないが）。原因も全く思いつかなかった。こんな時はさっさと見切りをつけて、それまでに効果があったこと（今回でいえばアンサンブル学習）をつきつめてやることも重要だと思う。

# おわりに
振り返ってみると当たり前のことしか書いてない気がするが、これが現在の自分のレベルということだろう。
attr_accessorに関して

# はじめに
Ruby初心者ですが、attr_accsessorの内容が最初イマイチ理解できず。
徐々に理解が出来たので纏めてみました！

※「この表現が変だよ」などあればコメントお願いします。

# attr_accessorとは？
@nameなどのインスタンス変数をクラス外から呼び出し、書き込みを定義するメソッド。

# attr_reader, attr_writerとの違い
attr_reader = 呼び出し専用
attr_writer = 書き込み専用

attr_accessor = 両方の機能を兼ね備えている


# インスタンス変数とは
インスタンスの中で値を保持する為の変数。

例）
user1　= User.new
Userクラスをnewすることでuser1というインスタンスが作られる。
クラスの中で定義されている「@変数名」がインスタンス変数となる。

# 使い方
インスタンス変数の内容を、呼び出しと書き込みの両方を行いたい場合はattr_accessorを選択する。

# 使用例
```ruby

class User
  attr_accessor :name, :age
# attr_accessor :ここにはインスタンス変数名を入れる。（シンボルか文字列で指定）

  def initialize(name,age)
# インスタンス変数に名前と年齢が代入される
    @name = name
    @age = age
  end
end

# user1とuser2のインスタンスを作成
user1 = User.new('ルフィー', 19)
user2 = User.new('ゾロ', 21)

# attr_readerで読み出し(以下attr_readerの内容)
puts user1.name
=> ルフィー
# def name
#   @name ← ('ルフィー')
# end


# attr_readerで読み出し(以下attr_readerの内容)
puts user1.age
=> 19
# def age
#   @age ← (19)
# end


# attr_readerで読み出し(以下attr_readerの内容)
puts user2.name
=> ゾロ
# def name
#   @name ← ('ゾロ')
# end


# attr_readerで読み出し(以下attr_readerの内容)
puts user2.age
=> 21
# def age
#   @age ← (21)
# end


# attr_writerで書き出し(以下attr_writerの内容)
user1.name = 'フランキー'
# フランキーがuser1.nameに代入される

# def name=(値) ← ('フランキー'が引数で渡される)
#   @name ← (インスタンス変数@nameに'フランキー'がセットされる)
# end


# attr_writerで書き出し(以下attr_writerの内容)
user1.age = 36
# 36がuser1.ageに代入される

# def age=(値) ← (36が引数)
#   @age ← (インスタンス変数@ageに36がセットされる)
# end


# user1の内容が変更されている
puts user1.name
=> フランキー
puts user1.age
=> 36
```

# 最後に
Rubyは凄く自由な書き方が出来て面白いと感じます！
（ただ、これが大規模開発には向かないと言われるところなんでしょうか）
PC環境でInference Engine Python APIを使ったOpenVINO

# 概要
[こちら](http://jellyware.jp/openvino/)のサイトにRaspberry Pi と Neural Compute Stick を使ったOpenVINOでのPython APIコードのチュートリアルが書いてありますが、PCのみの環境で行う場合には少し変更や追加が必要なので、そのメモを書きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69327/08be909a-5d24-d4b2-df27-4f881885bd78.png)
画像引用元：[OpenVINO™ でゼロから学ぶディープラーニング推論](http://jellyware.jp/openvino/)


必要なのは以下３つの項目です

>- ターゲットデバイスの変更
>- FP16をFP32へ変更
>- ライブラリ読込みの追加

# ターゲットデバイスの変更

Neural Compute Stickを意味する `MYRAID` から `CPU` に変更するだけ。これは簡単。


```python
# 変更前
plugin = IEPlugin(device="MYRIAD")
```

```python
# 変更後
plugin = IEPlugin(device="CPU")
```

# FP16をFP32へ変更

学習済みモデル（xmlファイルとbinファイル）をFP16からFP32に変更します
例えば、OpenVINO 2019_R3.1用の`face-detection-retail-0004`であれば、以下のサイトのFP32からダウンロードすればOK
[Intel Open Source Technology Center](https://download.01.org/opencv/2019/open_model_zoo/R3/20190905_163000_models_bin/face-detection-retail-0004/)


ちなみに、FP16のままでも動作する場合がありますが、FP32が推奨なので変更した方が良いでしょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69327/30b8cfc7-37a4-65ab-b33c-cfe299daae09.png)
画像引用元：[Intel OpenVINO™ TOOLKIT公式サイト](https://docs.openvinotoolkit.org/latest/_docs_IE_DG_supported_plugins_Supported_Devices.html)


# ライブラリ読込み追加

使用する学習済みモデルにもよりますが、以下のようなエラーが発生する場合があります（顔認識など）

```bash
Traceback (most recent call last):
  File "XXXXXXXX.py", line XXX, in <module>
    exec_net = plugin.load(network=net)
  File "ie_api.pyx", line 547, in openvino.inference_engine.ie_api.IEPlugin.load
  File "ie_api.pyx", line 557, in openvino.inference_engine.ie_api.IEPlugin.load
RuntimeError: Unsupported primitive of type: PriorBoxClustered name: fc7_mbox_priorbox
```

対応としてCPU Extensionsライブラリ読込みの追加が必要です。
OSやCPUでパスやファイル名が異なるので、色々試してみて下さい。


## Windows10(Intel Coreプロセッサ)の例

```python
# ターゲットデバイス指定の下に追加
plugin.add_cpu_extension("C:/Program Files (x86)/IntelSWTools/openvino/deployment_tools/inference_engine/bin/intel64/Release/cpu_extension_avx2.dll")
```

※上記でダメな場合は `cpu_extension.dll` を検索してフルパスで指定してみてください

## Linux(Intel Atomプロセッサ)の例

```python
# ターゲットデバイス指定の下に追加
plugin.add_cpu_extension('/opt/intel/openvino/deployment_tools/inference_engine/lib/intel64/libcpu_extension_sse4.so')
```

※Intel Coreプロセッサの場合は `libcpu_extension_avx2.so` に置き換えてみて下さい

## Macの例

```python
# ターゲットデバイス指定の下に追加
plugin.add_cpu_extension('/opt/intel/openvino/deployment_tools/inference_engine/lib/intel64/libcpu_extension.dylib')
```

これでPCさえあれば、無料でディープラーニング推論が出来ますね！　では、また。
エンジニア初心者が、エンジニアになって感じたメリット

## エンジニア初心者が、エンジニアになって感じたメリット

エンジニアとして働く一般的なメリットとして、
- ***働き方が柔軟***
- ***手に職がつく***

等が一般的な挙げられると思います。

これら以外に自分が感じた、エンジニアとして働く意外なメリットを今回は記事にしていきます。

## 物事の取捨選択が圧倒的に上手になる。

前回の記事でも書きましたが、([要件定義初心者のための要件定義指南](https://qiita.com/k941226/items/c0f287eb340309597659))
仕事中
- `目的`
- `目標`
- `手段`

の***３点セット***(以下３点セットと呼びます)を常に意識するため、私生活でもこの3点セットを自然と意識するようになります。

僕の現在の私生活における3点セットを定義すると
- `目的` => お金持ちになりたい！(余裕を持った生活がしたい。ある程度選択できる生活を送りたい)
- `目標` => 自分のできることを増やす。経験を積む。
- `手段` => 1日少しでもプログラミングに触れる。仕事では、コーディング限らず幅広く挑戦する。

という感じです。

このようなある程度の***軸***に沿って生活していると、以下のような場面で自分を客観的に見ることができるようになります。

- 暇だからゲームしよう
=> ストレス発散になるのならやる。そうでないのなら、パソコンを少しでも触っていた方が後々(将来的に)自分が楽になりそう。
- 飲み会に誘われた
=> 飲み会に時間を使って、自分に`+ の変化` (モチベーションが上がるなど) があるのなら行く。`-` or `+ - 0` だと少しでも思ったら行かない。

エンジニアとして働く前と比較して、圧倒的に***意図を持って時間を使う***ことができるようになりました。

ここがエンジニアとして働き始めて自分が感じた、***一番の変化で、一番のメリット***です。

独り言のような記事でしたが、以上でこちらの記事を締めくくります。

ご閲覧ありがとうございました。
deno v0.31.0の変更点

## 概要

https://github.com/denoland/deno/releases/tag/v0.31.0

denoのv0.31.0がリリースされたため、変更点をまとめます。

## 新機能

### denoでシグナルハンドリングができるようになりました

#### Promise API

```typescript
Deno.signal(Deno.Signal.SIGINT)
  .then(handleSIGINT);
```

#### Stream API

```typescript
for await (const _ of Deno.signal(Deno.Signal.SIGINT)) {
  handleSIGINT();
}
```

`dispose`メソッドを呼ぶと、ストリームを破棄できます。

```typescript
const stream = Deno.signal(Deno.Signal.SIGINT);

setTimeout(() => stream.dispose(), 2000);

for await (const _ of stream) {
  handleSIGINT();
}
```

#### 参考

https://github.com/denoland/deno/pull/3757

## 主要な変更点

### TCP/TLS接続に関するAPIのリネーム・型定義の変更

以下の関数がリネームされました。

- `Deno.dial` => `Deno.connect`
- `Deno.dialTLS` => `Deno.connectTLS`

#### `Deno.Conn`interfaceの変更点

`Deno.Conn`は`Deno.connect/connectTLS`から返却されるデータ型です。

`localAddr`及び`remoteAddr`プロパティが文字列から`Deno.Addr`型へ変更されています。

```typescript
interface Addr {
  hostname: string;
  port: number;
  transport: "tcp";
}
```

#### `Deno.Listener`interfaceの変更点

`Deno.Listener`は`Deno.listen/listenTLS`から返却されるデータ型です。

`addr`プロパティが関数から`Addr`型のプロパティへ変更されています。

#### 参考

https://github.com/denoland/deno/pull/3710
https://github.com/denoland/deno/pull/3709

### `Deno.open`にオブジェクトを渡せるようになりました

v0.30.0以前では下記のように文字列で指定していました。

```typescript:v0.30.0
const file = await Deno.open('hoge.txt', 'w');
```

v0.31.0以降は、オブジェクトを渡すことで挙動を制御できます。

```typescript:v0.31.0
const file = await Deno.open('hoge.txt', {
  write: true,
  truncate: true,
  create: true
});
```

https://github.com/denoland/deno/pull/3119

## その他の変更点

- (`std/endogin/yaml`)`stringify`関数の型定義の修正
  - 第2引数の`sortKeys`オプションの型定義が明確化されました。
  - https://github.com/denoland/deno/pull/3708
SereneLinuxに日本語入力システムを導入する

##もくじ
1. SereneLinuxとは
2. 日本語入力システムの導入
3. さいごに

##1.SereneLinuxとは

Ubuntu派生のLinuxディストリビューションです。
なんと作者は日本人の学生です！
実は私もSereneLinuxの開発チームに所属しております。皆さん凄い人ばかりでつよいを通り越して皆さん怖いです...
公式サイトはこちらです https://serenelinux.com

##2.日本語入力システムの導入

ここから本題です！
まず、SereneLinuxではGUIを用いて簡単にソフトウェアの導入が可能となっております
それがこちらです！![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350994/7fd0b8c9-b26b-690c-9007-cba8feb36b29.png)
**SereneStartdash**
こちらを使っていきます。
デスクトップ上のアイコンをダブルクリックしてください。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350994/31b21738-f81d-e157-5a0c-abbba7a9745e.png)
パスワードが求められるので自分のパスワードを入力してください。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350994/4c60af54-0612-57bb-82b0-baa07298c387.png)
起動したらまず「アップグレード」をクリックしてください。

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350994/a629821e-384e-c5b0-8cf9-d7d02d1b1fa0.png)
少々お待ちください...

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350994/480531bb-78db-14ac-db20-5d86e6076e96.png)
パッケージの最新化が完了したらはじめの画面に戻ります。
次は「追加と削除」をクリックしてください。

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350994/4dc7389f-8e45-5fde-e0a9-b4010fd83b02.png)
確認画面が出てきますので「読み込み開始」をクリックしてください。

![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350994/fbd23371-28c2-8fd2-11b6-594650148c97.png)
はい、こちらがインストール可能なソフトウェアとなっております。
沢山ありますが、ここの中から「日本語入力システム」を選択し"OK"をクリックしてください。

![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350994/19cc061d-6e6b-43db-7d58-f5835207a548.png)
少々お待ちください。

![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350994/242f1096-af2b-7099-99bd-9d989898c515.png)
少し怖いですが前に進むしかありません！
「続行する」をクリックしてください。

![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350994/397b6a2e-62e4-bf2d-f373-cad9eb22f7da.png)
インストール中です...

![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350994/d9d81835-543e-9f28-41c0-a875fac53e2f.png)
完了しました。"OK"をクリックして終了してください。

これで日本語入力ができるようになっているはずです。
もし出来ない場合は一度ログアウト後再度ログインをお願いします。

ご不明な点がございましたらこちらまでご連絡をお願いします。
https://twitter.com/Fascode_SPT
2019 Data Science Bowlに参戦してみた

Kaggleに初参戦してみたのでその感想をのこします。

#経緯
- (2018/10) DeepLearningをやってみたくて統計解析や機械学習を書籍やYoutubeで勉強。
- (2019/01) 仕事でPythonに初めて触れ、言語仕様を一気に覚えた。
- (2019/10) JDLA G検定 2019#3合格。さいよいよ実践だ。
- (2019/11) Kaggleのtutorial(Titanic)で練習。
- (2019/12) 2019 Data Science Bowlにエントリ。Webを見てると、Kaggleはすぐにでも参戦したほうが良いとの勧めが多かったので、簡単そうなTableコンペに初エントリ。

#結果
2184/3497。まあまた、こんなもんでしょ。
![jyuni.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490533/aa714d8a-24c7-e1e3-8fc9-526074880989.png)

#感想
- 最初は**いろんな人のコードが見れて感動**。例えばランダムフォレストで特徴量の重要度を測定し、重要度の低い特徴量を削減する手法なんかはすごいなと。（でも、あとで一般的な手法なんだと本で知りました:open_mouth:
- Kaggleが無償の実行環境(カーネル)を提供してて感激。またGCP使っている人も多いみたいで、**クラウドの時代なんだな**と実感。
- いろんな手法があるようだがだが、このコンペでは**XGBoost**に絞って使いかたを覚えることに。他の手法はまた次のコンペで。
- ハイパーパラメータのチューニングでは最初はグリッドサーチを使っていたが、**BayesianOptimization**が人気のようだったのでこちらを使用。
- KFoldでは**StratifiedKFold**なるものがあることを知り、こちらを使用
- 今回は正解率グループ(1~4)を予想するコンペで、最初はXGBoostのクラス分類で予想していたが、Discussion見てると回帰で予測し、適当な閾値により正解率グループに変換したほうが良いとのこと。やってみると確かにテストデータによる正解率は上昇。ちなみに閾値きめにはsp.optimizeの'nelder-mead'を使用。ここは達人コードを流用させてもらいました。
- 入力データは自分なりに工夫して選定したのだが、結果は全くダメ。公開されてる達人のコードを見ると、どうやら多数の入力データをやみくもに与えて、あとは決定木に頑張らせるという戦法の様子。無駄に見える入力を減らしたら成績が落ちるとのコメントが上がっていたが、そこは達人もなぜだがよくわからないとのこと。なるほど、**下手に人間が考えるよりもコンピュータのほうが賢い**ということね。
- やり始めるうちにハイパーパラメータのチューニングにはまってしまう。常時カーネルを実行していないと損した気分に。カーネルの制限で１時間でセッションが切れてしまうのだが、コミットの場合は８時間まで実行可能なので、毎日就寝前と、会社行く前はコミット（ハイパーパラメータ探索実行）。寝不足が続き日中はまぶたが頻繁に痙攣する始末。知らないうちに**Kaggle中毒**になってました:fearful:。参加目的(=機械学習を楽しむ)を思い出すことで中毒から逃れることができました。
- 終了時はものすごい解放感でした:relaxed:


#学んだこと
- 以下のステップの**手戻りを少なく**しないといくら時間があっても足りなくなってしまう。今回は何度も手戻りしてしまった:cry:
    1. 入力の決定
    2. 訓練データの評価方法の決定
    3. チューニングするハイパーパラメータの決定
    4. ハイパーパラメータの範囲決定→徐々に範囲を絞っていく→決定
- **評価方法は非常に重要**。物差しがくるってるとどうにもなりません。実際PrivateScoreとPublicScoreには結構差が出てました。PublicScoreでTopだったチームもPrivateScoreでは大きく順位を落としており、PublicScoreに最適化してしまっていたんでしょうね。<img width="500" alt="aaa.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490533/632df15b-8334-a3bf-0cd3-c170fcd11596.png">

#次の目標
- 特徴量エンジニアリングをちゃんと勉強する(OneHotEncodingとか..)
- 他手法(DeepLearningとかCNNとか)を実践してみる
- 画像認識、自然言語処理、時系列データのコンペに参加する（機械学習を一通りできるようになるため）
- メダルを取る

#これからKaggleを始める人へのメッセージ
- :grin:やっぱり実践するのは楽しい！
- :grin:理論的な知識がなくても十分楽しめます
- :grin:Discussionとかコードとか学びが非常に多い
- :grin:実行環境はKaggleが無償で提供してくれるのでWebブラウザさえあれば参加可能。環境構築にはまることがない！
- :grin:チューニング作業は泥臭くて心が折れそうになるのでけど、順位が出たり、皆のDiscussionを見てるとモチベーションを保ちやすい
- :hushed:Kaggle中毒には気を付けて！私は苦しかったです。
【gon】jsでRails変数を取得する


`Railsでjsライブラリを使うときに楽にRailsで定義した変数をJavaScriptに渡したい！楽したい！`

# プログラマ三大美徳
**1.怠慢(Laziness)**
**2.短気(Impatience)**
**3.傲慢(Hubris)**


まさにこれですね。

# 何を使うか?

RailsといえばGemですね。[gon]というgemです。
https://github.com/gazay/gon

#インストール

Gemfileに記載

```ruby:Gemfile
gem 'gon'
```

ターミナルからインストール

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

読み込み設定

```ruby:application.html.erb
<%= include_gon %>
<%= javascript_include_tag "application" %>
```


# 使ってみる

```ruby:****.controller.rb
gon.user_name = 'my name is imaizumi'
```

```****.js
console.log(gon.user_name)
```

<img width="1139" alt="スクリーンショット 2020-01-25 21.11.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425644/b3a7f44b-32fb-af56-cce9-ceb4748b708c.png">

バッチリ変数を渡せました:yum:
正規表現マッチ方法

# 正規表現マッチ方法

## Pythonでの正規表現マッチ方法のメモ

+ 1 `import re` で正規表現モジュールをインポートする。
***

+ 2 `re.compile()`関数を呼び出しRegexオブジェクトを生成する(raw文字列を使う)。
例：`phone_num_regex = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')`
***
+ 3 Regexオブジェクトの`search()`メソッドに、検索対象の文字列を渡すと、Matchオブジェクトを返す。
例：`mo = phone_num_regex.search('私の電話番号は415-555-4242です。')`
`mo`はMatching objectの意
***
+ 4 Matchオブジェクトの`group()`メソッドを呼び出し、実際にマッチした文字列を取得する。
例：`print('電話番号が見つかりました: ' + mo.group())`
→電話番号が見つかりました: 415-555-4242
***

### 一般的な文字集合を表す短縮形
| 短縮形 | 意味| 
|:-----------|:------------|
| \d       |       0~9の数字 |
| \D     |      0~9の数字以外|
| \w       |        文字、数字、下線(単語wordのw) |
| \W        |          文字、数字、下線以外 |
| \s       |       スペース、タブ、改行(空白spaceのs) |
| \S    |     スペース、タブ、改行以外 |

*** 
### 正規表現に用いる記号のまとめ

+ ?は、直前のグループの0回か1回の出現にマッチする。
+ *は、直前のグループの0回以上の出現にマッチする。
+ +は、直前のグループの1回以上の出現にマッチする。
+ {n}は、直前のグループのn回の出現にマッチする。
+ {n,}は、直前のグループのn回以上の出現にマッチする。
+ {,m}は、直前のグループの0~m回の出現にマッチする。
+ {n,m}は、直前のグループのn~m回の出現にマッチする。
+ {n,m}?, *?, +?は、直前のグループの非貪欲マッチを行う。
+ ^spamは、「spam」から始まる文字列とマッチする。
+ spam$は、「spam」で終わる文字列とマッチする。
+ .は、改行文字以外の任意の1文字とマッチする。
+ \d, \w, \sは、それぞれ、数字、単語を構成する文字、空白文字にマッチする。
+ \D, \W, \Sは、それぞれ、数字、単語を構成する文字、空白文字以外の文字にマッチする。
+ [abc]は、角カッコの中の任意の1文字にマッチする。
+ [^abc]は、角カッコの文字以外の任意の1文字にマッチする。
js if条件判定 早見表


```javascript
// 値
var v;
var v = '';
var v = 0;
var v = '0';
var v = null;
var v = 'null';
var v = undefined;
var v = 'undefined';
var v = [];

// console
console.log('v:' + v);
```


#条件が空文字

| 値 | console | if(v) | if(v == '') | if(v === '') | if(!v) | if(v != '') | if(v !== '') |
|:-----------------|:---|:---:|:---:|:---:|:---:|:---:|:---:|
| v | value:undefined | false | false | false | true| true | true |
| v = '' | value: | false | true | true | true | false | false |
| v = 0 | value:0 | false | true | false | true | false | true |
| v = '0' | value:0 | true | false | false | false | true | true |
| v = null | value:null | false | false | false | true | true | true |
| v = 'null' | value:null | true | false | false | false | true | true |
| v = undefined | value:undefined | false | false | false | true | true | true |
| v = 'undefined' | value:undefined | true | false | false | false | true | true |
| v = [] | value: | true | true | false | false | false | true |

#条件がnull
| 値 | console | if(v == null) | if(v === null) | if(v != null) | if(v !== null) |
|:-----------------|:---|:---:|:---:|:---:|:---:|
| v | value:undefined | true | false | false | true |
| v = '' | value: | false | false | true | true |
| v = 0 | value:0 | false | false | true | true |
| v = '0' | value:0 | false | false | true | true |
| v = null | value:null | true | true | false | false |
| v = 'null' | value:null | false | false | true | true |
| v = undefined | value:undefined | true | false | false | true |
| v = 'undefined' | value:undefined | false | false | true | true |
| v = [] | value: | false | false | true | true |

#条件がundefined
| 値 | console | if(v == undefined) | if(v === undefined) | if(v != undefined) | if(v !== undefined) |
|:-----------------|:---|:---:|:---:|:---:|:---:|
| v | value:undefined | true | true | false | false |
| v = '' | value: | false | false | true | true |
| v = 0 | value:0 | false | false | true | true |
| v = '0' | value:0 | false | false | true | true |
| v = null | value:null | true | false | false | true |
| v = 'null' | value:null | false | false | true | true |
| v = undefined | value:undefined | true | true | false | false |
| v = 'undefined' | value:undefined | false | false | true | true |
| v = [] | value: | false | false | true | true |
【フロントエンドエンジニア】プルリク前の確認事項（初心者向け）

#この記事を読むメリット
初めてのgithubでのプルリク（コードレビュー）していただく際に最低限チェックしておくべきことを大まかに知る事ができる。

```
レビュワーの方々の時間を必要以上に奪わず、自分の生産性も上がるはず！
```  


#目的

`作業時間を短縮する`、`コードを見やすく簡潔にする`、`生産性をあげる`

制作物の見た目を整えること"だけ"に目を向けていると、サイトが重くなったり、わかりずらく保守運用のしづらいコードを書いてしまうことになります。（自分がそうでした、、、）

今回は初めてのコードレビューをいただいた自分が最低限意識しておいた方がいいなと感じたものをメモとして残します。
足らないところがありましたら教えていただけますと幸いですmm

##コード記述において留意すること
###1. 社内のコーディング規約をしっかり確認
ここが一番大事な基準になると思うのでしっかり確認しましょう
自分は見落としが多々あり余計な時間を使ってしまいました
###2. 余計なタグが記述されていないか
余計なタグがあるとコード量が増え読みにくくなる上、サイトパフォーマンスが落ちるのでなるべく簡潔に描きましょう。
特にdivタグ（DIV病）には気をつけましょう
[「DIV病」とは](https://tenshoku.mynavi.jp/it-engineer/knowhow/dictionary/07
)
###3. 適切なtype属性を指定する
例えばbuttonを使う場合、type属性には「submit」がデフォルト設定されています
ボタンとして使用したい場合は

```qiita.scss
<button type="button">
    <span>
        ボタンだよ
    </span>
</button>
```
このようにしてあげましょう。
###4.入れ子関係を確認
「フレージングコンテンツ（button）の中に、ヘッディングコンテンツ（h2）を含めることはできない」などです。
[入れ子関係に悩んだときの秘密兵器です](https://yoshikawaweb.com/element/)
###5.開発用コメントは消す
開発中のメモ書きは至る所にあると思うのでプルリク前に不要なものは削除しときましょう
###6.省略できる記述は省略する(scss)

```qiita.scss
&.btn::after {
        content: '◯';
  は
  &.btn {
    &::after {
        content: '◯';
    }
}
```
このように書く事ができます。
また、同じタグ内のクラス名の重複なども必要なければ消しときましょう
###7.クラスは保守運用しやすい命名をする
今後デザインが変更される可能性なども踏まえて、わかりやすいかつ汎用性のある命名にしましょう。タグ名などでの命名は用途が限定されてしまうため好ましくないです
###8.影響範囲を考える
サイトが大きくなるほど1つの変更での影響範囲が大きくなる可能性があるので、コードを追加する際は常にどこまで影響範囲があるのか意識しましょう（していきます）
###9.タイプミスを確認
タグのとじ忘れ、スペルミスなどサイトの崩れに繋がるので確認しましょう
##プルリク直前に留意すること
###自身がどこまでテストをして問題ないと判断したのか伝える
影響範囲の確認や成果物のデザインカンプ等でレビュワーにゴールを示す
（◯◯部分はバックエンドの処理に依存するので今回のプルリクでは範囲外など）
###ページ全体に崩れ・誤字がないか確認
レビュワーの方はデバッガーやテスターではないので基本的には自分が最終確認者くらいの気持ちでいましょう（います）

全く案件を把握していない人間にもわかるように自分の成果物を説明できる状態を目指しましょう
git cloneでエラーが出た時の備忘録

#はじめに
ローカルにリポジトリをcloneしようとしたら、SSH設定ができていなかった人です。
忘れないうちに、SSH設定を備忘録として書こうと思いました。



##問題のエラー
```
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
```
SSHkeyの設定をしていないのが問題らしいです。
すみません。。。。


##SSHkeyの設定
ターミナルを開いて下記のコマンドを実行

```
$ cd .ssh
$ ls ~/.ssh

known_hosts
```

なにもないですね、はい。作りましょう。

同じ場所で下記コマンドを実行

```
＄ ssh-keygen
$ github　#任意の名前（今回はgithubのSSHKeyなのでgithubにしてます)
Enter passphrase (empty for no passphrase): 　#エンター
Enter same passphrase again:　　　　　　　　　　 #エンター

Your identification has been saved in /Users/yourname/.ssh/github. #秘密鍵できた
Your public key has been saved in /Users/yourname/.ssh/github.pub. #公開鍵できた

```

公開鍵と秘密鍵ができました。
鍵についてはググってください。

公開鍵のファイルをみたいので下記コマンドを実行

```
$ cat github.pub
```

catした公開鍵の内容を`ssh`からコピーします。

[github](https://github.com/)に移動し、[settings]→[SSH and GPG keys]をみます。


<img width="796" alt="スクリーンショット 2020-01-25 20.50.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542365/49e7284d-c9ea-8bb0-f08d-2db362c314d9.png">

[newSSHkey]をクリックします。


<img width="754" alt="スクリーンショット 2020-01-25 20.51.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542365/5805536c-162a-6896-3480-9583a402cbc0.png">

`Title`は任意でわかりやすいものを。
`Key`に先ほどコピーした公開鍵の内容をペーストしてください。



<img width="744" alt="スクリーンショット 2020-01-25 20.52.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542365/a33c1bdc-13c6-87ef-050c-60e5d281a364.png">

はい、keyの設定ができました。


ターミナルに戻り、下記コマンドを実行

```
$ vim config
#下記の内容を書き込む
Host github.com
        Hostname        github.com
        IdentityFile ~/.ssh/github

#保存して。。。

$ chmod 600 * 　#権限変更
```


はい、完了です。
あとはローカルで任意な場所に`git clone`をすればcloneできます。




#まとめ
なぜ今までSSHの設定をしていなかったのか...
また一つ賢くなりました。
[adachinさん](https://twitter.com/adachin0817)に教えていただきました。
ありがとうございます:sob::pray:
docker-compose upを用いてDockerコンテナ上でDjangoを起動する

#はじめに
docker-composeを用いてDockerコンテナ上でDjangoを起動させます。Macを使用します。

#docker-composeを使う理由
Docknizeされたアプリケーションでは、データベースやミドルウェアのコンテナを分け、複数のコンテナでアプリケーションを構成することがあります。
それぞれのコンテナでDocker runを実行するのは面倒です。その際、docker-composeを用いると複数のコンテナを一つのコマンドで制御することが可能となります。
docker-composeはコンテナの振る舞いをdocker-compose.ymlに記載し制御します。


機能毎にコンテナを分ける構成はAWSのチュートリアルでも紹介されておりマイクロサービスと呼ばれています。
マイクロサービスを意識した構成の利点としてはアプリケーションの開発やテストが機能ごとの小さな単位で実施できる事です。
また、各コンテナを疎結合として設計すると機能毎に独立した開発ができるため、他チームの作業を意識することなく開発、デプロイ、スケールさせることが可能です。
私の経験したスタートアップの開発でも、マイクロサービスを意識した設計をしたことで、並行した開発や小さな機能単位での検証や、テストができ便利でした。

本記事はDjangoアプリを[Docker上に構築しAWS Fargateにデプロイする](https://qiita.com/keita_gawahara/items/66e58a6eed5c0c5f31d2)プロジェクトの一部です。


#Dcokerfileの作成
下準備として、Pipenvを用いて仮想環境にDjangoをインストールしてください。
詳細手順については別に記事を書いているのでリンクを参照してください。
https://qiita.com/keita_gawahara/items/487a635d226fb0705b13

プロジェクトのルートフォルダにDockerfileを作成します。

```
$ touch Dockerfile
```

Dockerfileに以下の内容を追記します。

```
FROM python:3.7-slim

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

WORKDIR /

COPY Pipfile Pipfile.lock /
RUN pip install pipenv && pipenv install --system

COPY . /
```

docker buildコマンドでDockerfileをビルドします。

```
$ docker build .
Sending build context to Docker daemon  155.1kB
...
Step 7/7 : COPY . /
 ---> d239897dhfii9u”
Successfully built d26473003af
```

```
$touch docker-compose.yml
```

docker-compose.ymlに以下の内容を追記します。

```
version: '3.7'

services:
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    ports:
      - 8000:8000
```

docker-compose up　コマンドを用いてコンテナを起動します。

```
$ docker-compose up
Creating network...
...
web_1  | System check identified no issues (0 silenced).
web_1  | July 13, 2019 - 16:47:03
web_1  | Django version 2.2.3, using settings 'hello_project.settings'
web_1  | Starting development server at http://0.0.0.0:8000/
web_1  | Quit the server with CONTROL-C.
```

http://127.0.0.1:8000 をブラウザで表示するとDjango welcome pageが表示されました。これでDocker上にDjangoを起動することができました。

CONTROL-Cで終了させたあとdocker-compose downを用いてコンテナを完全に停止させます。

```
$ docker-compose down
```
初心者によるプログラミング学習ログ 220日目

#100日チャレンジの220日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

220日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>220日目<br>・Vue.jsでアプリ作成講座<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1220798525253926913?ref_src=twsrc%5Etfw">January 24, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
SPA入門色々(Vue.js/Blazor/React)

# 概要
SPA(Single Page Application)という技術があることを知り、フロントエンドフレームワークを触ってみるいい機会になるのでないかと思い、Vue.js/Blazor/Reactをまとめて触ってみた。
SPAのルータのページ切り替えを見て従来のiframeや生のJavaScriptとできることがどのように違うのかということも疑問に思ったので同じようなこちらでも同じような感じで実装を試みた。

# 作ったSPAの仕様
* 上部にメニューバー
* Home/Counter/Todoの独立したWebアプリをコンポーネントとして所持。
	+ Home
		- 別のコンポーネントを読み込んで文字を表示するだけなアプリ。
	+ Counter
		- Blazorの実行サンプルに付いてきたカウンターアプリ。
	+ Todo
		- [Vue.jsミニハンズオン（TODOリスト作成）](https://qiita.com/moonglows76/items/358ef3cd1566c38ece3a)を8割位実装したTodoアプリ。

# 成果物
[Vue.js](https://spa-vue-js.web.app) | [Blazor](https://spa-blazor.web.app) | [React](https://spa-reacts.web.app) | [iframe](https://spa-iframe.web.app) | [Vanilla-JS](https://spa-vanilla-js.web.app)
[ソースとか(GitHub)](https://github.com/yosgspec/SPA-Test)

# 感じたメリット・デメリット
## SPA全体
### メリット
* 本来サーバーサイドで受け持っていたような大幅なhtmlの書き換えが簡単にできる。
* htmlを分割して部品化できる。
* 単一htmlとしてシームレスにページ切り替えられる。

### デメリット
* フレームワークありきな存在であること。
* 読み込み時に時間がかかりがち。
* サーバーありきな存在なので気軽に公開しにくい。

## Vue.js
### メリット
* 本来のhtmlに近い書き方でhtmlを複数ファイルに分割できる(.vue)。
* 変数をフォームとバインド(同期)できる。
* v-for\v-ifでタグをループできる。
* CSSをコンポーネントに閉じ込めることができる。
* vue-cliがあれこれ揃えてくれるのでセットアップが簡単。
* 地味にラップされてるWebStorage。

### デメリット
* ルーターの設定が少し煩雑。
* exportするオブジェクトの構成が少し煩雑。

## Blazor
### メリット
* C#だけでほぼ完結して処理を書くことができる。
* 本来のhtmlに近い書き方でhtmlを複数ファイルに分割できる(.razor)。
* 変数をフォームとバインド(同期)できる。
* @for\@ifでタグをループできる。
* ルーターの設定が容易。
* イベントハンドラの呼び出しが素直。
* 他のコンポーネントを呼びだすためのimportが不要。

### デメリット
* まだリリース前。
* ページを開いた時の読み込みが遅い。
* @がゲシュタルト崩壊する。
* DOM由来のAPIを扱うのが面倒。
* 変数バインドと@onchangeを同時に使うことができない。
* CSSに対するサポートがない。
* ライフサイクルが少し心もとない?

## React
### メリット
* あくまでもJavaScriptが主体となっている。

### デメリット
* htmlじゃないhtml。
* htmlとして書くとJSXの形式が直感的じゃない。
* フォームと変数のバインドに癖がある。
* stateの更新が手間。
* 必要なプラグインは基本的物でも各自そろえる必要がある。
* CSSの扱いに癖がある(スコープ化するのも手間っぽい)。
* 専用のループ構文は存在しない。

## iframe
### メリット
* フレームワークが不要(htmlとJavaScriptの知識だけで良い)。
* いにしえの枯れた技術。
* 適当なホームページスペースに上げても動く。

### デメリット
* そもそも、SPAではない。
* htmlが独立しておりそれぞれの連携が面倒。
* URLが項目ごとに変わらない。
* 各フレームのサイズ調整が困難。
* フォームと変数のバインドとかはない。

## 生JavaScript
### メリット
* あるかな?

### デメリット
* 生成した要素の状態管理が絶望的。
* 再レンダリングが困難

# まとめ
触り始めたばかりの素人の感覚としてはReactよりもVue.jsが触りやすいもののように思えた。
アニメーションを付けたりする段階まで行くとまた印象が変わってくるのかもしれない。
Blazorはwasmというものの可能性を感じるものだと感じた。
また、全体的な構成がVue.jsと似ており、触りやすいような印象を受けた。
ちなみにAngularは触ろうとしたけど面倒くさくなって投げた(情報量少なくないですか…?)
なぜバブルソートは$O(N^2)$なのか

ほぼ自分用の備忘録
バブルソート自体の説明は省きます。
詳しく知りたい方は以下のリンクから飛んでください

引用：[バブルソート](http://blog.livedoor.jp/kazoo04/archives/50397634.html)


## 質問
N個の入力が与えられた時、N個の探索→(N - 1)この探索→(N - 2)この探索→・・・と探索をすることはよくある。

例えば、N = 10の時
$10+9+8+7+6+5+4+3+2+1 = 45$
より45回の計算回数であることがわかる。

では、この計算量はすぐにわかるだろうか？

## 答え
結果から言うとタイトルの通り$O(N^2)$になる。シンプルに考えると$O(N^2)$ならNが10の時100にならなくてはいけない気がするので紐解いていく


## 等比数列の和の公式
今回扱う探索の回数は初項N、公比-1の等比数列であることがわかる。
その為、有名な公式を使うとすぐにわかる。
式は以下となる

```math
\begin{align}
(N-1) + (N-2) + ・・・ + 2 + 1 &= \sum_{i=1}^{n-1} i \\
                           &=\frac{n(n-1)}{2} \\
                           &= \frac{n^2-n}{2}

\end{align}
```

以上より$O(N^2)$であることがわかる
目的のパスでコマンドプロンプトを開く方法

#概要
Windowsの操作に不慣れな方でも目的のパスでコマンドプロンプトを開いてもらえます。
コマンドプロンプトで`cd`してもらわなくて済みます。
主に電話レクチャ時に役に立つと思います。

#環境
Win10
#想定シチュエーション
デスクトップに落ちているショートカットの実体ファイルのパスをコマンドプロンプトで開きたい場合

#手順
デスクトップのショートカットを右クリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230037/c0f8f20f-5e5e-a5b3-267a-532740058666.png)

ファイルの場所を開くを左クリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230037/89fab3c6-e2bc-5de0-9c85-8743b5557196.png)

エクスプローラーが開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230037/b9c971f8-c7db-88e1-3267-db2bf84d5a68.png)

アドレスバーの下三角をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230037/0b286e28-ac4c-3e26-2e31-817190bb23bf.png)

「cmd」と入力し、Enterキーを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230037/4f106e0b-72ba-310a-7259-9c5ea2ef6029.png)

Chromeの実体ファイルがあるパスでコマンドプロンプトが開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230037/e46f07e4-b761-aa4e-ce79-051c87b58308.png)
作って学ぶbashタブ補完、mixコマンドを補完する

「mixコマンドの補完が効けばいいのにな」と思ったことはありませんか？
bashのProgrammable Completionで作れるみたいです。

今回はそれを作ったので紹介します。

# 環境

bash-completionがインストールされていることが前提です。
インストールされていない場合は以下でインストールします。

``` bash
# debian系
$ sudo apt install bash-completion
```

# 作り方

以下がとても詳しいのでココでは解説しません。

- [Bashタブ補完自作入門](https://blog.cybozu.io/entry/2016/09/26/080000)

compgentコマンドとcompleteコマンドについては以下

- [【 complete 】コマンド――補完の方法を指定する（bash）](https://www.atmarkit.co.jp/ait/articles/1907/12/news015.html)
- [【 compgen 】コマンド――bashの補完候補を生成する／使用できるコマンド名を一覧表示する](https://www.atmarkit.co.jp/ait/articles/1907/18/news009.html)


# 既に作られている実装

検索すると同じ目的のいくつかの実装がありました。
てっとりばやく使いたい場合はこれらから選んで使うのもありと思います。

- https://github.com/unblevable/mix-completion
- https://github.com/dalexj/mix_autocomplete
- https://github.com/bjhaid/elixir_auto_complete
- https://minhajuddin.com/2016/12/23/bash-completion-script-for-mix/

# 自分で作ってみた

既に作られているものを使うのは簡単だと思ったのですが、
bashのタブ補完は自分で作ることができれば他にも応用できそうな気がしたので作ってみました。

以下を~/.bash_completionとして保存し、terminalを開き直すと使えるようになります。
※ディレクトリ移動後の一発目がちょっともたつきます。

~~~ bash
_mix()
{
  local cur prev words cword split
  _init_completion || return
  type mix 1> /dev/null || return

  make_opts(){
    _mix_opts=""
    readarray -t _mix_task_list < <(mix help)

    local task
    for task in "${_mix_task_list[@]}"; do
      task=$(echo "$task" | awk '{print $2}')
      # ignore "mix" self and "iex -S mix"
      case $task in
        "#"|"-S")
        ;;
        *)
          _mix_opts+="$task "
        ;;
      esac
    done
  }

  local current_pwd=$(pwd)
  if [[ -z "$_mix_task_list" ]] || [[ $_mix_last_pwd != $current_pwd ]]; then
    make_opts
  fi
  _mix_last_pwd=$current_pwd

  if [[ $prev == mix ]] || [[ $prev == help ]]; then
    COMPREPLY=( $(compgen -W "$_mix_opts" -- "$cur") )
  fi
} && complete -F _mix mix
~~~

# おわり

bashがまったく書けなくて辛かったです:skull:
**「いいね」**よろしくお願いします。:wink:
SANS SEC642 サーバ設定

SANS SEC642の講義で貰ったVMサーバイメージを動かす方法
1)DNS/DHCPサーバの起動
2)ターゲットサーバの起動
3)SAMURAIも含めて、OSイメージのネットワーク設定をすべてホストオンリーにする

ただし、VMwarePlayerでは、DHCPサーバから、正しいIPアドレスを掴めないトラブルが発生します。
理由は、Vmware PlayerではデフォルトでDHCPサーバが動作しており、SAMURAIやターゲットサーバは優先的にVMwareのDHCPサーバからIPアドレスを取得しに行きます。

ですので、サービスメニューからVMwareのDHCPサーバを停止すればOKです。
![vmdhcp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573224/aabaf849-6d07-3d19-5fef-96acc8d1d0dd.png)


参考
http://one.angato.org/studyenv/csrpractice/dhcp/
Jupyter の kernel に pyenv 環境を追加する

## はじめに
Anaconda の環境登録などはせず，pyenv の環境を Jupyter の kernel として登録する時のメモです．
用途としては，python3系の中でバージョンを細かく分けたいときなどです．
Anaconda の仮想環境登録をする場合は[こちら](https://qiita.com/tomochiii/items/8b937f15c79a0c3eae0e)を参照．

## コマンド一発で

```
python -m ipykernel install --user --name={name} --display-name={display-name}
```
* `name`,`display-name` は既存のものと被らないように適宜設定．

## 手順
手元で python 3.7.4 の環境を登録した時の手順です．他のバージョンを登録する場合は適宜変更して下さい．
pyenv のインストール方法はこちらの記事が丁寧に書いてくれています．
→ [pyenv を用いた Python3 インストール](https://qiita.com/hasepyon/items/45ea509c64a6469ca5b6)

まず，追加したい version の pyenv に切り替える．

```
$ pyenv global 3.7.4
```

pyenv が切り替わっていることを確認する.

```
$ pyenv versions
  system
  3.6.5
* 3.7.4 (set by /home/user/.pyenv/version)
```

jupyter で現在登録されている kernel を確認する．


```
$ jupyter kernelspec list
Available kernels:
  python3    /home/user/.local/share/jupyter/kernels/python3
  python2    /usr/local/share/jupyter/kernels/python
```
以下のコマンドで現在の pyenv 環境を jupyter に登録する．

```
$ python -m ipykernel install --user --name=python3.7.4 --display-name=python3.7.4
Installed kernelspec python3.7.4 in /home/user/.local/share/jupyter/kernels/python3.7.4
```

* `name`, `display-name` を適宜設定する．
* `name` は kernel の情報が入るディレクトリの名前，`display-name` は jupyter でカーネルを選択するときの表示名になる．
* `name` では version の指定は行っておらず，現在の環境を登録するだけという点に注意！


```
$ jupyter kernelspec list
Available kernels:
  python3.7.4    /home/user/.local/share/jupyter/kernels/python3.7.4
  python3        /home/user/.pyenv/versions/3.7.4/share/jupyter/kernels/python3
  python2        /usr/local/share/jupyter/kernels/python2
```
無事に現在の環境が jupyter のカーネルに登録できました．
左側に出てくる kernel の名前は先ほどつけた `name` になっています．（`display-name` はあくまで Jupyter上での名前）

## kernel の削除
間違えて登録した時は，以下のようにアンインストール出来ます．

```
$ jupyter kernelspec uninstall python3.7.4
```

## うまく行かない時は
先ほど登録した kernel のディレクトリの `kernel.json` というファイルを確認する．

``` 
$ cat /home/user/.local/share/jupyter/kernels/python3.7.4/kernel.json 
{
 "argv": [
  "/home/user/.pyenv/versions/3.7.4/bin/python3",
  "-m",
  "ipykernel_launcher",
  "-f",
  "{connection_file}"
 ],
 "display_name": "Python3.7.4",
 "language": "python"
}
```

`"/home/user/.pyenv/versions/3.7.4/bin/python3"` が正しく指定出来ているかどうか確認してみる．
ここでのバージョンの指定が間違っていると，`name`や`display_name` があっていても所望のバージョンにならない．

## 参考
* [Jupyterで複数カーネルを簡単に選択するための設定](https://qiita.com/tomochiii/items/8b937f15c79a0c3eae0e)
【AWS】トライアル期間を試してみる。最初にやるべきことは何？~登録編~

## 目的
自分でサービスを作るのに、AWSを使えないか考えている。
とりあえずフリーで使えるなら使って作ってみよう！と思って初めてみる。
やっていることを時系列順に並べていく記録。

やるべきこととか大まかな流れは以下の記事を参考にした。
>[初めてのAWS (Amazon Web Service)](https://qiita.com/terappy/items/1e10bb85505acac5c282)
>[qiita : AWS1年目無料期間でやったこととハマったこと](https://qiita.com/chroju/items/c7ad918d79b0288bc490)
>[AWSアカウントを取得したら速攻でやっておくべき初期設定まとめ](https://qiita.com/tmknom/items/303db2d1d928db720888)

細かい操作とかは、awsのドキュメントを参考にした。
>[IAM Best Practices](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/best-practices.html)


## 登録する

[ここ](https://aws.amazon.com/free/?all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc)からフリーアカウント登録を行う。
登録後、確認メールがきたので、確認メールのリンクからコンソールを開く。

## アカウント設定
[ここ](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/getting-started_create-admin-group.html)の記述に従ってadministratorを作成。

その後、iamコンソール上の以下の項目が満たされるようにそれぞれ設定して行った。
<img width="747" alt="スクリーンショット 2020-01-25 19.03.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/af2cc41d-d477-a522-6c08-a255ca28ce6d.png">

## コスト管理
### Cost Budgetの設定
[10minutes tutorial : Control your AWS costs](https://aws.amazon.com/getting-started/tutorials/control-your-costs-free-tier-budgets/?trk=gs_card) に従って、コスト管理を行う。
cost budgetを作成して設定金額を超えたらアラートが発生するように。
フリートライアルなので＄0にしようとしたけどできなかったので注意。

### 請求情報とコスト管理の設定
通知を受け取る
<img width="1246" alt="スクリーンショット 2020-01-25 19.53.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/11185beb-e8ef-24d1-8e16-28f363cd0579.png">

### 

## Trusted Adviserの設定
[Trusted Adviser](https://console.aws.amazon.com/trustedadvisor/home?region=ap-northeast-1#/dashboard)ページに行ったところ、自動的にチェックが開始されて以下のような画面になったので、チェックが行われていると考えられる。
アラートとか自動で来るのか、このページに行かないとチェックされないのかはわからんけど、一旦おいとこう。

<img width="1006" alt="スクリーンショット 2020-01-25 19.31.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/a78d6ebe-422a-acb3-42ba-66ca236b32d9.png">

## あとやりたいこと
以下の設定をしている記事が多かった。
もっと勉強して、必要なら設定していきたい。

- cloud trailの設定
 - logが確認できるらしい。
- cloud watchの設定
 - コストに対してアラートが設定できるらしい。

料金情報をスラックに投げてくれたりする機能とかも欲しい気がする。 

## 利用開始
iamページのuserの詳細のコンソールログインリンクから、先ほど作成したadministratorで再度ログインする。


さて、いろいろやっていこう！
機械学習入門 ボルツマン機械学習から深層学習まで

まずはディープラーニングの仕組みを概念的に数式抜きに、ざっくりとわかりたい人向けの、最初の一冊。

<a href="https://www.amazon.co.jp/%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E5%85%A5%E9%96%80-%E3%83%9C%E3%83%AB%E3%83%84%E3%83%9E%E3%83%B3%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E3%81%8B%E3%82%89%E6%B7%B1%E5%B1%A4%E5%AD%A6%E7%BF%92%E3%81%BE%E3%81%A7-%E5%A4%A7%E9%96%A2%E7%9C%9F%E4%B9%8B/dp/4274219984/ref=as_li_ss_il?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92+%E5%85%A5%E9%96%80&qid=1579946344&sr=8-1&linkCode=li3&tag=systemsengine-22&linkId=40ee4ddfcab7121d4f2c6805e57c76fa&language=ja_JP" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=4274219984&Format=_SL250_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=systemsengine-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=systemsengine-22&language=ja_JP&l=li3&o=9&a=4274219984" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
https://amzn.to/2Rr3ZYz


##どのタイミングで読んだか

機械学習を勉強してみたいと思って、よくわかる系、をまずは読もうと思って買った。なので、まったく機械学習に関する予備知識はなかったです。最初の一冊

##良かった点と悪かった点
良い点としては、ディープラーニングってどんなものなのかを雰囲気をつかむことができる。非常に平易でサクサク読める。少し背景の数学などがわかると、とくにさらっと読んで雰囲気は掴めるかと。まったくの初心者でもわかるはず。概念を理解するにはいいと思う。

悪い点というか、私が間違ったのは、そもそも機械学習と深層学習の区別がついていなかったため、この本を買ってしまったけど、これは深層学習、つまりディープラーニングに関する本。いわゆる機械学習全般の入門書ではないのでご注意を。副題読むとそう書いてるけどね。

また最後のほうへ行けばいくほど、数式や理論を抜きに説明してて、何を説明しているのかわからなった。特にボルツマンマシン以降は、なんのために使うのかとか腑に落ちずに読んでたので消化不良。

おそらくこれ一冊だけでは雰囲気だけわかるけど、何もわからないと思う。でも、結構ちゃんと書いているので、その後数冊読んだあとにもう一度読むと何が書いているかよくわかるし、他の本で挫折しているときとかに読むと、逆につながりがわかっていいかも。俺ももう一度読み返したい。

##どんな人にお勧めか
機械学習、というよりディープラーニングに興味あるけど、難しい本はちょっとという人。特に中身を理解したい人かな。応用とか産業にとっての位置づけとかは全く書いてない。

ちゃんとした本に入る前の準備運動もしくは、ちゃんとした本を読んだあとの、理解の整理、くらいでもいいかも。
ESET Cyber Security Pro(6.8.300.0)とGradle Daemon

Gradle Daemon?


ESET Cyber Security Pro 6.8.300.0 に変更してから・・・？
FirewallをOFFにしないと Flutter でAndroidのビルドができなくなった。

ESETのFirewallを対話モードで実行すると、

|項目|値|
|----|----|
|リモートコンピュータ|::|
|リモートポート|51360|
|ローカルポート|51198|
|プロトコル|TCP|

というポートと通信している。

51198ポートを開いているコマンドを探す

```console
% lsof -i -P | grep 51198
COMMAND    PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
java      2772 USER  227u  IPv6 0x6eb2a67055220503      0t0  TCP *:51198 (LISTEN)
```

java で改めて抽出

```console
% lsof -i -P | grep java
COMMAND    PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
java      2772 USER  227u  IPv6 0x6eb2a67055220503      0t0  TCP *:51198 (LISTEN)
java      2772 USER  229u  IPv6 0x6eb2a670582df1b3      0t0  UDP *:59752
```

PID:2772 の情報

```console
% ps -f -p 2772
UID   PID  PPID   C STIME   TTY           TIME CMD
501  2772     1   0  5:18PM ??         1:09.43 /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java -Xmx1536M -Dfile.encoding=UTF-8 -Duser.country=JP -Duser.language=ja -Duser.variant -cp /Users/<USER>/.gradle/wrapper/dists/gradle-5.6.2-all/9st6wgf78h16so49nn74lgtbb/gradle-5.6.2/lib/gradle-launcher-5.6.2.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 5.6.2
```

GradleDaemonとあるので、そことの通信ができなくなっている様子。

ESETに以下のFirewall設定で追加

|項目|値|
|----|----|
|名前|GradleDaemon|
|全てのアプリケーション|チェック|
|アクション|許可|
|方向|内向き|
|プロトコル|TCP|
|ポート|ローカル|
|ローカルポート|51198|
|宛先|インターネット全体|

「51198」というポート番号が固定なのか気になるところ。

そして、この後さらに「adb」も。。。

|項目|値|
|----|----|
|名前|adb(Android Debug Bridge)|
|全てのアプリケーション|チェック|
|アクション|許可|
|方向|内向き|
|プロトコル|TCP|
|ポート|ローカル|
|ローカルポート|5037|
|宛先|インターネット全体|

どうも宛先をインターネット全体にしないと結局通信出来なかった。