OmniAICreator/Qiita-1.07M huggingface dataset:
Vue + AWS Amplifyでシンプルな画像共有アプリを作成する (概要) #1


# 今回のテーマ
Amplify Frameworkってのを使うと開発からデプロイまでめちゃくちゃ便利だよーってのを伝えたいのと、そのやり方について軽く通しながら説明出来たらなーって思っています。

大まかには以下のような感じです

- **Vue.jsでフロントエンド開発が出来るようになる**
- **Amplifyを用いた開発が出来るようになる**
- **設計からデプロイまでの流れを理解する**

あまり細かくは突っ込まない（予定）なのでそこはご了承ください。

# 今回作成するもの
instagramの機能を**最大限まで削り取ったような**シンプルな画像共有アプリ(PWA)です。
手軽に作れるようになるべく単純にしました。
それでいて色々な技術的要素を求められるので丁度いいかなと。

![instagram-logo-2-e1541140710741.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166345/cd2a07ef-fe4b-c61d-1c93-755be051e020.png)


仕様としては以下を想定しています。

- **ユーザー登録＆ログインが出来る**
- **画像を投稿・削除出来る**
- **投稿にいいねが付けられる**
- **タイムラインに最新の１０件が表示される**
- **マイページに自分の投稿一覧が表示される**


# 構成図
<img width="893" alt="スクリーンショット 2019-07-15 20.51.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166345/87a96ea2-fbac-4c82-2555-ef2aaa1f62b9.png">



# キーワード

### Vue.js
クライアントサイドのJavaScriptフレームワーク
[Vue.js](https://jp.vuejs.org/index.html)

### PWA
Progressive Web Applicationの略称
モバイルユーザーのUX向上を目的とした、WEBページ／WEBアプリケーションとネイティブアプリの利点を兼ね備えている
[Qiita: PWAに興味を持っている人向けに概要とか動向とかをまとめた](https://qiita.com/bunty/items/a0dc2d6b3986dd1c5a73)

### Amplify Framework
アプリケーションと統合するための一連のライブラリ、UI コンポーネント、コマンドラインインターフェイスを提供している
Amplify Consoleを用いることでCI/CDからCDNまで利用可能
[Amplify フレームワーク（スケールするアプリを最速で構築する方法をご提供](https://aws.amazon.com/jp/amplify/framework/)

### Amazon Cognito
AWSが提供する認証・認可基盤
ユーザー認証やAPI実行の管理を行う
[Amazon Cognito（ウェブ/モバイルアプリのユーザー管理）| AWS](https://aws.amazon.com/jp/cognito/)

### DynamoDB
フルマネージドNoSQL、スキーマレスなデータベースサービス
[Amazon DynamoDB（マネージド NoSQL データベース）| AWS](https://aws.amazon.com/jp/dynamodb/)

### S3
Simple Storage Serviceの略称、クラウド型ストレージ
[Amazon S3（拡張性と耐久性を兼ね揃えたクラウドストレージ）｜AWS](https://aws.amazon.com/jp/s3/)

### GraphQL
RESTfulなAPIの課題を解決するために開発されたクエリ言語
単一エンドポイントや型付けなどの特徴がある
[Introduction to GraphQL](https://graphql.org/learn/)

### AppSync
フルマネージドGraphQLサービス
これとGraphQLでBFFみたいなことが出来る
[AWS AppSync（アプリデータをリアルタイムで保存、同期）| AWS](https://aws.amazon.com/jp/appsync/)

### Sketch
UIデザインツール
これを使ってプロトタイピングが出来る
[The best products start with Sketch](https://www.sketch.com/)


# 終わりに
記事のペースは週２くらいになると思われます。
あまり期待せずに待ってもらえると嬉しいです。

次　→　[Vue + AWS Amplifyでシンプルな画像共有アプリを作成する (作成〜デプロイ) #2](https://qiita.com/yukitaka13-1110/items/b1a621fdcec3cd889de0)
[cocoa][swift]【研究】スパゲッティ・コード誕生の理由（わけ）

<p>自分はスパゲティ・プログラムには二種類あって、一つは未熟だから、もう一つは経験も技術もあるのに、と考えている。そして、問題は後者の方で、考えに考え抜いたスパゲティ、理由を聞いても皆が納得するないようで、本人も信念を持って取り組んだ結果だから、それを何とかするのが非常に困難だと考えている。</p>

<p>今回、別件でワインバーグ氏について調べていたら、スパゲティ・プログラムの原因を見つけるヒントが目に留まったので、それと、発見した原因を発表する。</p>

よく適応すれbするほど、適応力を失いがちだ。
<p>『コンサルタントの秘密 - 技術アドバイスの人間学 -』で紹介されていて、生物学の分野でロナルド・フィッシャー卿の「フィッシャーの基本定理」と呼ばれるもので、自然淘汰に関する基本定理だ。</p>

<p>ワインバーグ氏の著書では、プログラミングに関して取り上げた定理でないが、この意味を考えてみた閃いた。</p>

<p>経験のある、プロジェクトでも声がでかい人間が生み出すスパゲッティ・プログラム。それは、今、この瞬間に最適なもので、そのため、将来の変化に対応できず、それが、のちの人を苦しめている。</p>

<p>具体的な例を挙げてみよう。</p>

<p>例えば、三つのテーブル・ビューがあるスマートフォン・アプリケーション。一つは新規リスト、もう一つは、編集リスト、最後は削除リスト。リストを管理して、表示するという部分のコードは共通化できる。ベースクラスを導入しよう、と、スパゲティ・プログラム料理人は考える。</p>

<pre><code>class BaseTableViewController {
    func sortList() {
        ....
    }
}
</code></pre>

<p>よし、うまくいった。これがリファクタリングだ！俺ってすごい。</p>

<p>ここで悲しい依頼が。新規リストは、条件によって並び替えのルールを変えて欲しい。ああ、どうしよう。そうだ、前処理関数を導入すればいい！</p>

<pre><code>class BaseTableViewController {
    func prepare() {
        ...
    }
    
    func sortList() {
        prepare()
        ...
    }
}
 
class NewTableViewController {
    override func prepare() {
        ...
    }
}
</code></pre>

<p>新規リストのクラスで、前処理関数をオーバーライドして、挙動を変えればいい！</p>

<p>こうして、また新たなスパゲティ・プログラムが生み出される！</p>

<p>基本クラスのコードを読んでも、新キリストのコードを読んでも、どんな動きをするのか読み取れない。</p>

<p>では、どうやって、スパゲティ・プルグラムの調理が行われているのを見つけるのか？</p>

<p>長年の研究によって、自分が見つけたのは、以下だ。</p>

<ul>
<li>これはリファクタリングした方がいいな。やろう！<br />今この瞬間の共有に適応した、将来の適応力がないコードを生産する掛け声だ！</li>
<li>このコードは安全でないので修正する！<br />これからプログラミングされる部分は安全であるように心がけることには意義がないが、既に生産されたコード。そして、それが今後も手を加える可能性が低い箇所だとしてら、そいつが単に気に食わないから修正するということの言い訳だ。そんな奴に贈るワインバーグ氏の言葉はこれだ。『壊れていないものを直すな。』</li>
</ul>

【関連情報】
<a href="https://www.kyoritsu-pub.co.jp/bookdetail/9784320025370">コンサルタントの秘密―技術アドバイスの人間学―</a><br />
<a href="https://cocoa-kanto.connpass.com/event/135361/">Cocoa.swift 2019-07</a><br />
<a href="https://www.facebook.com/groups/cocoa.kanto/">Cocoa勉強会 関東</a><br />
<a href="http://www.bitz.co.jp/weblog/">Cocoa練習帳</a><br />
C# で再帰的にファイルを探す処理を書いてみた

最初にお断りするのですが、↓のオプションをちゃんと使えばだいたい同じことができます。
https://docs.microsoft.com/ja-jp/dotnet/api/system.io.directory.getfiles?view=netframework-4.8

まぁなんとなくイメージできたから書いてみたかった、という程度の理由で自前実装しました。

```c#

    public void Main()
    {
        var root = "Assets/StreamingAssets/";
        var paths = new List<string>();

        // txt パスをリストに追加する
        Action<string> action = (path) =>
        {
            if (path.EndsWith(".txt")) { paths.Add(path); }
        };
        CollectPath(root, action);

        foreach (var path in paths)
        {
            // 各パスに対してやりたいこと
            Debug.Log(path);
        }
    }

    private void CollectPath(string root, Action<string> action)
    {
        var dirPaths = Directory.GetDirectories(root);
        foreach (var path in dirPaths)
        {
            // 末尾に \ が付くのを回避（★）
            var p = path + "/";
            CollectPath(p, action);
        }

        var filePaths = Directory.GetFiles(root);
        foreach (var path in filePaths)
        {
            action(path);
        }
    }

```

`root`の値でピンとくる人も多いと思いますが、Unity 用の実装です。
環境が Windows のため何もしないと区切りが `\` になってしまうので、★のところで無理やり対処しています。
javascriptのProxyパターン

# Proxy パターン
Proxy とは 「代理(人)」 という意味です。
Proxyパターンはプログラミングにおけるデザインパターンの一種。既存クラスのメソッドが呼ばれた際に、一旦中間的な処理を実行してから渡すパターンです。

# 例
```js
// 画像読み込んで、画面に表示用メソッド
var imgFunc = (function() {
    var imgNode = document.createElement('img');
    document.body.appendChild(imgNode);
    return {
        setSrc: function(src) {
            imgNode.src = src;
        }
    }
})();

// 代理メソッド
var proxyImage = (function() {
    var img = new Image();
    img.onload = function() {
        imgFunc.setSrc(this.src); // 画像読み込みが完了したら、画像を設定
    }
    return {
        setSrc: function(src) {
            imgFunc.setSrc('./loading.gif'); // 画像読み込み完了までローディング画像を表示させ
            img.src = src;
        }
    }
})();

proxyImage.setSrc('./pic.png');
```

1. 代理メソッドproxyImageを呼び込んで、[./pic.png]を読み込み開始
2. ./pic.pngが読み込み完了までローディング画像./loading.gifを表示させる
3. ./pic.pngが読み込み完了したら、画像がimgNodeにセット（imgFunc.setSrc(this.src)で）され、画面に表示


この例でProxyパターンを使うことで画像遅延読み込みを実現することができます。

# 参考
1.zeng tan.2015. Design Pattern And Development Practice Of JavaScript
Android デバイスを接続して LogCat でログを確認する

#Android デバイスを接続して LogCat でログを確認する
Android の実機を PC に接続して、そのログのみを確認する方法です。
Android SDK の tools にある monitor をターミナルなどで実行することで、LogCat のみを表示させることが出来ます。

![001_monitor_terminal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300480/1074a6c9-5554-184c-934a-397a2e8d2b82.png)
![002_moniter_execute.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300480/c3c757b3-d42b-b2e5-1063-93894af0f652.png)
↑Android Device Monitor これが立ち上ります

![003_monitor_set_filter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300480/fd19c248-0ced-f00d-9dcd-e0c864c0a4f0.png)

フィルターを設定して表示させるログの絞り込みをすることも可能です。
LogCat タグ内の編集ボタン(Saved Filtersの表示がある部分の右側)をクリックして設定画面を開いて条件を指定します。

![004_monitor_filter_tag.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300480/37207356-d272-3069-c975-4f10d848735f.png)

登録したフィルター名をクリックすれば、それに関係するもののみ表示させることができます。

表示しているログをテキストファイルなどの形式で書き出すこともできます。
![006_logtext_set.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300480/c1a364c3-af5b-6a16-c945-3b02e187dc1f.png)
↑書き出したいログの範囲を選択した状態にして…
![007_logtext_save.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300480/0ed162fc-4a91-5613-eb32-24fb39621a25.png)
↑画面右上のフロッピーアイコンをクリックして…
![008_logtext_save.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300480/9bef92d0-8a1c-05b0-c78a-6fec95b8de09.png)
↑書き出す形式や場所を指定すれば、選択しておいたログが出力されます。
gulp4のインストール手順

gulp4のインストール方法を自分なりにまとめる。
以前gulp使ってたけど、しばらく触ってなかった間に（gulp3→4で）色々と変わったみたい。


## npm初期化

```cmd
npm init 
```

## npmインストール

```
npm install gulp -D
```

ローカルへのインストールで良い。

### インストールされたか確認

```
npx gulp -v
```

`npx`つければ良い。
（npmのバージョンが5.2.0以上であること）


### インストールに失敗したモジュールがあればインストール

```
npm install npm-install-missing --save-dev
```

## gulp実行テスト

### gulpfile.js作成

```javascript
var gulp = require('gulp');

gulp.task('default', function(done){
  console.log('gulp installed!!');

  return done();
});
```

### 実行できるか確認

```
npx gulp
```

## 参考リンク

- [gulp公式サイト](https://gulpjs.com/)
- [gulp公式サイト parallel()](https://gulpjs.com/docs/en/api/parallel)
- [npm 5.2.0の新機能！ 「npx」でローカルパッケージを手軽に実行しよう](https://qiita.com/tonkotsuboy_com/items/8227f5993769c3df533d)
- [gulp3→4の変更点に気をつけよう！](https://qiita.com/tatsuo-iriyama/items/08ba4bd621b7fdedcc4e)
- [gulp@4.0.0を試してみた](https://codecodeweb.com/blog/459)
【コンピューターサイエンス入門第0回:機械学習やってみる】 k平均法をJavaで実装してみよう

# はじめに

こんにちは、炭山水です。

ちょっとシリーズ物でも始めてみようかと思い、昔やってたクラスタリングのおさらいでもしつつ、Qiitaにまとめていく試みでもしてみようと思います。

まずはデータマイニングとかクラスタリングと呼ばれるデータ分類の基本である「k平均法」について、何回かに分けてJavaで少しずつ実装進めながら解説(という名の僕の復習)をしていこうかなと思います。

今回の第0回ではとりあえず前置きとか前提中心にお話ししようかなと思います。具体的な解説は次回からかな。

# 触れること、触れないことやその他注意書き

本シリーズではあんまりガチな「データマイニング」とか「クラスタリング」の種類の説明、用途の説明には触れず、あくまでk平均法と呼ばれる手法をとにかく最後まで実装してみることを目的とします。

座学チックに知識増やすより、手を動かした方が雰囲気つかめますからねという考えです。

手を動かしてみて雰囲気をつかむということを目的にしていますので、ありものの分析用ライブラリとかは使わずに自分で実装していきます。

あと、僕がこの辺の分野のことを知っていたのは10年以上前のことで、特にそれ以後キャッチアップとかはしていないので、情報が古いよということはご承知おきください。

# 前提

多少なりとも言語の知識はあるものという前提でお話しさせていただきます。また、筆者である僕が、最近仕事で使っているSpringBootをプライベートでも触ってみたいという動機も混ざっているので、SpringBootベースで進めていきます。

っていっても業務ロジック書くわけじゃないので、ほとんどSpringBootらしい話は出てこないと思いますけどね。ほぼJavaそのもので書くことになると思います。アノテーションを前置き無しで使っても勘弁してねくらいの話です。

# k平均法ってどんなことができるの？

詳しいロジックは次回以降に回すとして、すっごくざっくりというと、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/38e045e5-9ad6-1111-1463-83975a5dcf58.png)

こういう感じのデータを

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/e76d4294-86ee-6ee9-0a10-303ad55ff8c4.png)

こういう感じに分類することができます。

図では適当にXとかYとか置いたのですが、「とあるコンビニ利用者の購入金額と時間帯」とかそういうのをイメージしてもらうといいかと思います。

まあ、現実にこんなにきれいに集まってるデータはないのですが、それにしてもこのくらいのサンプル数を人間の目で見れば、なんとなーくグループに見えるものでも、コンピュータになんら前情報なく判別させようとするとテクニックが必要なわけです。

データが増えてきたり軸がXYじゃなかったりするとコンピュータの力を借りる必要がありますからね。

# では次回

今回はざっと前提の話と、なにができるかの話をしました。

次回からは実際に分類ロジックに必要な部品を説明しながら実装していきたいと思います。

次回
[【コンピューターサイエンス入門第1回:機械学習やってみる】 k平均法をJavaで実装してみよう～座標の概念について～](https://qiita.com/tan3_sugarless/items/364bf63680018e722b4e)
LeetCode / Remove Element

（[ブログ記事](https://mhiro216.hatenablog.com/entry/2019/07/15/215315)からの転載）

[https://leetcode.com/problems/remove-element/]

Given an array nums and a value val, remove all instances of that value in-place and return the new length.

Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

The order of elements can be changed. It doesn't matter what you leave beyond the new length.

Example 1:
Given nums = [3,2,2,3], val = 3,
Your function should return length = 2, with the first two elements of nums being 2.
It doesn't matter what you leave beyond the returned length.

Example 2:
Given nums = [0,1,2,2,3,0,4,2], val = 2,
Your function should return length = 5, with the first five elements of nums containing 0, 1, 3, 0, and 4.
Note that the order of those five elements can be arbitrary.
It doesn't matter what values are set beyond the returned length.

[前回の記事](https://mhiro216.hatenablog.com/entry/2019/07/14/191526)と類似の問題です。
指定された値をリストから取り除く問題です。これだけなら簡単すぎて問題になりませんが、入力のリストを<b>直接</b>修正する必要があります。

また、相変わらず以下に留意する必要があります。気をつけましょう。。。
<b><span style="color: #ff5252">入力のリストnumsに対して、関数の返り値はリストの要素数nで、正解を判定する対象はnums[:n]になる</span></b>

#### 回答・解説

##### 解法1
リストの要素数分ループを回していき、除外対象の値valでない値が見つかったら、リストの前から順に値を置き換えていきます。
変数countを初期値0のポインタとし、値の置換場所を指し示すものとして使います。
nums = [3,2,2,3], val = 3
の場合、2度目のループで3でない値(2)が見つかるので、nums[count]を2で置き換えます。
ポインタをcount += 1で1つ進めて、次の処理に移ります。

最終的に正解を判定する対象は、nums[:count]になります。

```python
class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        count = 0
        for i in range(len(nums)):
            if nums[i] != val:
                nums[count] = nums[i]
                count += 1
        return count
```

今日は非常に簡単な問題でした。まあ祝日なので、このくらいの軽さで。
php-master-changes 2019-07-14

今日は不要コードを削除する修正があった！

# 2019-07-14
## petk: Remove PHP_MYSQL variable
- https://github.com/php/php-src/commit/7a6d737de728d541597033e538d333795c913ec7
- [7.4~]
- ビルドシステムで、不要変数 PHP_MYSQL の削除
- ext/mysql で使われていた

## petk: Remove timelib outdated defines
- https://github.com/php/php-src/commit/c72d6da461d0b6be0cc4d457a64f36f556d09fca
- [7.4~]
- ext/date で、timelib の不要なマクロ定義の削除

## petk: Remove duplicate PTHREADS template define
- https://github.com/php/php-src/commit/66c02cc0a1db8eb0eaef2b15c5103875a9a171a7
- [7.4~]
- ビルドシステムで、不要な `#undef PTHREADS` の削除
amazon app store向けにアンドロイドアプリを配信するまで

## はじまり
　グーグル以外のアンドロイドアプリのAmazonのamazon appstoreはあまりやっている人が少ないのか情報が少ない。なので、amazon appstore向けにアンドロイドアプリを配信するときに戸惑ったことを書いてみる。

## 公式情報
https://developer.amazon.com/ja/docs/app-submission/getting-started.html
　Amazonのアカウントを作るところから始める。日本のAmazonのアカウントを持っているから大丈夫だと思っていたが。どうやら.comつまりアメリカのアマゾンのアカウントが必要だった。有料販売する場合は各種の税に関する情報が必要だろう。

### アプリの実際の作成

　アプリを作った時の画像をサンプルとして、「ふりがな付与」アプリを例として書いていく。

[「ふりがな付与」アプリ](https://www.amazon.co.jp/kyukyunyorituryo-%E3%81%B5%E3%82%8A%E3%81%8C%E3%81%AA%E4%BB%98%E4%B8%8E/dp/B07TBFT3BG/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=%E3%81%B5%E3%82%8A%E3%81%8C%E3%81%AA%E4%BB%98%E4%B8%8E&qid=1563029427&s=mobile-apps&sr=1-1)


Android studioにはImage Asset Studioでアイコンが作れる。それとは別にアイコンを作る必要がある。
　
https://developer.amazon.com/ja/docs/app-submission/asset-guidelines.html

|小アイコンのサイズ |114 x 114px |
|---|---|
|大アイコンのサイズ |512 x 512px  |
|形式|PNG（背景色透明） |


![icon114.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186721/4bd32288-feb5-d801-d866-c4f67a093c0b.png)
上のアイコンを作った。角を丸めて、透明にしたほうが良かったかもしれない。

## 署名

　apk署名をandroid studioで書いてもサイトでまた書く必要がある。

https://developer.amazon.com/ja/docs/app-submission/understanding-submission.html#app_signatures

>Amazonでは、申請されたアプリに使用されている署名をいったん削除し、開発者ごとに一意のAmazon署名を用いてアプリを再署名します。Amazon署名は変更されることがなく、同一アカウントのすべてのアプリに対して同じAmazon署名が使用されます。


## 参考

[Amazon Android アプリストア でアプリを公開してみた　くうと徒然なるままに](
http://kuxumarin.hatenablog.com/entry/2017/03/29/Amazon_Android_%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B9%E3%83%88%E3%82%A2_%E3%81%A7%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92%E5%85%AC%E9%96%8B%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F)
CNTKで作成したモデルをONNX形式で出力してみる。

# はじめに
最近、CNTKを使用してみています。CNTKは[ONNX](http://onnx.ai/)に対応しており、ONNX形式のモデルを入出力できます。ONNXは機械学習のモデルを異なるフレームワーク間で共有するツールです。Chainerで作成したモデルをCNTKで利用する、など相互に活用できるようになります。

今回はirisの分類をCNTKで行い、ONNX形式でモデルを出力してみようと思います。

# 環境
| 環境 | バージョン |
| --- | --- |
| OS | Ubuntu 16.04 |
| Python | 3.6.8 |
| CUDA | 10.01 |
| CNTK | 2.7 |

# CNTKでiris分類の概要
以下のような簡単サンプルプログラムを使い、CNTKとONNXの使い方をご紹介します。
本記事ではソースコードの一部を抜粋しています。ソースコードの全量は以下に公開しています。
https://github.com/t2hk/cntk_onnx_iris

  * iris分類を行うモデルを作成する
  * 作成したモデルをONNXで出力する
  * ONNXモデルを読み込み、irisの推論を行う

## GPUを使う
CNTKでGPUとCPUのどちらを優先的に使用するかは"try_set_default_device"で設定できます。

```py
from cntk.device import try_set_default_device, gpu

try_set_default_device(gpu(0))
```

## ネットワーク構築
入出力となる学習データ、分類ラベルの変数定義を行い、ネットワークを構築します。
irisの分類なので、入力となる特徴データは4つ、出力となる分類は3つとなります。

```py
# 各種パラメータ定義
n_input = 4
n_hidden = 10
n_output = 3

# 学習データと分類ラベルの入力変数を定義する。
features = C.input_variable((n_input))
label = C.input_variable((n_output))

# ネットワークを構築する。
model = Sequential([
  Dense(n_hidden, activation=C.relu),
  Dense(n_hidden, activation=C.relu),
  Dense(n_hidden, activation=C.relu),
  Dense(n_output)])(features) 

ce = C.cross_entropy_with_softmax(model, label)
pe = C.classification_error(model, label)
```

## 学習
学習データと正解ラベルのデータを用意し、訓練器を作成します。

なお、irisのデータセットの読み込みは省略します。

```py
x_train_batch = [ミニバッチ用の学習データ]
t_train_batch = [ミニバッチ用の正解ラベル]

minibatch = C.learning_parameter_schedule(0.125)
trainer = C.Trainer(model, (ce, pe), [sgd(model.parameters, lr=minibatch)])
trainer.train_minibatch({features : x_train_batch, label : t_train_batch})

sample_count = trainer.previous_minibatch_sample_count
aggregate_loss += trainer.previous_minibatch_loss_average * sample_count
```

## モデルのONNX出力
作成したモデルをONNX形式で保存します。formatで形式を指定するだけです。

```py
output_file_path = R"[出力するモデルのファイルパス]"
model.save(output_file_path, format=C.ModelFormat.ONNX)
```

## ONNXモデルの読み込み
既存のONNXモデルを使用する際もformatでONNXを指定するだけです。

```py
load_model = C.Function.load(output_file_path, device=C.device.gpu(0), format=C.ModelFormat.ONNX)
```

## ロードしたONNXモデルで推論する
ロードしたモデルから分類器を作成し、evalで推論します。

```py
classifier = C.softmax(load_model)
for i, test in enumerate(x_test):
  infer = np.argmax(classifier.eval([test]))
  print("[{}] in:{} correct:{} infer:{}".format(i,test, t_test[i], infer))
```

# おしまい
CNTKを使って簡単にONNX形式のモデルを出力できました。次回はこのモデルをMarkLogic10のCNTKで使用してみたいと思います。

# 参考
以下のサイトを参考にさせて頂きました。ありがとうございます。

* [CNTK 2.2 Python API 入門 - パッケージ構成、基本演算 & 順伝播型 NN 分類器](https://qiita.com/masao-classcat/items/966a45f7235389a3bce9)
* [CNTKのExample(TrainResNet_CIFAR10.py](https://github.com/microsoft/CNTK/blob/master/Examples/Image/Classification/ResNet/Python/TrainResNet_CIFAR10.py)
* [ディープラーニング入門
Chainer チュートリアル　(14. Chainer の基礎)](https://tutorials.chainer.org/ja/14_Basics_of_Chainer.html)
Javaパフォーマンス 1章 イントロダクション

[O'Reilly Japan \- Javaパフォーマンス](https://www.oreilly.co.jp/books/9784873117188/)
こちらの本の１章まとめ

1章 イントロダクション - Qiita←今回記事
[2章 パフォーマンステストのアプローチ \- Qiita](https://qiita.com/momosetkn/items/675b5b7643b742c0f225)←次回記事
[3章 Javaパフォーマンスのツールボックス \- Qiita](https://qiita.com/momosetkn/items/e00a59ed1672afb65df7)
[4章 JIT コンパイラのしくみ \- Qiita](https://qiita.com/momosetkn/items/21d00b0a2d015624fc07)
[5章 ガベージコレクションの基礎 \- Qiita](https://qiita.com/momosetkn/items/e5ff2a8f6c11b959735c)

本書では、JVMの設定と良い標準APIの使い方の２つについて説明がされる。

# パフォーマンスの全体像

## よりよいアルゴリズムを記述する
最終的にはパフォーマンスはコードの適切さにかかってくる。
特定の要素を探すコードだったら、いくらループするコードをなんとかしようとしても、HashMapを使うコードには勝てない。

## コードの量を少なくする
いまだに書いたコード量で開発者を評価する管理者もいるが、
コード量が少ない場合のほうがパフォーマンス面で有利なことが多い。特にJavaだとこの傾向が強いらしい。

コンパイルしないといけないコードが増えれば、JITコンパイラのによってコードが速く実行できるようになるまでの時間が増加。
生成廃棄しないといけないオブジェクトの量が増えれば、GCの作業量も増える。
多くのオブジェクトを保持し続ければ、GCのサイクルが伸びる。
ロードするクラスが増えれば、起動する時間も増える。
実行されるコードのサイズが増えれば、キャッシュに収まらない可能性もある。

パフォーマンスは常に悪化する。機能追加がされていくため。

## 早まった安易な最適化
>1日のうち97%くらいは、ささいな効率については忘れるべきです。早まった最適化は諸悪の根源です。

という有名な言葉がある。
クリーンで率直なコードを書いて読みやすくするようにすべきで、
分析をせずに最適化（パフォーマンス面で優位になる代わりに、構造が複雑になるような修正）するべきではない。
しかし、明らかにパフォーマンス面で問題になるようなコードを避けるというのは別の問題で、それはいいことである。

## 外部を見渡す(データベースは常にボトルネック)
外部リソースを使わないスタンドアロンの場合は、パフォーマンスでネックなのはそのアプリケーションだけ。
しかし、外部リソースを使う場合は、そこがネックになる。
本書では、Javaだけでなく、全体について分析がされていると仮定してJavaパフォーマンスについて説明を行う。

## よくあるケースのために最適化する
頻度の高いユースケースに注力する。
MySQL 8.0でSPATIAL INDEXを使用するには列定義でSRIDを指定する必要がある

# はじめに

下記記事の記事(以降「前記事」)に対する解決策がわかったので書いておく。

「MySQL 8.0でSPATIAL INDEXが使用されない」
https://qiita.com/miyauchi/items/809c82c0e469fd8992ce

結論としては、MySQL8.0でSPATIAL INDEXを使うためには列定義でSRIDを指定しなければならない。SRIDを指定しなかった場合はSPATIAL INDEXは一切使われない。

詳しくは下記の記事で書かれている。

https://qiita.com/qyen/items/bc4a7be812253c2be9f9

(追記)SPATIAL INDEXが使用されても結局遅くない？っていう記事書きました。
https://qiita.com/miyauchi/items/f6621cc79aff98dd46e0

# ogr2ogrを使ってる人への注意点

GDAL3.0.1のogr2ogrで取り込んだ(作成した)テーブルにはSRIDが指定されていないので要注意です。

そもそも前記事を書いたのはogr2ogrで取り込んだデータに対して検索をかけた際に、SPATIAL INDEXが使用されなかったことが発端です。

ogr2ogrを使ってシェープデータをMySQLに取り込んで使用するつもりの人はこの記事で記載するように、列定義にSRIDを後から定義してあげてください。

# 列定義を修正する

前記事のテーブルは下記でした。

```
mysql> SHOW CREATE TABLE test;
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                           |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
| test  | CREATE TABLE `test` (
  `geom` geometry NOT NULL,
  SPATIAL KEY `sp_index` (`geom`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
```

上記テーブルのgeom列を修正するために、まずはSPATIAL INDEXをDROPする必要がある。

その後、SRIDを指定し、再度SPATIAL INDEXを作成する。

```
mysql> ALTER TABLE test DROP INDEX sp_index;
Query OK, 0 rows affected (0.09 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> ALTER TABLE test MODIFY geom GEOMETRY NOT NULL SRID 4326;
Query OK, 2 rows affected (0.06 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> ALTER TABLE test ADD SPATIAL INDEX(geom);
Query OK, 0 rows affected (0.12 sec)
Records: 0  Duplicates: 0  Warnings: 0
```

# SPATIAL INDEXが使われるかどうか確認

無事使われることが確認できました！

```
mysql> EXPLAIN SELECT ST_AsText(geom) FROM test WHERE ST_Intersects(geom, ST_GeomFromText('POINT(43.06 141.34)', 4326));
+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | test  | NULL       | range | geom          | geom | 34      | NULL |    1 |   100.00 | Using where |
+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.04 sec)
```

# まとめ

MySQL8.0でSPATIAL INDEXを使うためには列定義でSRIDを指定しましょう。
nmap

# nmap
普段関心がない、nmapを調べてみた。

## OS
```
3.10.0-957.21.3.el7.x86_64
```

## usage
```
nmap ホスト名
```

とりあえずオープンしているポートを調べる。一瞬で帰ってきた。

```
Starting Nmap 6.40 ( http://nmap.org ) at 2019-07-15 12:06 UTC
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000035s latency).
Other addresses for localhost (not scanned): 127.0.0.1
Not shown: 994 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
111/tcp  open  rpcbind
5000/tcp open  upnp
8080/tcp open  http-proxy
8081/tcp open  blackice-icecap
8082/tcp open  blackice-alerts
```

-Aをつけると詳細にスキャンしてくれる。遅い。
【Maya】ポリゴンオブジェクトを強制クリーンアップするスクリプト

　Mayaってごちゃごちゃやってるとたまに、マテリアルがアサインできなくなったり、裏面でもなく頂点カラーもないのにフェースが真っ黒になってしまったり、何かツールで編集しようとしてもエラーになってしまったり、色々オブジェクトの挙動がおかしくなるときがありますよね（よく起こるのにいい例が思い浮かびませんでしたが、とにかく色々）。

　適当にキューブを作る→結合→キューブの部分削除　をして強制的にオブジェクトを綺麗にするのが手っ取り早い事が多く、今回はその一連の動作をスクリプト化してみました。

#導入方法
以下のソースコードをスクリプトエディタのPythonタブに貼り付け、中ボタンでシェルフフィールドにドラッグ＆ドロップ。

```python
import maya.cmds as cmds

def Main():
	selectedObjects = cmds.ls(sl=True, tr=True)

	targetMesh = []

	for i in selectedObjects:	#ポリゴンオブジェクトだけを抽出
		shape = cmds.listRelatives(i, s=True, typ='mesh')
		if shape:
			targetMesh.append(i)
	
	
	if len(targetMesh) == 0:
		cmds.confirmDialog(t='エラー', m='ポリゴンオブジェクトを選択してください')
		return

	for i in targetMesh:
		temp = cmds.polyCube()
		afterMesh = cmds.polyUnite(temp, i, op=True)	#キューブを作成し結合

		cmds.delete(temp)	#不要になったメッシュの削除
		cmds.delete(afterMesh, ch=True)	#ヒストリを削除
		cmds.rename(i)	#名前を元に戻す

Main()
```
![Script_CleanUp_ScreenShot.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462577/6836fcdf-3efe-b7b4-e4ba-ee9a7a945330.jpeg)

#使い方
ポリゴンオブジェクトを選択してスクリプトを実行するだけです。
複数選択に対応していますが子に別のメッシュを持ってる場合は対応していません。
Linuxのマルチスレッドプログラミングにおけるスタックサイズの設定について

# 要約

`ulimit` で表示される `stack size` が `unlimited` の場合，スレッドを使用するプログラムを実行する際には注意が必要．
有限値が設定されている場合，おそらく，各スレッドのスタックサイズはその値が使用される事になるだろう．
しかし， `unlimited` の場合， *スレッドのスタックサイズが小さい有限値* (2MiBとの事です．[コメント](https://qiita.com/tell/items/9eed6bde9de4e8f6fd15#comment-50990667b492961cadb9)頂きありがとうございます)に設定されてしまう可能性が有る．
ここで「小さい」と書いたのは，多くの場合においてスタックサイズのデフォルト値である8192KBよりも小さいという事を指している．
また，「可能性」なので，環境によっては問題が生じない事もあるだろう．
つまり，もしも小さく設定されてしまった場合， スタックオーバーフロー(`SEGV`)が起き易くなるという事．
回避・解決手段はスタックサイズを適切な有限値に設定する事．

また， @angel_p_57 さんの[コメント](https://qiita.com/tell/items/9eed6bde9de4e8f6fd15#comment-50990667b492961cadb9)より，この現象に関するソースコードの該当部分([代入](https://github.com/lattera/glibc/blob/master/nptl/nptl-init.c#L388)，[定義](https://github.com/lattera/glibc/blob/master/sysdeps/x86_64/nptl/pthreaddef.h#L20))を教えて頂きました．
ありがとうございます．

# 実験

要点は上に書いたので，とりあえず公開する．
色々と見ているうちに，システムの情報や仕様，例外の対処関連の話が気になって来たので，備忘録も兼ねて再現実験をしようと思う．
今はたてこんでいるので，後でやる．

TODO

## 環境

TODO

# 参考文献

* [スタックオーバーフローのハンドリング (Stack Overflow Handling)](http://www.nminoru.jp/~nminoru/programming/stackoverflow_handling.html)
tensorflow.js loadLayersModelの注意点

#loadLayersModel
- tf.loadLayersModel("http://学習済みモデルのパス")　の"学習済みモデルのパス"の部分は、webサーバから提供されていないとエラーになる。
- なので、node.js expressとかを使って、学習済みモデルを提供してあげる必要がある。
- また、express側でCross-Origin Resource Sharing (CORS)をallowしてあげる必要がある。


#参考
- https://book.mynavi.jp/manatee/detail/id=99768
- https://www.tensorflow.org/js/tutorials/conversion/import_keras
Dependabotで依存パッケージ更新のプルリクを作成してもらう

# はじめに
皆さん、依存パッケージのアップデートを定期的にしていますか？
自分はGitHubのセキュリティアラートがきてからバーション確認をすることが多いです。。

そんな中、Twitterを見ていると依存パッケージ更新のプルリクを出してくれるDependabotというサービスがあるとのことでjavascriptのプロジェクトで試してみました。

# Dependabotとは
[Dependabot](https://dependabot.com/)は依存パッケージの更新を定期的にチェックし、更新があった際にプルリクエストを作成してくれるサービスです。

2019年の5月にGitHubにJoinしたことで無料で使えます😊
[Dependabot is joining GitHub](https://dependabot.com/blog/hello-github/)

## サポート言語

`2019/07/15`時点では下記言語がサポートされているようです。
<img width="697" alt="スクリーンショット 2019-07-13 0.56.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/2cc87b8d-b90b-ffd4-3e58-1c47ecf13dfa.png">

## 導入手順
### インストール

GitHubのMarketplaceから`Dependabot`を検索します。
<img width="1030" alt="スクリーンショット 2019-07-13 0.18.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/ba5ded3c-dfe1-c6b8-1390-21aa5ddae540.png">

`Install it for free`からインストールし、追加するリポジトリなどの設定を進めます
<img width="1067" alt="スクリーンショット 2019-07-13 0.20.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/a8eb8b64-5d5a-0f5e-5b22-d6b973075763.png">

### Dependabot設定
#### ダッシュボード画面
`Bump now`で即座にパッケージのチェックを行うことが可能です。
<img width="611" alt="スクリーンショット 2019-07-13 1.10.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/7729ad9e-e5f2-fa07-c7c9-19838a8fe65e.png">

#### 設定項目
Update scheduleで日毎、週毎、次毎にパッケージチェックを行うように設定も可能です。
ReviewersやAssigneesも指定できるので、自分を設定しておくことでプルリクの確認がしやすくなります。
ディレクトリや対象のbranchを指定することも可能です。

<img width="799" alt="スクリーンショット 2019-07-13 1.14.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/810c0b32-a7d6-0541-eef6-289d67cc02eb.png">

### GitHubの画面
#### プルリク一覧画面
更新パッケージがあれば`dependencies`や`security`のラベルを付与してプルリクを作成してくれます。
<img width="1008" alt="スクリーンショット 2019-07-13 0.26.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/ce2ec3e3-fd6c-7bc0-0ee7-14ab8db0fcbd.png">

#### プルリク詳細画面

Changelogでどんな内容のバージョンアップであるか確認ができます。
<img width="1015" alt="スクリーンショット 2019-07-13 1.15.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/aecc2dd8-42df-679d-ef07-1f3430b475c1.png">

プルリクのコメントからDependabotを操作することも可能です。
その為、CIを回して問題なければ自動でmergeをすることもできます。
<img width="701" alt="スクリーンショット 2019-07-13 1.15.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/a6877272-652c-fae5-699f-711d3a001bc9.png">

# おわりに
今までパッケージの更新はGitHubのセキュリティアラートがでたらバージョンアップしていました。
Dependabotを入れることで自動でプルリクを作成してくれて、バージョンアップの内容もプルリクから確認できるのは便利です。CIを実行して問題なければ自動でmergeできるのも良さそうなので、個人開発でもテストコードを書くモチベーションが高まります。

Botがプログラミングしてプルリクを投げてくる時代がくるのかも。。🧐

# 参考URL
[【Dependabot】依存パッケージが更新されてたら勝手にプルリクしてくれるやつ](https://qiita.com/nju33/items/c9962fb57749624039b3)
[依存パッケージを更新するサービス「Dependabot」で Dockerfile の更新をチェックする](https://kakakakakku.hatenablog.com/entry/2018/10/12/192502)
Stethoを使ってFlutterアプリのデバッグをする

Flutterアプリを開発していてAPIのJsonレスポンスを見やすく改行して出力する方法を探していたのでメモとして残します。
普段はhttpclientに[dio](https://pub.dev/packages/dio)を使っていますが、dioでレスポンスなどをログ出力しなくてもかなり見やすく開発することができます。


今回使ってみたのはこちらの[flutter_stetho](https://pub.dev/packages/flutter_stetho#-readme-tab-)というプラグインです。
Androidのみ対応しているので注意してください。

## 導入

pubspec.yaml に以下を追記します

```yaml
dependencies:
  flutter_stetho: ^0.2.2
```

※ 2019/07/15時点ではプラグインの実装がflutter 1.7に対応していないため
既に1.7にバージョンアップした人は修正済みのブランチを指定する必要があります。


```yaml

  flutter_stetho:
    git: 
      url: https://github.com/vanelizarov/flutter_stetho.git
      ref: flutter-1.7.8-compatibility
```

## 使い方

`runApp()`する前に`Stetho.initialize()`を書くだけでStethoのデバック準備は完了です。

```dart
void main() {
  Stetho.initialize();

  runApp(FlutterStethoExample(
    client: http.Client(),
  ));
}
```

chromeのURLバーから`chrome://inspect`を開いてアプリ名の`inspect`をクリックします。

<img width="689" alt="Screen Shot 2019-07-15 at 19.57.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236405/08a72987-1c59-04f3-8170-9732f69d28a5.png">

あとはchromeのデバックツールが開くので画像やAPIのヘッダーやレスポンスなどを表示することができます。
デバッグコンソールにログ出力しているとログが増えて、本来みたいログが見えないといったことがでてくるのででこういったツールを使うとより開発が楽になりそうです。

<img width="917" alt="Screen Shot 2019-07-15 at 19.58.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236405/36303a05-1563-480f-d7fa-96a7e74cda94.png">

早くflutter1.7対応したPRマージしてくれないかな。。

以上です。
golangでOpenCVを使おう

##投稿者の環境##
Golang version:go1.12.4
OS:Windows 10

##こんなサイトが・・・##
https://gocv.io/
Qiitaの記事で調べてみるとこのサイトのやつは無かったのでかきまーす。

##ダウンロードが必須のもの##

###まずパッケージを手に入れましょう。###
```cmd.exe
go get -u -d gocv.io/x/gocv
```

###次にMinGW-W64をダウンロードします。###
[MinGW-W64 compiler installer](https://sourceforge.net/projects/mingw-w64/?source=typ_redirect)
ここでは最新のバージョンをインストールしてください。
サイトによると7.X以上がいいらしいです。
Architechureの部分を**x86_64**にしてください。
###最後にCMakeをダウンロードします。###
[CMake](https://cmake.org/download/)
Threadsを*posix*
exceptions handlingを*seh*にします。

##パスを通す##
MinGW-W64とCMakeのパスを通します。
デフォルトだと
MinGW[C:\Program Files\mingw-w64\x86_64-7.3.0-posix-seh-rt_v5-rev2\mingw64\bin]
CMake[C:\Program Files\CMake\bin]

数字のところがバージョンにより異なる可能性があるので、そこはなんとなくで・・・
なぜか最新バージョン(8.1.0)で行くとうまくいかなかったので
うまく行かない人はバージョン落とすといいかもしれません

##Opencv Contrib Modules##
%GOPATH%\src\gocv.io\x\gocv に移動します。

```cmd.exe
win_build_opencv.cmd
```
ダウンロードとビルドが行われます。(割と時間がかかります)
その後　*opencv*　というファイルが完成しているはずです(たぶんC直下にあるはず)。
その内部にある
**C:\opencv\build\install\x64\mingw\bin**
をパスに設定します。
##確認##
最後にパスが通っているか確認するために
gocvのディレクトリに移動し、下記のコマンドを実行します。

```cmd.exe
go run cmd\version\main.go
```
実行結果にgocvとopencv libのバージョンが返ってくれば成功です。

##最後に##
パス通した後は再起動してね、
import するときは**gocv.io/x/gocv**でおｋ
GOPATH忘れたら　go env GOPATHで教えてくれます。
間違っているところがあったら教えてください。
最後まで出来た方はぜひ　いいね　をお願いします。
##参考文献##
https://gocv.io/

###追記###
2019/10/15 わかりにくい部分があったので修正しました。
爆速でFacebookのconsoleのマネをする

<img width="665" alt="スクリーンショット 2019-07-15 20.10.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244632/37f2f9fc-a4c9-dfc1-f991-9403f840b552.png">

タイトルは半分釣りです。
Facebook、 ~~陰キャの皆さん以外は~~ 使ってますよね。
Facebookの画面でブラウザの開発者コンソールを開いたことはありませんか？

<img width="659" alt="スクリーンショット 2019-07-15 20.13.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244632/b91411ef-ae86-974e-d214-3e699c207b30.png">

そう。これこれ。
実はこれ、自分で簡単にできちゃうんです。
一番最初の画像と同じものを作るには、

```javascript
    console.log(
      '%cWARNING!',
      'font: 5em; color: white; background-color: red; padding: 12px;'
    );
    console.log(
      '%cこれは開発者向けのブラウザー機能です。Snovel機能を有効にするためまたは誰かのアカウントをハッキングするために、ここに何かをコピー・貼り付けするように言われた場合、それは第三者があなたのSnovelアカウントへのアクセスを得るための詐欺・不正行為です。',
      'font-size: 2em; color: red; line-height: 1.25;'
    );
```

これだけ。
EC2 Instance Connect についてまとめてみた

# はじめに
Qiitaでの初投稿です。
EC2 Instance Connectを調べる機会があったのでまとめてみました。

# EC2 Instance Connectとは
EC2 Instance Connectとは、ざっくり言うとEC2に**簡単に、安全に**SSH接続できるサービスという感じ。
- IAMによる接続制御ができる
- マネジメントコンソールから接続できる
- CloudTrailで接続リクエストを監査できる
が大きな利点でしょうか。
**対応しているOSは現在、AmazonLinux2とUbuntu 16.04以降**のみ対応。

Instance ConnectでSSH接続する方法は大きく分けて以下の2つがあります。
### 1. マネジメントコンソールから接続  
上にも書いた通り、マネジメントコンソールからSSH接続ができ、IAMロールによって接続制御ができます。
ただし注意点として、2019年7月現在、接続するEC2のキーペア発行が必須。
使わないのになぜ。。
### 2. CLIから接続  
任意のSSHクライアントで接続できます。
こちらの場合、接続する際にInstanceConnectのAPIが1回限り(しかも６０秒間だけ)有効な公開鍵が生成されるため、セキュリティを強化できます。
こちらはキーペアなしで接続できるため、キーペアの管理が不要になります。
ただし、キーペアを発行したインスタンスへの接続はこの方法ではできないみたいなので、EC2 Instance ConnectをコンソールからCLIからとどちらも行うのは無理っぽい。  

# セッションマネージャーとの違い
マネジメントコンソールからSSHできるって、セッションマネージャーと何が違うのって思った方も多いのではないですかね。私も思いました。

そもそも、セッションマネージャーで接続した場合、ログイン状態ではないんですよね。
なので、接続時に**`.bashrc`が読み込まれない**ということがデメリットでもあります。

また、EC2 Instance Connectで接続を行う際はネットワーク経由での接続となるため、EC2はパブリックサブネットに配置し、パブリックIPを割り当てる必要があります。
それに対してセッションマネージャーでは、PrivateLinkを経由させることでプライベートサブネットに配置したEC2にも接続が可能になります。

さらに、セッションマネージャーではセッション操作ログをS3またはCloudWatchLogsに出力することができるため、実行コマンドや出力結果をAWS上にログとして簡単に保存することができるというのもメリットです。(ただし、OS自体にログは残らない)

まとめると
####セッションマネージャー
* プライベートサブネットに配置したEC2に接続可能
* 操作ログをAWS上に簡単に取得できる(OSにログは残らない)
* 接続時、ログイン状態ではない

#### EC2 Instance Connect
* パブリックサブネットにインスタンスを配置し、セキュリティグループとIAMによる接続制御が必要
* 1回限りの公開鍵が生成され、接続できる
* CloudTrailに接続記録が残る(操作ログはAWS上には残らない)

どちらもメリット・デメリットがあるため、状況に応じて使い分けてください。

# セキュリティグループの設定
上のまとめでちらっと書きましたが、EC2 Instance Connectの接続制御は、セキュリティグループでも制御する必要があります。

マネジメントコンソールでの接続の場合、ユーザーのリージョンからのSSHを許可する必要があります。結構大きく開ける必要があるので注意してください。
リージョンのIPは[ここから確認できます](https://docs.aws.amazon.com/ja_jp/general/latest/gr/aws-ip-ranges.html)。(2019年7月現在東京リージョンのIPは`3.112.23.0/29`)

CLIから接続する場合、接続元のIPからのアクセスのみ許可すればOKです。


# 最後に
本当は使い方まで書きたかったんですが、特徴書いてみると結構あったので次回に回します。
使ってみると、Instance Connectもっと使いやすくなればな、という印象でしたが、やはり鍵の管理が不要になるのは便利ですし、IAMでのSSH制御等、新たな価値観が作られて行くようで個人的にとても面白かったです。今後のアップデートにも期待です。


今回、こちらのサイトを参考にさせていただきました。 
[Amazon EC2 Instance Connect のご紹介](https://aws.amazon.com/jp/about-aws/whats-new/2019/06/introducing-amazon-ec2-instance-connect/)
[Connect Using EC2 Instance Connect](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-connect-methods.html)
[EC2 Instance Connect の特徴や注意点についてまとめてみる](https://qiita.com/hayao_k/items/7b44ed1cd11651272985)
論文まとめ：PersonLab: Person Pose Estimation and Instance Segmentation with a Bottom-Up, Part-Based, Geometric Embedding Model

# はじめに

ECCV 2018 から以下の論文のまとめ
G. Papandreou, et. al, "PersonLab: Person Pose Estimation and Instance Segmentation with a Bottom-Up, Part-Based, Geometric Embedding Model"

モデルのアーキテクチャやdecoder部分のみまとめる。

arXiv:
https://arxiv.org/abs/1803.08225

github:
github上には既にいくつかコードがあり、例えば以下のKeras実装
https://github.com/octiapp/KerasPersonLab
は星が多い。

# 概要 
1. ボトム・アップ方式で同時に多人数に対し pose estimation を行うモデル
2. keypoint の検出と同時に人のインスタンス・セグメンテーションを行い、これらを統合してインスタンス・セグメンテーションまで行う
3. COCO dataset で既存のボトム・アップ手法を上回る精度を達成した


# 手法の全体像 
以下の図が全体像

<img width="668" alt="personLab_img00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/2e64e0eb-d472-7485-66bc-ac11acb180be.png">

解説にあるように、左の入力画像に対してCNNで以下の５種類を出力する。
1. 各 keypoint の位置を推定する heatmap
2. 上記推定位置の short-range な offset
3. 同上推定位置の middle-range な offset （四肢の形成に用いる）
4. 人のセグメンテーションマスク
5. keypoint 推定位置の long-range な offset

図中、上側に着目すると、最初の３つの出力により各人の姿勢を推定する。

図中下側で、この姿勢と出力４番目、５番目から人のインスタンスレベルのセグメンテーションを行う。

# 各人の姿勢推定
## 1. keypoint を検出する

ここは基本的に文献[2]の手法と同じ。

まず各種定義

$x\_i$ ：画像上の $i = 1 , \ldots , N$ ピクセルにおける位置。

```math
\mathcal{D}_R(y) = \{ x: \| x-y \| \leq R \
```
は $y$ を中心とし、半径 $R$ の円内。

$y\_{j,k}$ ：$j$ 番目の人の $k$ 番目の keypoint。

CNNからの１番目の出力である heatmap $p\_k (x)$ では、ピクセル $x$ が $x \in \mathcal{D}\_R(y\_{j,k})$ なら１、それ以外は０を推定する。$R$ は定数 32 pixel を使用。

CNNからの２番目の出力である short-range offset $S\_k(x)$ では、近傍の keypoint の位置をベクトルで指し示す。つまり

```math
S_k(x) = y_{j,k} - x
```

近傍の範囲はやはり $R = 32$。

heatmap $p\_k (x)$ と short-range offset $S\_k(x)$ から hough-voting で詳細なkeypoint の位置を求める。

```math
h_k(x) = \frac{1}{\pi R^2} \sum_{i=1:N} p_k(x_i) B (x_i + S_k(x_i) - x)
```

$B(\cdot)$ は bilinear kernel。$x_i + S_k(x_i) = y\_{j,k}$ は $x\_i$ が推定するkeypointの位置なので、$x_i + S_k(x_i) - x$ は $x$ から $x\_i$ のkeypoint推定位置へのベクトル。これに対して bilinear kearnelをかける。

それに対して $p_k(x_i)$ をかけるので、おおよそkeypointの半径 $R = 32$ ピクセルだけ集計することになる。

集計したものを面積 $\pi R^2$ で割って規格化。

ということで、ざっくり言うと、heatmapの推定したkeypoint周辺領域に関してshort-range offsetの指し示すkeypointの位置を集計することで正確な位置を推定する感じ。

<img width="900" alt="personLab_img20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/4cb3239b-69d7-7d83-ac8d-3ba0a4ee9f5d.png">

## 2.keypoint を関連づけて骨格にする

ここでは出力に３番目 middle-range な offset $M\_{k,l}(x)$ を用いる。ここで $k,l$ は keypoint $k$ から keypoint $l$ への四肢という意味。具体的には 

```math
M_{k,l}(x) = (y_{j,l} - x)I \left( x \in \mathcal{D}_R (y_{j,k})\right)
```

のように、$j$ 人目の keypoint $k$ の半径 $R$ 内のピクセルに対し、それと関連する keypoint $l$ の位置をベクトル $y\_{j,l} - x$ で表す。

更に、以下の図

<img width="651" alt="personLab_img01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/9250514f-7536-4085-29ee-6045b3adfbe9.png">

のように、出力２番目 short-range な offset を利用して keypoint $l$ の位置精度を上げる。

具体的には

```math
M_{k.l}(x) \leftarrow x' + S_l (x'), \ where \ x' = M_{k,l}(x)
```

とする。つまり、$x$ 位置の指し示す対応する keypoint 位置である $M\_{k,l}$ ピクセルに注目し、このピクセルの short-range offset として指し示す keypoint 位置 $S\_l (x')$ で更新することで、更に精度の高い位置を得る。この作業を２周繰り返す。

<font color="red">書きかけ</font>



# reference  
[2] G. Papandreou, et. al. "Towards Accurate Multi-person Pose Estimation in the Wild"
Cで正規表現を使う

正規表現で使う関数は次のように定義されている。
これらを使って正規表現をつかった検索を行う。

```C
#include<regex.h>
int regcomp(regex_t *preg, const char *regex, int cflags); 
int regexec(const regex_t *preg, const char *string, size_t nmatch,regmatch_t pmatch[], int eflags);
size_t regerror(int errcode, const regex_t *preg, char *errbuf,size_t errbuf_size);
void regfree(regex_t *preg);
```

### step1
まず、regcompを使って正規表現文字列をregexecで使えるようにコンパイルを行う。
regexに正規表現文字列を指定し、コンパイルされたものはpregに格納される。
cflagはregexecに対して影響を与えるフラグである。意味は以下の表の通り。

| cflag        |意味                                           |
|--------------|:----------------------------------------------|
| REG_EXTENDED |拡張正規表現で検索を行う。                         |
| REG_ICASE    |大文字小文字を無視する。                           |
| REG_NOSUB    |マッチした位置を教えない。                         |
| REG_NEWLINE  |全ての文字にマッチするオペレータに改行をマッチさせない。|

### step2
次に、regexecを使って検索を行う。

pregにはregcompでコンパイルしたものを検索範囲となる文字列を指定する。
nmatchとpmatch[]はマッチした位置を取得するために使用するもの。
eflagsはregexecに対して影響を与えるフラグである。意味は以下の表の通り。

| eflag        |意味                                           |
|--------------|:----------------------------------------------|
| REG_NOTBOL   |行頭にマッチするオペレータが失敗する。               |
| REG_NOTEOL   |行末にマッチするオペレータが失敗する。               |

regexecは失敗時にREG_NOMATCHを返す。
マッチする文字列が無い場合もREG_NOMATCHを返す。

### step3

regcompはregex_t構造体の中にマロックした領域を保存するようになっているため、これを解放するためにregfreeで最後に解放する。

### エラー処理

regcompは失敗時にはエラーコードを返すようになっている。
このエラーコードを文字列化するにはregerrorを使う。

## 例

grepコマンド的なものを作ってみる。

```C:example.c

#include <stdio.h>
#include <stdlib.h>
#include <regex.h>

int main(int argc, char *argv[]) {
	if (argc != 3) {
		fprintf(stderr, "usage:\n%s PATTERN FILENAME\n", argv[0]);
		exit(1);
	}

	int err;
	char err_str_buf[4096] = {0};

	// STEP1
	regex_t patbuf;
	err = regcomp(&patbuf, argv[1], REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
	if (err != 0) {
		regerror(err, &patbuf, err_str_buf, sizeof(err_str_buf));
		fprintf(stderr, "regcomp: %s\n", err_str_buf);
		exit(1);
	}

	FILE *fp;
	char buf[1024] = {0};
	fp = fopen(argv[2], "r");
	if (fp == NULL) {
		perror(argv[1]);
		exit(1);
	}
	//STEP2
	while(fgets(buf, sizeof(buf), fp)) {
		if (regexec(&patbuf, buf, 0, NULL, 0) == 0) {
			fputs(buf, stdout);
		}
	}
	//STEP3
	regfree(&patbuf);
	fclose(fp);
	return 0;
}

```

実行結果

```
$ gcc -o example_program example.c
$ ./example_program reg.* example.c
#include <regex.h>
    regex_t patbuf;
    err = regcomp(&patbuf, argv[1], REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
        regerror(err, &patbuf, err_str_buf, sizeof(err_str_buf));
        fprintf(stderr, "regcomp: %s\n", err_str_buf);
        if (regexec(&patbuf, buf, 0, NULL, 0) == 0) {
    regfree(&patbuf);
```

# 参考
https://linuxjm.osdn.jp/html/LDP_man-pages/man3/regex.3.html
Microbit:DC motor制御（DFROBOT DFR0548ボード）その2

前回 [Microbit:DC motor制御（DFROBOTボード）](https://qiita.com/Gyutan/items/08182be2eea552bbed64)、DFRobotのDFR0548（4chDCモータドライバー）を使ったロボットの無線制御について紹介しました。
今回は、そのプログラムを改良して、モータースピードを変えられるようにしました。
送信側と受信側のそれぞれのプログラムです。

### 送信側
![controllor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165987/6de79ce0-c832-c3c1-bd90-1a6a4f17190b.png)

#### 送信側コード解説

`最初だけ`のブロック中に`無線グループの設定`と`無線で送信`でspeedの値を送信ます。
speedは0から255の値ですが、今回255をHighSpeed、125をLowSpeedとしました。
`ボタンA`の中に無線でspeedの値を送信の値として125をセットします。
`ボタンB`も同様に255をセットします。
これで、Aボタン、Bボタンを押すことでspeedを変えることができます。
後は、前回の記事と同じように、各ジェスチャーに対応するコントロール番号を無線で送信します。

### 受信側
![reciver.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165987/ce7f4511-b7c1-4fe3-5073-0364876e5691.png)

#### 受信側コード解説

`最初だけ`のブロック中に`無線グループの設定`を行います。
送信側の最初だけブロックの中に入っていたspeedの値を受信します。
受信した値をspeedという変数に格納します。

※変数はスコープなどが気になりますが、ここではGlobal変数として取り扱っています。Global変数は、書き込むところを1か所にするのが理想です。

また、各ジェスチャーに対応して送られてくる番号に対応したアクションを行います。
アクション（例えば：前進「Forward」）について、その動作をまとめた関数を作ります。
これまで、関数に引数は取れなかった？のですが、引数が取れるようになりましたので、引数を入れた関数を作成します。
![関数引数.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165987/1e833771-a7a7-ee46-3da7-648145e9156f.png)
数のところにspeedで受け取った値が入ることになります。

※関数を作成すると自動的にブロックが一番上に配置されます。JavaScriptのコードを見ればわかると思いますが、上からプログラムが実行されます。
※右上にある`ボタンAが押されたとき`のブロックは、受信プログラムが動作するかのテスト用に作ったものなので、不要ならば削除してください。

### 完成して搭載したロボット
前から
![P_20190715_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165987/74bf41fb-e304-72d6-cef5-e1cf01e7c64c.png)

後ろから
![P_20190715_184915.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165987/689678c6-340c-f19e-ad88-9156232eac9d.jpeg)
[python]算数・数学⑤~集合と順列と確率~

# 前回まで
[前回はこちら](https://qiita.com/hiroyuki_mrp/items/44b350c371754006af06)

# 改めて
機械学習を始めるにも、算数や数学がわからないと、入門書すら読めない。ただそこまで、ちゃんと解説してあるものもない。ということで最低限必要な数学基礎をこの記事で書けたらいいなと思っています。

# 環境
ほぼ影響ないですが、python3系を利用。

# 前提
四則演算や累乗（2乗とか3乗とか）がわかっていること。

# 集合

集合とは以下のようなものを言います。一つ一つは要素と言います。
{1,3,5,7,9}

10以下の奇数を要素として集合を記述するときに
{1,3,5,7,9}
という書き方と
{x|xは10以下の奇数の自然数}
という書き方ができます。

要素xが集合Aに属してることを$x\in{A}$と記述します。$1\in{A}$ですし$2\in{A}$ですね。

なお
A = {1,2,3,4,5,6,7,8,9,10}つまり{x|xは10以下の自然数}
B = {1,3,5,7,9}
とあったときに、BはAの部分的な集合（部分集合）と言えるので、$B\subset{A}$もしくは$A\supset{B}$	とすることができます。


pythonでかいてみます。

```py
a = {1,2,3,4,5,6,7,8,9,10}
b = {1,3,5,7,9}
#ちなみにset型となっています。
type(a)　#->set

b <= a    #->True
```

集合の要素を変えてみます

```py
a = {1,2,3,4,5,6}
b = {5,6,7,8,9,10}

a|b#和集合：合体させて重複無くしたもの
->{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

a&b#積集合：重複しているもの
->{5,6}

a-b#差集合:aにあってbにないもの
->{1, 2, 3, 4}

b-a#差集合:bにあってaにないもの
->{7, 8, 9, 10}

a^b#対象差:aもしくはbにしかないもの
->{1, 2, 3, 4,7, 8, 9, 10}

#集合に要素を追加:add()
#集合から要素を削除: discard(), remove(), pop(), clear()
```

# 順列

懐かしきこういうやつ。
${}_n P_r　= n\times(n-1)\times(n-2)\times(n-3)\times・・・\times(n-r+1)$

7個から3桁を作る場合は

${}_{7} P_3　= 7\times(7-1)\times(7-2)=7\times6\times5=210$
となる。

```py 
import itertools
num = {1,2,3,4,5,6,7}
a = set(itertools.permutations(num,3))
len(a) # -> 210
```

# 階乗

7個から7桁を作る場合は

${}_{7} P_7 = 7!= 7\times6\times5\times6・・・\times1=5040$

```py
b = set(itertools.permutations(num,7))
len(b) #->5040

import math
math.factorial(7)#->5040
```

# 重複順列(一度選んだものを再度選べる場合)

${}_n \Pi_r = n^r$

７つの数字を１つずつ選んで戻して3桁を作る場合

${}_7 \Pi_3 = 7^3$

```py
#7個の数字から１つずつ３回選ぶ
num = {1,2,3,4,5,6,7}
a = set(itertools.product(num,num,num))
len(a)
# -> 343
```

# 組み合わせ(Combination)

順番を考慮しないものです。
つまり（1,2,3）と（3,2,1）を同じものとみなします。

${}_nC_r=\frac{nPr}{r!}$

例えば５つの数字から３つの組み合わせを作る

${}_5 C_3 = \frac{5\times{4}\times{3}}{3\times{2}\times{1}}$

```py
num = {1,2,3,4,5}
p = len(set(itertools.permutations(num,3)))
f = math.factorial(3)#階乗
com = p/f
com #-> 10.0

もっと簡単に以下のメソッドで出来る
c = set(itertools.combinations(num,3))
len(c)
```

### 二項定理

3次関数を考える。
```math
(a+b)^3 = a^3 + 3a^2b+3ab^2+b^3
```
これを場合の数の問題として考える。
本来の式で考えなおす。
```math
(a+b)^3 = (a+b)\times(a+b)\times(a+b)
```

たとえば$a^2b$の項が作られるのは、３つの(a+b)のなかのどれかから、それぞれaを2回とbを1回選ぶ行為になる。
つまり3パターンあるということになります。なので係数は3になります。
逆に$a^3$や$b^3$となるのは、1パターンしかないということになる。係数は１になります。

この考えで4次関数を考えると

```math
(a+b)^4 = _4C_0 a^4 + _4C_1 a^3b + _4C_2 a^2b^2 + _4C_3 ab^3 + _4C_4 b^4
```
これを一般化したのが二項定理になります。



# ここまで

ここまで。確率については結構雑な感じになっていますが、違う投稿で、尤度の説明でもう少し具体的にしていきます。

[次回](https://qiita.com/hiroyuki_mrp/items/d373b951e216f62c4957)は微分について投稿していきます。
EC2上のMySQLをsequel proを使って表示する

#本番環境のDBもsequel proで見やすく表示したい！
ところどころ、これどこから設定するの？というところがあったので画像つきでまとめてみました。

#設定手順
`sequel pro`を開いたら左下の`+マーク`をクリックします
![スクリーンショット 2019-07-15 18.46.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406531/b4d5058f-2af0-b850-2db2-eb5ab73e1c50.png)

こんな感じに新規の設定ができるようになります。
現在は`ソケット`タブが選択されているので`SSH`をクリックしてSSHタブを開きましょう
![スクリーンショット 2019-07-15 18.46.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406531/e5fe7dd7-924e-7fc4-7a17-ade90a306b28.png)

下の画像のように設定項目が出てきます（項目が少なく表示される場合は一旦他のタブを選択してからSSHタブを選択し直してみてください）

![スクリーンショット 2019-07-15 18.55.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406531/f9b2a611-cc88-5142-c52a-c6d814386f4e.png)


##設定項目説明
- 名前：  awsとかEC2とかお好きな名前に
- ユーザ名：root(デフォルトだとroot、変更している場合はそちらのユーザ名)
- パスワード：EC2上のMySQLのrootユーザのパスワード(同じく変更している場合はそちらのパスワード)
- データベース：記入なし
- ポート：3306
- SSHホスト：EC2で設定した`Elastic IP`の数字部分
- SSHユーザ：ec2-user
- SSH鍵：EC2インスタンスの秘密鍵をファイル選択(sshでサインインするときに使うhoge.pem)
- SSHポート：記入なし
- SSLを使用して接続：チェックなし


最後にお気に入りに追加してから接続(お気に入りに入れないとまた設定し直しになります。
無事接続できれば成功です！！

#感想

設定してみると意外と簡単に接続できました。
これでSQL文打つのから少し開放されますね！
CUIで操作する場面では[Mycliの導入](https://qiita.com/shojimotio/items/efc8fce9ce3ebe179897)をおすすめします。

#参考
####[Sequel PRO：データベースに接続する方法](https://qiita.com/iwaseasahi/items/e245e61da4b7613494c5)
Revealと脱獄したiOSデバイスで他人のアプリUIレイアウトを見る

## Revealとは
iOSとtvOSのUI構築&デバッグツール
公式サイト(英語)：https://revealapp.com

## Reveal料金
14日無料体験
個人ライセンスは59ドル/年、学生なら30%OFF。

## インストール方法

ダウンロードリンクはメールで送ります。

またはHomebrew Caskでインストール：

```sh
brew cask install reveal
```

## インテグレート方法

[公式ドキュメント](https://support.revealapp.com/hc/en-us/articles/360022818251-Integrating-Reveal-with-your-iOS-application)

要はReveal.frameworkをiOSアプリに導入します。USB又は同じWi-Fiネットワークでデバッグできます。Xcodeで操作しなければならないので、ソースコードが必要であることです。

脱獄したiOSがあれば、ソースコードが無くてもインテグレートできます。

## 脱獄方法

現時点iOS 12.2までは脱獄可能です。
使うプロジェクトは unc0ver ([GitHub](https://github.com/pwn20wndstuff/Undecimus))。

## 脱獄したiOSでインテグレート方法

マニュアルで導入する方法に興味があれば、[Peter Steinberger氏](https://twitter.com/steipete)の記事[How to Inspect the View Hierarchy of Third-Party Apps](https://petersteinberger.com/blog/2013/how-to-inspect-the-view-hierarchy-of-3rd-party-apps/)を参照してください。

手順を短くするには、CydiaパケッジRevealLoaderを使います。

RevealLoaderが古くなり、最新版Revelに対応しないため、私が[修正したGitHub fork](https://github.com/HackingGate/Reveal2Loader)を使いましょう。

Xcode 9,10,11に対応させたforkです。いずれのXcodeバージョンを用意してください。

```sh
git clone https://github.com/HackingGate/Reveal2Loader.git
cd Reveal2Loader
```

パケッジ(.deb)をコンパイルします。

```sh
make clean
make
make package
```

脱獄したiOSデバイスのIPアドレスを確認ください。本記事は`192.168.2.2`にします。

コンパイルしたパケッジ(.deb)をiOSデバイスにアップロードします。`naville.revealloader2_1.0.0-1_iphoneos-arm.deb`は先ほどコンパイルしたファイル名です。

```sh
scp releases/debs/naville.revealloader2_1.0.0-1_iphoneos-arm.deb root@192.168.2.2:~/
```

SSHログインします。

```sh
ssh root@192.168.2.2
```

パケッジ(.deb)をインストールします。

```sh
dpkg -i naville.revealloader2_1.0.0-1_iphoneos-arm.deb
```

最後に`Setting up...`が表示したら、インストールは成功です。

## 他人のアプリをインスペクトします

設定を開いて下さい。

<img width="320" alt="IMG_0011.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165985/e1eee86d-65e7-8a71-b268-3c80d5ee79d9.png">

Reveal -> Enabled Applicationsでインスペクトしたいアプリをenableします。

<img width="320" alt="IMG_0012.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165985/a2337280-5fc2-38f0-d73d-31b64305cdc7.png">

Enableしたアプリを開いたら、Revealで表示されます。

## インスペクト例

App StoreのUIレイアウト画像です。UICollectionViewを利用していることが分かりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165985/16fe1123-0f5d-9178-358a-a08d5b3df517.png)

RevealはUIKit以外で開発されたアプリはインスペクトできません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165985/f0782e26-2f59-1e8f-31ce-ae573243bbc0.png)

Pinterestは[ASCollectionView](https://github.com/abdullahselek/ASCollectionView)を利用しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165985/4ff2ec65-1376-54f6-8a08-9b38b860c7aa.png)