OmniAICreator/Qiita-1.07M huggingface dataset:
初心者エンジニアがステップアップのためにすべき４つのこと

## はじめに
RubyやPythonの本を読み終えて、フレームワークのチュートリアルも終わらせたぞ！みたいな人が対象です。

「なんとなくコードの書き方の感覚はついてきた！でも、仕事で使えるような気がしないんだけれど...？」という状態を抜け出す方法を書いていきます。

## 1. まずはとにかく作ってみること
人間は忘れる生き物なので、学んだことも使わなければ穴の空いたバケツのように流れていってしまいます。
けれども、覚えたことも繰り返し思い出していけば、段々と記憶に定着していきます。
（[エビングハウスの忘却曲線](https://ja.wikipedia.org/wiki/%E5%BF%98%E5%8D%B4%E6%9B%B2%E7%B7%9A)なんてものがあります。）

そこでオススメなのが、**実際に簡単なサービスを作ってみる**ことです。[1]

学んだ知識をフル活用するため、作業のすべてが復習になるからです。
このタイミングで陥りがちなのが「**本やチュートリアルで勉強した内容を全然覚えておらず、自分には才能がないんだと卑下してしまう**」ということかもしれません。
ぶっちゃけた話、現時点で完璧に覚えている必要がありません。
むしろ、これらの教科書を「**自分の辞書として活用してやる**」という気概でいましょう。
「XXをやりたいときにはこのページの内容を読めば良いや」と頭の中にインデックスするくらいがちょうど良いのです。
こういった知識は書くことを繰り返していくうちに、本を参照せずに書けるようになっていきます。

とにかく開発をしてみましょう！

## 2. コードは読めるものだと知る
「**[リーダブルコード](https://www.oreilly.co.jp/books/9784873115658/)を読むといいよ！**」という話でございます。

この本は**コードの意図を他の人に伝えるためのエッセンスを詰め込んでいる本**です。
「そもそも、コードを意図して書けないしまだ読むの早いかな...」と敬遠しがちかもしれません。
ですが、初心者こそ本書を読むことで「**コードは暗号の羅列じゃなくて、ちゃんと読めるものなんだ！**」ということをわかるのですごく良い本なのです。
コードが読めるようになると、ロジックがどのような意図で書かれているのかがわかるようになります。
それができるようになると、すごいエンジニアたちの技術の結晶であるOSSのコードを参考にできるのです。[2]
（Rails製のOSSを例に出すと、GitLabやRedmine、dev.toとか...、これらのコードを読むだけで勉強になります。）

なので、本書を早いうちに読んでおくことは後々ジワジワと効いてきます。
ホントにいいことづくめなので、オススメなんです。
騙されたと思って読んでほしい。

## 3. 抽象的な視点を持つこと
「Webアプリケーションを作るぞ！」と意気込んで、Webアプリ開発をググると「Rails、React、AWS、...」と勉強にしなきゃいけないことがたくさん現れて「無理だ〜！」って気持ちになります。

技術を俯瞰してみると意外と**繋がっていたり似通っていたり**しているのです。
一つの技術がしっかりとわかっていると、そこを手がかりにして芋づる式に学べるようになっていたりします。

なので、すべてを暗記しようと思わず、ふと立ち止まって「自分が知っている技術と繋がっている部分はないだろうか？」とか「似ている部分はないだろうか？」と考えてみるとよいかもしれません。

そして、意外に大事なのは「**なぜ、そうなっているのだろうか**」というのを調べることです。
様々な技術が繋がっていたり、似通っていたりするのには理由があるからです。
そして、その**なぜ**の答えは重要なことだったりするのです。

「そんなことを言われても、どうすれば...」と思うので、抽象的な視点で技術を見るのに私が参考している本があります。
西尾泰和さんの『**[コーディングを支える技術](http://gihyo.jp/magazine/wdpress/plus/978-4-7741-5654-5)**』という本です。
本書は**プログラミング言語**を題材に、いろんな言語に搭載されている機能が存在する理由を教えてくれます。
「**プログラミング言語ってたくさんあるけれど、本質はどれもみんな似たような感じなんだね〜。**」ということが学べます。

プログラミング言語に限らず、技術の学習中に「コレは僕の知っているアレと似ているな、なぜだろう」と調べてみると、意外な理由やテクニック、プラクティスが隠されていることがわかるかもしれません。

## 4. 設計の重要性を学ぼう
アプリケーションは複雑になってくると勢いで書けなくなってきます。
最初は勢いだけで書けていたアプリケーションも、ある時を境に一つの変更をしたら「あちこちが壊れたりして大変！」って状況になったりするかもしれません。
それを事前に避けたり改善したりするのに必要なのが**設計**なのです。[3]

オブジェクト指向設計について学べる本は星の数ほどあると思いますが、はじめの1冊にオススメの本があります。

Sandi Metzさんの『**[オブジェクト指向設計実践ガイド](https://gihyo.jp/book/2016/978-4-7741-8361-9)**』という本です。
とにかく**実践的な学び**に重きをおいていて、話を追って写経していくだけで「設計ってなんぞや。」ということがわかると思います。
本書を読み終わった頃には、**設計の考え方、設計の原則、動的型付き言語のオブジェクト指向テクニック、リファクタリングテクニック**が身についていることだと思います。

サンプルコードにはRubyが使われていますが、PythonやPHP7、JavaScriptのようなオブジェクト指向で開発できる動的型付き言語を使っているのであれば、読めると思いますし問題なく学べると思います。

## 最後に
Railsチュートリアルを終えた頃の自分にアドバイスを送るとしたら、と思って書きました。
次は何を学んでいけばいいんだろうと悩んでいる初心者エンジニアに道しるべになれば良いと思います。

[1]: 「簡単なサービスって言っても思いつかない！」って人には、TwitterのようなSNSと連携して遊べるようなネタサービス（XXXメーカーみたいなモノ）を作ることをオススメします。
[2]: 自分が使っているフレームワークなどで作られたOSSを参考にできるようになるので、成長速度がものすごく高まります。
[3]: オブジェクト指向設計に限るとマサカリ飛びそうですけど、駆け出しエンジニアさんが使っているであろうPythonやRuby、JavaScriptはオブジェクト指向なので...。
jQurey スクロールだけで要素を下からfadeInさせる方法

#スクロールだけで要素を下からfadeInさせながらる方法

webサイトでよく見かける、スクロールしていって可視範囲に入ればフェードインを行う。
今回はそのコードを書いていきます。

##ゴール
スクロールさせて、指定した要素をフェードインさせる。

##考え方
・指定した要素を隠す
・スクロールさせる
・フェードインさせる

##コード
```index.html
 <div class="fadein">
    <div>子要素</div>
    <div>子要素</div>
    <div>子要素</div>
    <div>子要素</div>
 </div>

```

```style.css
 .fadein {
  opacity: 0;
  transform : translate(0, 50px);
  transition : all 1500ms;
}

.fadein.scrollin{
  opacity: 1;
  transform: translate(0, 0);
}


```

```javascript
 $(window).scroll(function (){
    $('.fadein').each(function(){
        var elemPos = $(this).offset().top,
            scroll = $(window).scrollTop(),
            windowHeight = $(window).height();
          if (scroll > elemPos - windowHeight + 100){
              $(this).addClass('scrollin');
            }
        });
    });

```

##解説
htmlは見ての通りです。
CSSで、transform : translate(0, 50px);を指定し、縦方向に50px下げておきましょう。ここで下げることによって、フェードインさせた時、下から上がってくるようになります。
そして、opacityを0にして見えないようにしましょう。
transition : all 1500ms;は変化させる要素の数と時間です。今回は全ての要素を1,5秒かけてフェードインさせます。

次はjQueryで動きをつけていきます。
スクロールしたときの動きをつけたいので、windowオブジェクトに対し、scrollメソッドを用います。

そうしたら、必要な高さを各変数に代入していきましょう。
各高さのイメージはこちら。
![フェードイン.png](https://qiita-image-store.s3.amazonaws.com/0/302326/7f566e8b-b0f2-4bba-16ec-3fce4b4d27df.png)


ifを用いこのような分岐にします。

***if (scroll > elemPos - windowHeight + 100){}***

これを訳すとこうです。
**"スクロールした量 > 要素からtopまでの高さ - ブラウザの高さ + 100"**
となります。

![フェードイン2.png](https://qiita-image-store.s3.amazonaws.com/0/302326/59efece2-4fbc-4661-12e8-7ab6f0e7ec3d.png)

最後の+100は余白です。
あってもなくても構いませんが、ないと要素に差しかかったらすぐフェードインを始めるようになります。

あとは、addClass(.scrollin)でクラスを追加し、
.fadein.scrollin{
  opacity: 1;
  transform: translate(0, 0);
}
と指定することで、フェードインさせることができます。

##まとめ
要素が変わっても、要素からの高さとブラウザの高さを求めればこの方法で実装は可能です。
pandasのgroupbyでグループ化した文字列を結合する

# はじめに
データベースのデータを整理しているときに、文字列型のカラムに入っている値をグループごとに結合したい場面がありましたので、メモとして残しておきます。


# 参考
- Pandas：グループ毎に括って最大の値を含む列を抜き出す
http://publicjournal.hatenablog.com/entry/2017/10/08/113544

- additional positional arguments
https://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.apply.html

- 時刻の計算と関数のDataFrameへの適用
https://qiita.com/Sasagawa0185/items/1185933dd0e560a26b07

# 環境
- Google Colabratory
- pandas==0.22.0

# 手順
次のようなデータを考えます。

```python
import pandas as pd

df = pd.DataFrame({
    'id':['1','2','2','2','3','3'],
    'tag':['a','a','b','v','s','j'],
    'value':['70','23','64','23','12','9']
    })
```
データフレームは下記の形になります。

|  | id | tag | value |
|--:|:---:|:---:|:---:|
| 0 | 1 | a | 70 |
| 1 | 2 | a | 23 |
| 2 | 2 | b | 64 |
| 3 | 2 | v | 23 |
| 4 | 3 | s | 12 |
| 5 | 3 | j | 9 |

例えばidはユーザidで、tagは何らかの特徴を表す値、valueは支払い金額だとします。

ユーザごとグルーピングして支払い金額を集計しつつ、tagの値も残したいとします。
そこで、tagの値はアンダースコアで結合して残すことにします。

pandasでグループ化したのち、`list`をapplyすると、tagをリスト化してレコードに持つことができます。リストの中身をソートして、アンダースコアでjoinします。

```python
result = (df.groupby('id')['tag']
          .apply(list)
          .apply(lambda x:sorted(x))
          .apply('_'.join)
         )

# 下記でもOK
# result = df.groupby('id')['tag'].apply(lambda x: '_'.join(sorted(list(x))))
# または
# result = df.groupby('id')['tag'].apply(lambda x: '%s' %
#                                        '_'.join(sorted(list(x)))).reset_index()
```

下記のように結合されます。

|  | id | tag |
|--:|--:|:--|
| 0 | 1 | a |
| 1 | 2 | a_b_v |
| 2 | 3 | j_s |


元のデータフレームと同じサイズにする場合。

```python
result = df.groupby('id')['tag'].transform(lambda x: '_'.join(sorted(x.tolist())))
```

# おわりに
文字列にもgroupbyを使用して操作できると思ってない人も結構いるんじゃないでしょうか。
windows10 + vagrant のおすすめフォルダ構成

provisioingにchefを使う場合。

```
root/
    Vagrantfile
    chef-repo/
        cookbooks/ <-- berkshelfのレシピを格納する
        site-cookbooks/ <-- 自前のレシピを格納する
        Berksfile
    workspace/ <-- 共有ディレクトリに /vagrant/workspace として追加
        (何か作業する)
```

centos/7 とか /vagrantが共有されていてもVMで変更したものがホストに同期できないものもあるので、/vagrant以外に共有場所を作っておくイメージ。
この構成でgitに放り込んでおけば、だいたい作業を共有できると思う。
画像を切り取って保存するやつ（Python3.7.0、OpenCV3.4.1）

画像を切り取って保存するやつ。
マウスでドラッグした領域を保存するやつ（コメントアウト部分）と、正方形に切り取って保存するやつ。

## 開発環境
- python 3.7
- opencv 3.4.1

## ソースコード
~~~python 
import cv2

selecting = False
ix, iy, cx, cy = -1, -1, -1, -1
w, h = 0, 0

def draw_boundingbox(event, x, y, flags, param):
    global selecting, ix, iy, cx, cy, w, h
    if event == cv2.EVENT_LBUTTONDOWN:
        selecting = True
        ix, iy = x, y
        cx, cy = x, y
    elif event == cv2.EVENT_MOUSEMOVE:
        cx, cy = x, y
    elif event == cv2.EVENT_LBUTTONUP:
        selecting = False
        cx, cy = x, y
        w, h = abs(cx - ix), abs(cy - iy)

cv2.namedWindow("img")
cv2.setMouseCallback("img",draw_boundingbox)
dirname = "./"
filename = "lena"
extension = ".jpg"
img = cv2.imread(dirname + filename + extension, -1)

selecting_ = False
num = 0
while(True):
    frame = img.copy()
    if selecting == True:
        selecting_ = True
        # cv2.rectangle(frame, (ix, iy), (cx, cy), (255, 255, 255), 2)
        ### for square
        cv2.rectangle(frame, (ix, iy), (cx, iy+cx-ix), (255, 255, 255), 2)
    else:
        if selecting_ != selecting:
            if w != 0 and h != 0:
                cv2.rectangle(frame, (ix, iy), (cx, iy+cx-ix), (255, 255, 255), 2)
                # jx, jy = min(ix, cx), min(iy, cy)
                # img_crop = img[jy:jy+h, jx:jx+w]
                ### for square
                jx, jy = min(ix, cx), min(iy, iy+cx-ix)
                img_crop = img[jy:jy+w, jx:jx+w]
                cv2.namedWindow("img_crop")
                cv2.imshow("img_crop", img_crop)
                c = cv2.waitKey(0) & 0xFF
                if c == ord('s'):
                    cv2.imwrite(filename + " - " + str(num) + extension, img_crop)
                    num += 1
                cv2.destroyWindow("img_crop")
                selecting_ = False

    cv2.imshow("img", frame)
    c = cv2.waitKey(1) & 0xFF
    if c==27 or c==ord('q'):
        break
~~~

## 結果
マウスをドラッグして切り取り、's'キーで保存する。保存したくない場合は他のキー。'q'キーで終了。

<img width="385" alt="imgcrop.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/63863/da485535-9ffe-1161-ff41-26251535c18f.png">
【メモ】AWSでシークレットキーをユーザー作成後に作成する手順

# AWSでシークレットキーをユーザー作成後に作成する手順
ユーザー作成時にアクセスキーを生成する方法についての有益な記事は発見することができたが、ユーザー作成後に作成する方法が検索でヒットしなかったのでメモ。

## 手順
1. コンソールを開く 
2.  IAMをクリック 
3.  左側のユーザーをクリック
4.  該当のユーザー名をクリック 
5.  認証情報タブをクリック 
6.  アクセスキーの作成をクリック 
7.  .csvファイルのダウンロードをクリック 

以上。
virtualbox 上の Ubuntu で webcam を使いたい


# 環境
* Host: MacOS
* Guest: Ubuntu 18.04
* 仮想化: Virtualbox 6.0 (Vagrant使えなかった）

Virtualbox はインストールしてある前提で進めます。

# 手順

## `Virtualbox` の `extensions` をインストール
https://www.virtualbox.org/wiki/Downloads

より、`VirtualBox 6.0.0 Oracle VM VirtualBox Extension Pack` をインストールします。
Virtualbox と **同じバージョン** をダウンロードしてください。ここ重要。

ダウンロードしたら、パッケージをダブルクリックすると自動的にインストールされ・・・ねぇよ( ﾟДﾟ)ｺﾞﾙｧ!! 
という訳で手動でインストールします。

Virtualbox を起動し、Tools > Preferences をクリック
<img width="500" alt="Screen Shot 2019-01-08 at 17.41.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/8963/f4ccd98f-3494-3a10-571e-4f4ba1fc922a.png">

Extensions タブの右端にある `+` をクリックします。
※写真はすでに追加されてる状態。

<img width="500" alt="Screen Shot 2019-01-08 at 17.44.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/8963/5ed044b9-7277-326f-60eb-a6d19f227fae.png">

ダウンロードしたパッケージを選択し、利用規約に同意してインストールします。
追加後は `virtualbox` のプロセスを再起動しろとの事。未検証。


## webcam を attach する
次に attach に必要な情報を取得します。

* 起動中の仮想マシン名の取得

```
$ VBoxManage list runningvms
"webcam_default_1546854116602_85444" {dd6325fd-c307-45cd-bcb2-c4b7900400ee}
```

* カメラパスの取得

```
$ VBoxManage list webcams
Video Input Devices: 1
.1 "FaceTime HD Camera"
0x1410000005ac8600 <-- これ
```

以上、それではアタッチします。

```
$ VBoxMange controlvm "webcam_default_1546854116602_85444" webcam attach 0x1410000005ac8600
[880/896]
VBoxManage: error: Attach emulated USB webcam (VERR_PDM_NO_USB_HUBS)                                                              
VBoxManage: error: Details: code VBOX_E_VM_ERROR (0x80bb0003), component ConsoleWrap, interface IConsole, callee nsISupports
```

おう。どうやら USB controller が有効になってない模様。

## USB controller を有効にする

Virtualbox の設定画面から USB 2.0 を有効にします。

もしくは単純に `VBoxManage` で変更しても可（のはず）

```
$ VBoxMange modifyvm "webcam_default_1546854116602_85444" --usb on
```

成功すると、以下の写真のように `Webcams` が選択されている状態になっているはず！
![vm.png](https://qiita-image-store.s3.amazonaws.com/0/8963/2abb58db-17e8-0eeb-f929-83996832fd02.png)


### 確認

ゲストにログインして、terminal にて以下をタイプ

```
$ ls /dev/
=> video* が表示されていれば成功。
```


# 参考
* https://www.virtualbox.org/manual/ch09.html
* http://kikuchy.hatenablog.com/entry/2014/02/23/VirtualBox%E3%81%AE%E3%82%B2%E3%82%B9%E3%83%88OS%E3%81%8B%E3%82%89%E3%83%9B%E3%82%B9%E3%83%88%E3%81%AEWeb%E3%82%AB%E3%83%A1%E3%83%A9%E3%82%92%E4%BD%BF%E3%81%86
Windows10でCapsLockを別のキーに割り当てる

# やりかた

* レジストリエディタを開く
  * Windowsキー -> regedit と入力 -> Enter
* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layoutを開く
* バイナリ値(REG_BINARY)を生成し、名前を`ScancodeMap`にする<br>
**Widnwos10だとScancodeとMapの間に半角スペースは入れないようです**
* 値を以下のようにする(CapsLock -> 左Ctrl, 右Alt -> CapsLock)
<pre>
00 00 00 00 00 00 00 00
02 00 00 00 1D 00 3A 00
3A 00 38 E0 00 00 00 00
</pre>

* 先頭の `00` 8つはプレフィックス
* 次の `02 00 00 00` は設定の個数
* 次から設定内容。変更前 -> 変更後 と2バイトずつスキャンコードを書く
    * リトルエンディアン
* 末尾の `00` 4つはポストフィックス
* PC再起動

スキャンコードはググってね。
Kubernetes の備忘録

# 概要
Kubernetes を使う上でのちょっとしたネタの備忘録です。

# Windows にインストールした minikube クラスタを WSL から叩けるようにする
[公式のインストール方法](https://kubernetes.io/docs/tasks/tools/install-minikube/) でインストールした minikube クラスタを、WSL 側にインストールされた kubectl から叩けるようにする設定。

kubectl の設定のうち、クラスタ、ユーザ、コンテキストの3つを全部 WSL 環境にコピーすればよい。なお、そのように設定して、パスを通しても、 minikube コマンド自体は正しく実行出来ない。

## 設定例

PowerShell 側で:

```
kubectl config view > kubeconfig
```

WSL 側で:

```
mkdir -p ~/.kube
nkf -Luw ~/WinHome/kubeconfig | sed -e 's%\\%/%g' -e 's%C:%/mnt/c%g' | diff -y - ~/.kube/config
nkf -Luw ~/WinHome/kubeconfig | sed -e 's%\\%/%g' -e 's%C:%/mnt/c%g' > ~/.kube/config
```
[PHP]郵便番号APIで住所を表示

※編集中ですが、コードだけでも共有しておきます。

#今回のコード
```php5:例
<?php
$postalCode = 1000001; //ここに好きな郵便番号を代入
$url = 'http://zipcloud.ibsnet.co.jp/api/search?zipcode=' . $postalCode; //下7桁が任意の郵便番号になったurlを$urlに代入

//urlからはファイルが返される

$resJson = file_get_contents($url); //ファイルの内容を文字列に読み込む
$resJson = mb_convert_encoding($resJson, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); //文字化け防止
$res = json_decode($resJson,true); //第二引数を「true」にすると配列型に変換

//返ってきた文字列を、それぞれの変数に代入して整理していく
$prefecture = $res['results'][0]['address1'];
$city = $res['results'][0]['address2'];
$city2 = $res['results'][0]['address3'];
$zipcode = $res['results'][0]['zipcode'];

//出力
echo '郵便番号「' . $zipcode . '」は';
echo '<br>';
echo $prefecture . $city . $city2 . 'です。';
```
```text:実行結果
郵便番号「1000001」は
東京都千代田区千代田です。
```
AWS LambdaのLayer用にOpenCVをビルド（Python3）

# Lambda Layers

AWS Lambdaのデプロイパッケージには50MBのサイズ制限がある。Numpy・SciPy・OpenCVをベタにビルドすると、それだけでお腹いっぱい。
そこでLambda Layers。展開後のサイズで250MBまで使える。
AWS公式は現在Numpy・SciPyのみ提供している。OpenCVも当然あっていいはずなのに今はまだないので、丸1日かけてビルドした。

### 追記

展開後250MB制限がつらいので、節約術（strip -s）を使った。70MBほど減っている。

# 準備

要Docker。

使うOpenCVのバージョンを決める。決めたら、ソースツリーをzipで固める。ファイル名はopencv-master.zipとopencv_contrib-master.zip。もしHEADでよければ、GitHubでDownload ZIPしたそのまんま。

# ビルド

以下のDockerfileとdocker-compose.ymlと同じところに、opencv-master.zipとopencv_contrib-master.zipを置いておく。

```dockerfile:Dockerfile
FROM lambci/lambda:build-python3.6
ENV AWS_DEFAULT_REGION ap-northeast-1

ENV HOME /home/hoge
RUN mkdir $HOME
WORKDIR $HOME

COPY opencv-master.zip .
RUN unzip opencv-master.zip
RUN mv opencv-master opencv
COPY opencv_contrib-master.zip .
RUN unzip opencv_contrib-master.zip
RUN mv opencv_contrib-master opencv_contrib

RUN yum update -y
RUN sed -i -e 's/enabled=0/enabled=1/' /etc/yum.repos.d/epel.repo
RUN yum install cmake3 -y
RUN pip install --upgrade pip
RUN pip install numpy

RUN mkdir ~/opencv/build
WORKDIR $HOME/opencv/build
RUN cmake3 -D CMAKE_BUILD_TYPE=RELEASE -D BUILD_SHARED_LIBS=NO \
    -D BUILD_LIST=aruco,features2d,imgcodecs,imgproc,python3,xfeatures2d \
    -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules \
    -D PYTHON3_EXECUTABLE=/var/lang/bin/python \
    -D CMAKE_INSTALL_PREFIX=~/bar_dist ..
RUN make install

RUN mkdir -p ~/foo/python
RUN mv ~/bar_dist/lib ~/foo/python/
WORKDIR $HOME/foo
RUN find . -name *.so|xargs -n 1 strip -s
CMD zip -ry9 ~/cv2_layer.zip * && cp ~/cv2_layer.zip /share
```


```yml:docker-compose.yml
version: '2'
services:
  app:
    build:
      context: .
    volumes:
      - .:/share
```

上記のDockerfileなどなどを置いたディレクトリで、

```bash
docker-compose build
docker-compose up
```

カレントディレクトリにcv2_ll.zipが生成される。

# 使い方

cv2_ll.zipをAWSコンソールでLayerとして登録する。自分のLambda FunctionにこのLayerをつける。このとき、AWS公式で提供されているNumpy・SciPyのLayerも同時につける必要がある。

importに時間がかかるので、ハンドラモジュールのグローバルでimportする必要がある。ハンドラ関数内でimport cv2しようとすると、デフォルトの制限時間の3秒以内に終わらない。

# OpenCVモジュールの取捨選択

BUILD_LISTを編集する。ちなみに上のリストでビルドすると、2019/01/08のHEADで展開後サイズが49,254,022バイトとなる。

# 共有ライブラリ？

上の例では静的リンクしてあるので、メモリを余計に食っているはず。Lambda FunctionでLD_LIBRARY_PATHを見ると/opt/libに通っているので（Layerは/optに展開される仕組み）、もしここに.soを配置すれば使えるはず。

追記：
むしろメモリを余計に食った。import cv2しただけの状態で54MB vs 58MB。

# 参考
[AWS Lambda で OpenCV と Pillow を使う環境を準備する](https://qiita.com/mkisono/items/b2add04203f7b4a6da67)
[Using Packages and Native nodejs Modules in AWS Lambda](https://aws.amazon.com/jp/blogs/compute/nodejs-packages-in-lambda/)
iPhoneアプリのHTTPS通信のパケットキャプチャをする

iPhoneアプリを開発しているとローカル環境で検証する分にはデバッグをして確認をすることができるが、試験を行うために他端末に配信すると、通信形式がHTTPSであればパケットキャプチャができなくなってしまいます。
今回はWeb Debugging Proxyで有名なCharlesを使ってHTTPS通信のパケットキャプチャをする方法を記載します。

## Charlesの設定とiPhoneからCharlesに接続する方法
[iPhoneからCharlesを使ってMacで立てたlocalホストにアクセスする](https://qiita.com/hiroshirs/items/aa7142ca4d0c63b5b05b)の記事の2つの章を参照  

- Charlesの設定  
- iPhoneの設定

## Charles側でSSL Proxy設定をONにする
Proxy -> SSL Proxying Settingsから設定を有効化する
Locationに * を追加する（チェックマークをONにする）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/237130/f3576a88-aee4-1c2c-3102-969717ae1abe.png)



## CharlesのSSL証明書をインストール&有効化

iPhoneをCharlesで立てたProxy経由でネットワークに接続している状態で、safariで以下のURLを打って、CharlesのSSL証明書をインストール
http://charlesproxy.com/getssl
<img width="375" alt="IMG_0957.png" src="https://qiita-image-store.s3.amazonaws.com/0/237130/99264670-13e6-503a-7748-a14f242ff4da.png">


上記SSL証明書がインストール済であれば、
一般 > 証明書信頼設定 > の中 「Charles Proxy CA(xxx)」が表示されるため、ONに変更する
<img width="375" alt="IMG_0958.png" src="https://qiita-image-store.s3.amazonaws.com/0/237130/84815b21-b52b-d797-4610-ca3eeb892e57.png">

HTTPS通信が必要なアプリを起動し、正常に動作すれば成功です。
CNN　転移学習とファインチューニング

#転移学習
・学習済みのモデルを新しいタスクに使うこと
・学習済みモデルの重みをそのまま使う


#学習済みモデルのインスタンス化
<b>include_top=False</b>
・分類器の部分は使わない
・畳み込みの部分だけ使う

→畳み込みの部分は画像の一般的・普遍的な特徴をとらえているが、分類器は以前学習したタスクに特化しているため

```python

from keras.applications import ResNet50

conv_base = ResNet50(weights='imagenet',
                     include_top=False,
                     input_shape=(32, 32, 3))
```

#モデル
```python

from keras import models
from keras import layers

model = models.Sequential()
model.add(conv_base)
model.add(layers.Flatten())
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))

model.summary()
```
#凍結
新しく付け足した分類器の重みの更新をしている間に、学習済みモデルの重みも一緒に更新されないように凍結する

```python

# 凍結前の更新可能な重みの数
print('before', len(model.trainable_weights))
```
>before 216

```python
# ResNet50の重みを凍結して更新されないようにする
conv_base.trainable = False
```
```python

# 凍結後の更新可能な重みの数
print('after', len(model.trainable_weights))
```
>after 4

#データと学習
```python
from keras.datasets import cifar10
(X_train, y_train),(X_test, y_test) = cifar10.load_data()

from keras.utils import np_utils

X_train = X_train.astype('float32')
X_test = X_test.astype('float32')

X_train /= 255.0
X_test /= 255.0

# ワンホットベクトル
n_classes = 10
Y_train = np_utils.to_categorical(y_train, n_classes)
Y_test = np_utils.to_categorical(y_test, n_classes)

from keras import optimizers

model.compile(loss='categorical_crossentropy',
              optimizer=optimizers.Adam(lr=1e-3),
              metrics=['acc'])

history = model.fit(X_train, Y_train,
                    batch_size=50, epochs=20, validation_split=0.1)

```

#ファインチューニング
・学習済みのモデルの最後の一部分の重みを再学習させて、
　新しいタスクについても適合できるようにすること

＜最後の一部分に限る理由＞

・前半部分は画像の特徴の一般的なことを捉えているため再学習させる必要がない

・最後の方の層は、より具体的な特徴を捉えるようになっている
　そのため、最後だけを再学習させることで新しいタスクに適合させることができる

・以前のタスクしか知らないモデルと新しいタスクしか知らない分類器のつなぎ目を滑らかにするというイメージもできる

```python
#最後のresblock(res5a_branch2aから最後まで)のみ再学習させる
conv_base.trainable = True

set_trainable = False
for layer in conv_base.layers:
    if layer.name == 'res5a_branch2a':
        set_trainable = True
    if set_trainable:
        layer.trainable = True
    else:
        layer.trainable = False
```
```python
# 更新される重みの数
print('after', len(model.trainable_weights))
```
>after 44

#コンパイルと学習
```python
model.compile(loss='categorical_crossentropy',
              optimizer=optimizers.Adam(lr=1e-3),
              metrics=['acc'])

history = model.fit(X_train, Y_train,
                    batch_size=50, epochs=3,
                    verbose=1, validation_split=0.1)
```
非AWS環境のRedashからRDSに接続メモ

AWSではないところにあるRedashからRDSのデータソースにアクセスする場合は少し面倒なのでメモで残しておく

* AWSではないサーバ上でRedashが動いている
* RDSはVPC上にある


# RDSのパブリックアクセス許可

まずインターネット越しにVPC内のRDSに接続する許可をする。パブリックアクセシビリティ「はい」を選択

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57350/192697fa-8964-8d9b-05f4-d35a8551cb96.png)

# セキュリティグループでDBのIPを空ける

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57350/9982fa2e-aaef-70c2-55a2-1f70ae44bd5c.png)

# RDSにDBユーザを作成

* rootでログイン

```
$ mysql -hxxxx-db-all-1-cluster.cluster-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -uroot -pPassword
```

* ユーザ作成。「*」ではなく「`%`」で指定

```
MySQL [(none)]> GRANT ALL ON `%`.* TO <user>@'<address>' IDENTIFIED BY 'Password';
Query OK, 0 rows affected, 1 warning (0.06 sec)
```

# Redashでデータソース登録

* Test ConnectionでSuccessとなること

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57350/422e7f5b-f07f-88f3-2442-ff1d04cb1dee.png)
Amazon Linux WorkSpaces でメニューのカスタマイズを GUI で行う

このトピックには新しい記事があります: [続・Amazon Linux WorkSpaces でメニューのカスタマイズを GUI で行う](https://qiita.com/mosop/items/fb6bcc9390246c743520)

Amazon Linux WorkSpaces (Amazon Linux 2) でメインメニューのカスタマイズを GUI でやりたかったのでアプリをセットアップしてみました。備忘録を残しておきます。

## 2 つの管理アプリを使い分ける

現状ではランチャーの作成を Alacarte[^1] で、ランチャーの編集を AppEditor[^2] で行うのがいいように思います。

2 種類のアプリを使い分ける理由は、

* Alacarte ではランチャーに引数つきのコマンドを設定できない
* AppEditor で作成したランチャーのカテゴリがおかしくなる

という不具合があるためです:upside_down:

## アプリのセットアップ

### Alacarte

Amazon 公式のパッケージをインストールすれば OK です。

```
sudo yum -y install alacarte
```

### AppEditor

手頃なパッケージがなかったので Docker ベースのビルド環境を作りました。

自前でビルドするか、私がビルドしたパッケージを[配布先](https://github.com/albuild/appeditor/releases/v0.1.0)から入手してインストールしてください。詳しくは [README](https://github.com/albuild/appeditor) をどうぞ。

## ランチャーの作成

ターミナルから Alacarte を起動してランチャーを作成します。

Alacarte の起動時には `XDG_MENU_PREFIX` 環境変数に "mate-" をセットしておきます。こうしないと作成するランチャーのカテゴリが Other として認識されてしまいます。

```
XDG_MENU_PREFIX=mate- alacarte
```

![misc (4).png](https://qiita-image-store.s3.amazonaws.com/0/63688/d24172bf-1848-aa82-c28d-b256d4525224.png)

無事に起動したので、ランチャーを作りましょう。毎回環境変数を指定して Alacarte を起動するのは面倒なので、まずは Alacarte 自身のランチャーを作ってみます。

Accessories カテゴリにランチャーを作ることにします。左のリストから Accessories を選んで、New Item をクリック。

![misc (5).png](https://qiita-image-store.s3.amazonaws.com/0/63688/dd7789d9-d271-7b15-0872-902abdf6971d.png)

前述のとおり、コマンドに引数を指定できない不具合があるので、ひとまず "alacarte" とだけしておきます。

![misc (6).png](https://qiita-image-store.s3.amazonaws.com/0/63688/8b259298-cf31-9ab0-000f-228f1a75a34b.png)

ランチャーができました:tada:

### ランチャーの編集

AppEditor でコマンド起動時の環境変数を設定します。メインメニューの [System Tools] → [AppEditor] で AppEditor を起動します。

![misc (8).png](https://qiita-image-store.s3.amazonaws.com/0/63688/9b718fc8-789a-7e1f-d7f7-fd6e78a56b10.png)

AppEditor が起動しました。Alacarte で作成したランチャーを編集していきます。

まず、対象のランチャーが Other カテゴリにあることに注意してください。おそらく WorkSpaces の環境と AppEditor の相性がよくないのでしょう。実際はちゃんと Accessories カテゴリに登録されているので、気にしないで編集していきます。

コマンドを `env XDG_MENU_PREFIX=mate- alacarte` に変更して、環境変数を指定するようにします。ランチャーのコマンドに環境変数を指定する場合は env コマンドを利用するとよいと思います。

適宜、アイコンを設定します。アイコンを変更するにはランチャー名の左にあるアイコンのグラフィックをクリック。

最後に [Save] をクリックして、完了です:tada:

### 補足: MenuLibre について

今回選んだアプリ以外に有名そうなもので MenuLibre というアプリがあったのですが、試してみたところ、何か変な動きをしている感じだったので、使うのをやめました。MATE (WorkSpaces で採用されているデスクトップ環境) で不具合が出るという情報が結構あったので、相性が悪いのかもしれません。

[^1]: GNOME 用のランチャー管理アプリ。GNOME 本家のプロジェクトのようですが、更新が止まっているので、不具合の改善は見込めません。
[^2]: Adam Bieńkowski さんが作っているランチャー管理アプリ。GitHub でスターが 70 以上ついていたので使ってみました。(https://github.com/donadigo/appeditor)
aws sam -cliがインストールできないときの解決策

# とりあえずやってみる
ドキュメント通りやってみる。
https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-sam-cli-install-mac.html

command not found: aws が出る
pathとかも通ってるはず。。。

# 解決策
pip install awscliがうまくいってなかった。

```
sudo pip install awscli --ignore-installed six
```

これで解決！
インストールできてないものがあってもうまくやってくれるオプションらしい。

# 参考
https://qiita.com/sachiko-kame/items/126e0a41acf270d05a73
MongoDBのシェルでmongosから、セカンダリ指定でクエリ実行したい場合


```bash

# DB指定
use hoge;

# セカンダリ指定
db.getMongo().setReadPref('secondary');

# 確認
db.getMongo().getReadPref()
> { "mode" : "secondary" }

# セカンダリ実行となる
db.hoge.findOne();

```

[参考ドキュメント：Mongo.setReadPref()](https://docs.mongodb.com/manual/reference/method/Mongo.setReadPref/)

なんか全然見つからなかったので、Mongoシェルのソースコード読んで見つけた。。

https://api.mongodb.com/js/current/symbols/src/src_mongo_shell_db.js.html
ご存知 git graph コマンド

## はじめに

これは完全に私的なメモ、備忘録です。

### ご存知 git graph コマンド

[ここ](https://github.com/Shinpeim/introduction-to-git/blob/master/05_branch.md)にあるものを改造しました。

Git のログを見やすく表示するためのエイリアスです。"git graph" で検索すると、同様のコンセプトで多くの方がエイリアスを作っていらっしゃいます。みなさん様々なエイリアス（別名）をつけていますが、私は参考にしたサイトそのまま "git graph" にしました。

```sh
git config --global alias.graph "log --graph --date-order --all --pretty=format:'%h %C(green)%ad%C(cyan reverse)%cn%C(reset) %C(white bold)%s %C(red reverse)%w(80)%d' --date=short"
```

### バックスラッシュが￥マークになってしまうターミナルを使っている場合は変換

上記 git graph で表示されるバックスラッシュが￥マークだったので [ここ](https://qiita.com/koto/items/0f51eec8fd70d5a56ee6) を参考に pager を細工しました。

```sh
git config --global core.pager 'sed -r '\''s/\\(\x1b[^ ]+ )/∖\1/g'\'' | less -+S'
```

### ログを１件だけ詳細に表示したい

「（主に直前の）コミットの詳細を知りたい」ということが時々あったのでエイリアスにしました。

```sh
git config --global alias.detail "log -1 -p --stat"
```

### 日付タグ

あまりタグ機能を使う必要に迫られなかったのですが。とりあえず日付のバージョンを作りたいというときにはエイリアスを作っておくといいかも。

```sh
git config --global alias.datetag "tag tmp$(date +%Y.%m.%d_%H%M)"
```
asciidocでマニュアルを作成する

# Asciidocとは
Markdown記法のように記述していくとドキュメントが作成できるようなものです。
例えば、見出しを書く場合は、

``` midashi.adoc
== 見出し1
=== 見出し2

```
のように書くことが出来ます。

# Asciidocを使用した理由
新製品をリリースするにあたり、マニュアルの整備が必要となり私がその業務を担うことになりました。
初めてマニュアル作成を行うので、作成したことがある人に作成方法を周りの人に聞いていたら、

"あんなの二度とやりたくない！"
"wordをpdfに変換して、見出しやらページ数やら自分でつけるのがダルい"
"見出しやページの確認作業が人海戦術のためミスが多発する"

などなど、かなり否定的な意見が出てきましたので、効率がよく、作業性の高いツールはないかと探していたら、
Asciidocにたどり着きました。(最初はMarkdown記述で行っていました。)

物は試しという事で、軽く使ってみたのですが、非常に使い勝手が良かったためAsciidocで作成してみることにしました。

# Asciidocの何が良いのか
* **自動生成**

目次やページ数が自動生成されるのが非常に楽です。
また、
```
asciidoctor-pdf filename.adoc
```
と、コマンドラインで打つだけでpdfに変換してくるため、複数のwordファイルをpdfに変換し、pdfを結合するという作業がこのコマンド一つで完結してしまいます。
弊社では、Wordを使用しており、
> "wordをpdfに変換して、見出しやらページ数やら自分でつけるのがダルい"

という面倒な点を回避できたことから、マニュアル作成者に非常に好評です。
私自身、今回の業務でマニュアル作成をしていることもあり有用性を感じています。
同期にも展開してその使い心地を体感してもらっていますw

* **リアルタイムプレビュー**

実際に書いたものが、どう成果物として現れるか確認できるのも非常に良いです。
しかも、それをhtmlやpdfに変換してもプレビュー通りの見た目になるので、余計な修正の手間もかからず便利です。
なんかプレビューするとズレるんだけどーって事も今のところないので良き。

* **自由度**

Wordだと、見出しを作成したり、強調したい部分はフォントサイズを変更する。という場合が多いかと思いますが、
Asciidocでもそれは可能です。
こんな感じです。

```sample.adoc
*強調したい*
```
フォントサイズは一律ですので、強調したい部分が複数あってもフォントのズレはありません。
Wordでは良くも悪くも自分でフォントサイズを指定できるため、最終リリース前にフォントサイズがずれてますよ！
って指摘が良くあるらしいので、それは防げるかなぁと思っています。

# まとめ
まとまりのない文章でしたが、ここまで読んでいただき、ありがとうございました。
今後少しずつ自分で得た知識のアウトプットをしていきたいと思います。
Djangoで作成日時と更新日時、論理削除を設定

# 最新情報
最新のDjangoで作成日時と更新日時、論理削除を設定は

[すぐに使える❗ Djangoに論理削除を導入](https://zenn.dev/notover9/books/660e4fce4da9b5)

に改めて書きました。

# 環境
- django2.1

# ベースモデル
ここで、作成日時と更新日時と削除日時のカラムを作り、論理削除のロジックを作っていく。

```python:base_model.py
from django.db import models
from django.utils import timezone


class BaseQuerySet(models.query.QuerySet):
    def delete(self):
        return super(BaseQuerySet, self).update(deleted_at=timezone.now())

    def hard_delete(self):
        return super(BaseQuerySet, self).delete()

    def alive(self):
        return self.filter(deleted_at=None)

    def dead(self):
        return self.exclude(deleted_at=None)


class BaseManager(models.Manager):
    def __init__(self, *args, **kwargs):
        self.alive_only = kwargs.pop('alive_only', True)
        super(BaseManager, self).__init__(*args, **kwargs)

    def get_queryset(self):
        if self.alive_only:
            return BaseQuerySet(self.model).filter(deleted_at=None)
        return BaseQuerySet(self.model)

    def hard_delete(self):
        return self.get_queryset().hard_delete()


class BaseModel(models.Model):
    # auto_now_add はインスタンスの作成(DBにINSERT)する度に更新
    created_at = models.DateTimeField('作成日時', auto_now_add=True)
    # # auto_now=Trueの場合はモデルインスタンスを保存する度に現在の時間で更新
    updated_at = models.DateTimeField('更新日時', auto_now=True)
    deleted_at = models.DateTimeField('削除日時', blank=True, null=True)

    objects = BaseManager()
    all_objects = BaseManager(alive_only=False)
```

# モデル
各モデルでベースモデルを継承する。
`created_at` `updated_at` `deleted_at`はベースモデルで設定し、継承しているので、モデルでは設定する必要はない。

```python:news_model.py
from django.db import models
from .base_model import BaseModel, BaseManager

class NewsManager(BaseManager):
    ...


class News(BaseModel):
    ...

    objects = NewsManager()
    all_objects = NewsManager(alive_only=False)
```

### 論理削除
`News.objects.filter(...).delete()`
### 削除
`News.objects.filter(...).hard_delete()`

### 論理削除したものも含めて検索
`News.all_objects.filter(...)`
### 削除していないデータ
`News.all_objects.filter(...).alive()`
### 論理削除したデータ
`News.all_objects.filter(...).dead()`
GitHub の Pro ユーザになりきれるブックマークレット

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">上流階級兵です<br>よろしくお願いします <a href="https://t.co/dCgDPCFIPV">pic.twitter.com/dCgDPCFIPV</a></p>&mdash; 死してなお動き出すライオン (@lion_man44) <a href="https://twitter.com/lion_man44/status/1082532900900196352?ref_src=twsrc%5Etfw">January 8, 2019</a></blockquote>

`PRO` バッジかっこいい！

しかし GitHub に $7/mon 払えない貧民なので、ブックマークレットで上流階級の真似事をすることにしましょう。

``` javascript
javascript:(function(e,t){e.className='border-top border-gray-light py-3';e.innerHTML='<svg class="octicon octicon-star mr-2 text-gray-light" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M14 6l-4.9-.64L7 1 4.9 5.36 0 6l3.6 3.26L2.67 14 7 11.67 11.33 14l-.93-4.74L14 6z"></path></svg><span class="label bg-purple text-uppercase">Pro</span>';t.parentNode.insertBefore(e,t)})(document.createElement('div'),document.getElementsByClassName('js-profile-editable-area')[0])
```

使い方は、このワンライナーをブラウザのアドレスバーにコピペして Enter を押すだけです。

![](https://qiita-image-store.s3.amazonaws.com/0/16369/dd56a725-6f60-e451-bf33-8e58a229027f.png)

かっこいい！！！！！！
Pythonで電子書籍フォーマットのEPUBからデータを抽出してみる

仕事で電子書籍フォーマットであるEPUBからデータを抽出する必要があったので、調べたところ ebooklib　といライブラリが便利そう。使ってみたので軽く紹介。

## EPUB とは

<img src="https://qiita-image-store.s3.amazonaws.com/0/186028/25975f57-705e-f5e3-2e15-a3a278ed9c8e.jpeg" width="200px" />

電子書籍フォーマットの一種です。 多くのデバイスの間でも汎用性高く、ここ数年段々普及しているフォーマットです。EPUB については　「EPUB 3とは何か？」 という本が オライリーから無料でダウンロードできます。https://www.oreilly.co.jp/books/9784873115528/

## Python で EPUB の中から必要なデータを所得する。

EPUBを扱うならこちらが便利
https://github.com/aerkalov/ebooklib

DocumentはこのPDFが詳しい
https://media.readthedocs.org/pdf/ebooklib/latest/ebooklib.pdf

今回はこちらのモジュールを使ってEPUBからデータを抜き出してみる。使い方はめちゃ簡単。

```python:main.py
import sys
import os
import ebooklib
from ebooklib import epub

book = epub.read_epub('.<.epubファイルのパス>')

title = book.get_metadata('DC', 'title')
creator = book.get_metadata('DC', 'creator')
publisher = book.get_metadata('DC', 'publisher')
language = book.get_metadata('DC', 'language')
  
print(title) # タイトル
print(creator) # 執筆者
print(publisher) # 発行人
print(language) # 言語

items = book.get_items()
   for item in items:
       if item.get_type() == ebooklib.ITEM_DOCUMENT:
           print('==================================')
           print('ファイル名 : ', item.get_name()) # ファイル名
           print('==================================')
           print(item.get_content().decode()) # 本文をファイルごとに書き出し
           print('==================================')

```

これで .epub 拡張子のファイルパスからデータの抽出ができた！このライブラリは他にも EPUB から画像データを抽出したり、実際にEPUBデータを作成できたりも可能。英語ならPDFでドキュメントがみれる。詳しくはこちらを！
https://media.readthedocs.org/pdf/ebooklib/latest/ebooklib.pdf

Elasticsearchに入れて分析できるようにしたいのでそこに関しても今後追記するかも
awsで "The policy is attached to 0 entities but it must be attached to a single role"　エラーが出た場合の対処法

# はじめに
awsのCodeBuildでビルドプロジェクトを作成しようとしたときに、以下のエラーが出てプロジェクトが作成できないという現象に遭遇しました。
"The policy is attached to 0 entities but it must be attached to a single role"

![スクリーンショット 2019-01-08 13.46.47.png](https://qiita-image-store.s3.amazonaws.com/0/191873/b578de36-78bf-f07f-60c8-31462025a98b.png)

本エラーの発生手順と解決策について以下にまとめます。

# 結論
本エラーはCodebuild(awsサービス)が自動的に作成し、指定したIAMロールにアタッチしようとしているポリシーA(CodeBuildBasePolicy-プロジェクト名-リージョン名)と同一のポリシーA'が既に存在＊しており、かつ、当該IAMロールからポリシーA'がデタッチされていると発生します。

 ＊ 過去に同一のプロジェクト名でCodeBuildプロジェクトを作成している場合に存在する

ポリシーA'(CodeBuildBasePolicy-プロジェクト名-リージョン名)を削除すれば、エラーは発生しなくなります。

# エラーが出る時

以下の手順で本エラーが発生します（2019/01/08現在）。

１． Codebuildでプロジェクトを作成する（例としてプロジェクト名を"testproject"とする）


※「AWS CodeBuild にこのサービスロールの編集を許可し、このビルドプロジェクトでの使用を可能にする」にチェックを入れて作成する

![スクリーンショット 2019-01-08 14.04.34.png](https://qiita-image-store.s3.amazonaws.com/0/191873/3c422206-87a4-e8d9-1cf9-e7af08051733.png)



２． 作成したtestprojectを削除する
３． testproject作成時に指定したロール（ここではRoleForCodeBuild）から、testproject作成時にCodeBuildが自動的に作成・アタッチしたポリシーをデタッチする

![スクリーンショット 2019-01-08 13.45.52.png](https://qiita-image-store.s3.amazonaws.com/0/191873/45af9e9d-16b1-7dcf-8d2b-6d869186185b.png)

４．CodeBuildプロジェクト作成画面を開きさきほどと同じ名前(testproject)を入力して、作成しようとする (「AWS CodeBuild にこのサービスロールの編集を許可し、このビルドプロジェクトでの使用を可能にする」にチェックを入れる)

「ビルドプロジェクトを作成する」を押すと本エラーが発生します。


# エラーの原因
CodeBuildが自動的に作成して、ユーザが指定したロールにアタッチしようとしているポリシーが既に存在し、かつ、それが指定したロールからデタッチされているため、です。

以下のようなケースで起こりうると思います。

CodeBuildプロジェクトを削除しても、その時にCodeBuildが自動的に作成したポリシーは残ります。既存のロールに既に不要なポリシーが残っている(アタッチされている)のは気持ち悪いためロールの管理画面で×ボタンを押してデタッチします。その後、忘れた頃にまたCodeBuildでプロジェクト作るときに、たまたま以前と同じ名前でプロジェクトを作成すると、本エラーが発生します。

# エラーの解決策
CodeBuildが自動的に作成したポリシーを削除する。

![スクリーンショット 2019-01-08 13.53.04.png](https://qiita-image-store.s3.amazonaws.com/0/191873/51e27f8a-cd59-5813-d5bf-16ee26c05c70.png)

CodeBuildが自動的に作成したポリシーであり、かつ、プロジェクトごとに作成されるポリシーのため、以前に作成されたCodeBuildBasePolicy-xxxポリシーは削除して問題ない。

# まとめ
"The policy is attached to 0 entities but it must be attached to a single role"エラーが発生する条件とその解決方法をまとめました。
C++ Builder XE4 > TeeChart > 軸 > BottomAxisの開始日時と終了日時を取得する > Chart1->BottomAxis->Minimum と Maximum

```txt:動作環境
C++ Builder XE4
```

### 概要

- BottomAxisの開始と終了日時を取得する

実装時のコード入力補完にてプロパティMinimumとMaximumを見つけた。


### 実装

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <DateUtils.hpp>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormShow(TObject *Sender)
{
    Chart1->Series[0]->XValues->DateTime = true;
    Chart1->BottomAxis->DateTimeFormat = L"mm/dd hh:nn";

    TDateTime dt;

    dt = Now();

    double yval;
    for (int idx=0; idx < 1000; idx++) {
		yval = (1+ idx) % 200;
        Series1->AddXY(dt, yval, "", clRed);
		dt = IncMinute(dt, 1);
	}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Chart1Click(TObject *Sender)
{
	TDateTime startdt = Chart1->BottomAxis->Minimum;
	TDateTime enddt = Chart1->BottomAxis->Maximum;

	String msg;
	msg = startdt.FormatString(L"yyyy/mm/dd hh:nn");
	Memo1->Lines->Add(msg);

	msg = enddt.FormatString(L"yyyy/mm/dd hh:nn");
	Memo1->Lines->Add(msg);
}
//---------------------------------------------------------------------------
```

### 動作例

グラフ内をクリック後

![2019-01-08_17h34_33.png](https://qiita-image-store.s3.amazonaws.com/0/32870/4bc50b90-a668-02d0-0d64-759018fb9513.png)

開始日時と終了日時を取得できた。
FreeBSD12でrelaydを使う方法

[2019年5月30日 追記]
https://github.com/freebsd/freebsd-ports/blob/master/net/relayd/Makefile
relaydのportsが更新されて、
libresslをスタティックリンクするように変更になったのでFreeBSD12でも使えるようになりました。
さきほど確認したらpkgのリポジトリにも登録されていたのでインストールも簡単です

```
# pkg install relayd
```





2019年1月8日現在、FreeBSD12上のrelaydのportsのがBROKENなのでports/pkgからインストールすることができません

```
BROKEN_FreeBSD_12=      does not build, OpenSSL 1.1 unsupported
```

12用がないのでFreeBSD11用のパッケージを無理やりインストールします

```
# pkg add -f http://pkg.freebsd.org/FreeBSD:11:amd64/latest/All/relayd-5.5.20140810_3.txz
```

起動しようとするとlibssl.so.8が必要なのでエラーになります

```
# /usr/local/etc/rc.d/relayd onestart
Performing sanity check on relayd configuration:
ld-elf.so.1: Shared object "libssl.so.8" not found, required by "relayd"
/usr/local/etc/rc.d/relayd: WARNING: failed precmd routine for relayd
```

そんな時に便利なパッケージがcompat11xです
FreeBSD11のライブラリをインストールしてくれるパッケージです
amd64用のパッケージ名はcompat11x-amd64になります
これをインストールして起動してみます

```
# pkg install compat11x-amd64
# /usr/local/etc/rc.d/relayd onestart
Performing sanity check on relayd configuration:
/usr/local/etc/relayd.conf:60: cannot load certificates for relay wwwssl
/usr/local/etc/relayd.conf:112: syntax error
/usr/local/etc/rc.d/relayd: WARNING: failed precmd routine for relayd
```

ライブラリが足りないとは言われなくなったので設定ファイルを整えれば起動できそうです
VMwareのゲストOSのポートをホストネットワークに公開する（NAPT設定）

# 概要
VMwareの各ゲストOSに別PCからSSH接続する設定のメモ。
VMwareのネットワーク設定を行う事により、ゲストOSのポートをホストネットワークに公開できる。
## イメージ図
![イメージ図](https://qiita-image-store.s3.amazonaws.com/0/339580/64b4d6bb-9d49-4d74-e9dc-d1223b79f21d.png)
## 環境メモ
* ホストOS：Windows 10 
* ゲストOS：CentOS 7.6.1810
* VMware：Workstation 15 Player 15.0.2 build-10952284
※仮想ネットワークはNAT接続で構築

# 設定方法 
## vmnetnat.conf の修正（NAPT設定）
C:\Users\All Users\VMware\vmnetnat.conf を編集し、ホストOSポート番号～ゲストOSポート番号の対応関係を incomingtcp セクションに以下の要領で追記する。

```
[incomingtcp]
10001 = yyy.yyy.yyy.yyy:22
10002 = yyy.yyy.yyy.yyy:22
10003 = yyy.yyy.yyy.yyy:22
```
変更後、サービス一覧等より VMware NAT Service を再起動する。

## ホストOSのファイアウォールを設定（ポートの解放）
「セキュリティが強化された Windows ファイアウォール」画面よりポート開放の設定を行う。SSH接続用であれば以下の通り。

* 受診の規則
 * プロトコルの種類：TCP
 * ローカルポート：特定のポート（22）
* 送信の規則（なし）

## その他手順
セキュリティソフト等を導入している場合は、ファイアウォール設定がされている可能性があるため、その場合は同様にポート開放設定を行う。
CircleCIでの「WARNING: terminal is not fully functional」

CircleCIがコケたので調べてみた

### 発生したエラー

```terminal
#!/bin/bash -eo pipefail
psql -U hoge_user -d hoge_db -h localhost -f database/sql/create_tables.sql
SET
SET
SET
SET
SET
WARNING: terminal is not fully functional

 set_config 
------------
 
(1 row)

(END)Too long with no output (exceeded 10m0s)
```

テスト用データベースの構築の途中で入力待ちになりタイムアウトしたようだ。
※migrationを利用できない環境で、データベースとテーブルの構築をsql文で実行している

入力待ちになるのは困るので、解決策を探す。


### 対応

psqlで利用するPAGERをlessからcatに変えて対応している人を見つけた。

[database - Rails: rake db:structure:load times out on CircleCI 2.0 - Stack Overflow](https://stackoverflow.com/questions/53055044/rails-rake-dbstructureload-times-out-on-circleci-2-0)


```yml
jobs:
    build:
        docker:
          - image: MY_APP_IMAGE
            environment:
              PAGER: cat # prevent psql commands using less
```

無事解決できました。
PAGERが変わってしまったのはおそらくPostgresqlの環境を9から10に変えて、なにかしら設定が変わってしまったのかと思いますが、深くは追っていません。
ORACLE　PL/SQLの基本

最近PL/SQLについて聞かれることがあったので、昔とった何とかってやつで復習したいと思います。

PL/SQLって？
---
PL/SQLは米オラクルが開発した、「SQL（Structured Query Language：非手続き型言語）」を“手続き型”言語として拡張したプログラミング言語になります。
PL/SQLを使うことにより、単独のSQLでは実現できない処理や、複雑な処理を容易に実現できます。【WIKI参照】
https://ja.wikipedia.org/wiki/PL/SQL

※MariaDBは10.3からOracle Database互換機能としてPL/SQLをサポートするようになりました。

メリットとデメリット
----
ここでは、PL/SQLのメリット・デメリットについて語りたいと思います。

メリット
---
1. パフォーマンスに優れている
PL/SQLを使用しない場合、SQLを発行し対話的にデータ処理を行うことになりますが、Oracle Databaseを使用している環境でPL/SQLを使った場合、PL/SQLの手続き処理とSQL処理をOracle Database上で一緒に行えます。
そのため、他のプログラミング言語に比べて、プロセス間通信のオーバーヘッドやネットワークトラフィックを削減できます。
![PLSQLイメージ図.png](https://qiita-image-store.s3.amazonaws.com/0/315849/ca613a5e-2768-bd78-b64e-7a92c78291b2.png)

2. SQLとの親和性が高い
PL/SQLはSQLを拡張したプログラミング言語なのでSQLとの親和性が担保されていますので、プログラム内ではSQLの全ての文や関数などが使用可能です。
データ型もサポートされているために、SQLとPL/SQL間でデータ型の変換作業も不要です。

3. 移植性に優れている
PL/SQLで記述されたアプリケーションは、特定のハードウェアやプラットフォームに依存しないのも特徴です。
Oracle Databaseが動作する全ての環境で実行できます。
また、JavaやVBといった言語でも呼び出しが可能なので、言語依存が少ないもの特徴になります。

デメリット
---
1. オブジェクト指向ではない
PL/SQLは古い言語のため、オブジェクト指向に対応していません。
とはいえ、システム開発を行ってくうえで、継承などのオブジェクト指向の考え方がやはり必要です。
状況に応じて他言語とPL/SQLを使い分ける必要があります。

2. デバッグ環境が弱い
単純な入力ミスもコンパイルするまで発覚しません。
コンパイルエラーが発生しなくても正常に動き、実行結果に問題があった場合はどこに問題があったのか発見しづらいのもあります。
そのためデバッグには経験とセンスが重要になってきます。

3. ユーティリティ不足
必要最低限のユーティリティしか用意されていないため、他の言語に比べて貧弱です。
自分で追加作成するのも容易でないため、すべてをPL/SQLで解決しようと考えないほうがいいです。


PL/SQLの構造
---

PL/SQLで作成したプログラムを「PL/SQLブロック」と呼び、4つのキーワードで区切られた3つの「部」で構成されています。
![PLSQL　ブロックの基本構造.png](https://qiita-image-store.s3.amazonaws.com/0/315849/0a1d155a-76fc-d0d1-149e-c9609738bd8d.png)

DECLARE以降が「宣言部」、BEGIN以降が「実行部」、EXCEPTION以降が「例外処理部」となり、最後のENDでブロックの終了を宣言するという構造です。

1. 宣言部（DECLARE～）
宣言部では、ブロック内で使用するオブジェクト（変数やカーソルなど）の定義を記述します。

2. 実行部（BEGIN～）
実行部では、SQLによるデータ操作や、手続き処理（反復文や分岐文など）など、実際に行う処理を記述します。

3. 例外処理部（EXCEPTION～）
例外処理部では、ブロック内で発生した例外に対する処理を記述します。
ここは他のプログラム言語でもあるので、わかりやすいですね。

4. END 
END;で、PL/SQLブロックの終了を宣言します。

基本はこんな感じになります。
機会があれば、また応用編などを投稿したいと思います。
Raspberry Pi Zero W でポケット・ミクを歌わせる

# はじめに
　こちら「[ポケット・ミクを MIDI 操作で歌わせてみた](https://qiita.com/YuichiSato/items/1c99c6560c285b86ade8)」の関連記事です。
　ポケット・ミクを歌わせ続けるたい時に PC に繋ぎっぱなしにするのは不便なので、Raspberry Pi Zero W から歌わせることが出来れば便利だなと思いやってみました。

# 接続図
![Image from iOS.jpg](https://qiita-image-store.s3.amazonaws.com/0/13938/75e355b4-f467-be2a-2f0e-02474e0b2468.jpeg)

# 手順
　`alsa-utils` パッケージをインストールしていなければインストールしておきましょう。

```bash
# aptitude install alsa-utils
```

　次のコマンドで出力可能ポートを確認します。この時にポケット・ミクの電源を入れていないと表示されないので注意が必要です。

```bash
# aplaymidi -l
 Port    Client name                      Port name
 14:0    Midi Through                     Midi Through Port-0
 20:0    NSX-39                           NSX-39 MIDI 1
```

　`NSX-39` がポケット・ミクです。
　次のコマンドで MIDI ポート（送信側）とポケット・ミク（受信側）を接続します。

```bash
# aconnect 14:0 20:0
```

　この状態でプログラムを実行すればポケット・ミクが歌い始めます。
【Mac】jpg, png→epsの一括変換フォルダ

Macに標準搭載されているAutomatorを使って，epsファイルへの一括自動変換フォルダを作成する．

# 目次
- [作成するもの](#作成するもの)
- [ImageMagickのインストール](#imagemagickのインストール)
- [Automatorの設定](#automatorの設定)
- [フォルダにアクションを適用](#フォルダにアクションを適用適用されていない場合)


# 作成するもの
jpgファイルやpngファイルをフォルダに追加すると，自動的にepsファイルに変換して，フォルダ分けするフォルダアクション。
![demo.gif](https://qiita-image-store.s3.amazonaws.com/0/231104/8f93b0b3-05a9-6cd1-846c-a4fcc100a3de.gif)



# ImageMagickのインストール
epsファイルへの変換は，ImageMagickのconvertコマンドで行います。

```bash
brew install imagemagick
```


# Automatorの設定

<img width="1112" alt="Automator.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/231104/db6cfcdc-85fd-2b6e-0c6f-ebe47c3e96fe.jpeg">

1. Automatorを起動して「フォルダアクション」を選択
2. アクションを設定したいフォルダを選択（ここでは「eps変換」というフォルダに設定）
3. 左のアクションから「シェルスクリプトを実行」をドラッグして追加
4. シェルに「/bin/bash」を選択
5. 入力の引き渡し方法に「引数として」を選択
6. スクリプトに以下を記述

```bash
IFS=$'\n'

for f in "$@"
do
  fpath=${f%/*}  # ファイルパス
  froot=${f%.*}  # ファイル名（拡張子なし） 
  ext=${f##*.}  # ファイル拡張子
  out=$fpath/eps/${froot##*/}.eps  # 出力ファイル名

  # 特定の拡張子ならば
  if [ $ext = "jpg" -o $ext = "jpeg" -o $ext = "png" ]; then

    # フォルダ用意
    if [ ! -e $fpath/org/ -o ! -d $fpath/org/ ]; then
      mkdir $fpath/org/
    fi
    if [ ! -e $fpath/eps/ -o ! -d $fpath/eps/ ]; then
      mkdir $fpath/eps/
    fi

    # eps変換
    /usr/local/bin/convert $f eps2:$out

    # フォルダ移動
    mv $f $fpath/org/
  fi
done
```

ここまでできたら適当な名前をつけて保存しましょう。（ここでは「epsConverter.workflow」という名前で保存）



# フォルダにアクションを適用（適用されていない場合）

<img width="592" alt="folderAction.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/231104/c3e93bfe-33bf-f4bd-a21a-1a048c1014c5.jpeg">

1. アクションを設定したいフォルダで右クリック
2. 「フォルダアクション設定...」
3. 確認画面で「サービスを実行」を選択
4. フォルダに先程作成したアクションを設定
どうしてもCannot access class '〇〇'. Check your module classpath for missing or conflicting dependenciesでエラーする。

# 現象

kotlinでアプリを作っていて、途中まではビルドも通っていたのにDataBindingを多用していたらある時からビルドしようとしても

```
Cannot access class '〇〇'. Check your module classpath for missing or conflicting dependencies
```

とエラーが出てしまうようになった。
kotlin-kaptの適用もちゃんと行っているし、各xmlファイルやクラスファイルにバグはないように思えるしさっきまでビルドも通っていたのに…。

# 解決方法
package名を大文字始まりにしてしまっていた。
「javaのpackage名は全て小文字にする」というのは厳密なルールではなく慣習（推奨）で、実際プロジェクトが単純な構成なうちはビルドも通っていたので見落としてしまっていた。
各packageを小文字だけにリネームしてやって、無事解決した。

![packageLarge.png](https://qiita-image-store.s3.amazonaws.com/0/245217/fde6608e-0132-45f6-4754-c0c7bce8a17b.png)



:arrow_double_down:　Rename

![packageSmall.png](https://qiita-image-store.s3.amazonaws.com/0/245217/245aa208-5f30-6e63-775d-b66ffb1d98c2.png)

解決！
VSCodeの拡張機能開発でユーザー設定を変えながら単体テストする

VSCodeの拡張機能開発で単体テストする際に、ユーザーが設定した値に応じた動作をテストする方法をまとめました。


## 前提条件
下記のpackage.json内で定義されたconfigurationを、取得するSmapleクラスのgetParamメソッドをテストすることを想定して解説します。

```json:package.json
省略
"contributes": {
    "configuration": {
        "type": "object",
        "title": "Sample configuration",
        "properties": {
            "extension.myParam": {
                "type": "string",
                "default": "",
                "description": "sample value"
            }
        }
    }
},
省略
```

```ts:src/Sample.ts
import * as vscode from 'vscode';

export class Sample {
  public getParam(): string {
    let configuration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration('extension');
    
    if (configuration.myParam.lenth > 0) {
      return configuration.myParam;
    }
    return "None";
  }
}
```

## updateメソッドで任意の値を設定する
vscode.workspace.getConfigurationで現在のconfigurationを取得します。
更にupdateメソッドを実行することで任意の値を設定することが可能です。
第一引数がconfigurationの名称、第二引数が設定する値。

```ts
let settings = vscode.workspace.getConfiguration("extension");
setting.update("myParam", "hoge"); // myParamをhogeに変更
```

## テストする
update実行後、そのままテストを書いても設定が反映される前にassertが実行され、テストは失敗します。
updateはThenableを返すので、実行完了を待ってからテストする必要があります。
Mochaには実行完了を待ってからテストする書き方が何通りかありますが、async/awaitを使って書くと下記のようになります。

```ts:src/test/extension.test.ts
import * as assert from 'assert';
import * as vscode from 'vscode';
import { Sample} from '../Sample';

suite("Sample Tests", () => {
  test("Test getParam method", async () => {
    let extension = new Sample();
    let settings = vscode.workspace.getConfiguration("extension");

    await setting.update("myParam", "hoge").then(() => {
      assert.equal(extension.getParam(), "hoge");
    });

    await setting.update("myParam", "").then(() => {
      assert.equal(extension.getParam(), "None");
    });
  });
});

```
ownCloud + ONLYOFFICE をdockerで

昨年、連携がうまくいなくてissuesで指摘されて、連携がうまくできたのでポイントをまとめておきます。

## ownCloud
[owncloud-docker/server](https://hub.docker.com/r/owncloud/server)を使って建てました。
docker-compose.yml に以下の2つを追加しました。

```
- OWNCLOUD_SUB_URL=/owncloud
- OWNCLOUD_LOG_TIMEZONE=Asia/Tokyo
```

defaultだと　http://localhost:8080 の様にアクセスするのを
http://localhost:8080/owncloud みたいにSUB URL指定したかったから。
これが後程、詰まってしまうポイントになりました。

## ONLYOFFICE DocumentServer
[onlyoffice/documentserver](https://hub.docker.com/r/onlyoffice/documentserver)
これをそのまま建てました。

## ownCloud - ONLYOFFICE apps ver2.0.3
ownCloudのプラグインでONLYOFFICEと連携させます。
この時、３つ設定するのですが

### Document Editing Service address
ONLYOFFICE DocumentServerのURL
https://doc.huangru.local/

### Document Editing Service address for internal requests from the server
Specify container name
ONLYOFFICE DocumentServerのURL.
http://only/


### Server address for internal requests from the Document Editing Service Specify container name
ownCloudから連携時のONLYOFFICE DocumentServerのURLを指定

私は、ここの連携がうまくいかずに、悩んだポイントです。
ownCloud と ONLYOFFICE DocumentServerは
それぞれのDockerコンテナで起動しています。
ネットワークはブリッジしています。

所が、今回は、SUB URLを指定してましたので
当然ですが、**SUB URLを指定してないといけません。**

ここが噛み合ってないと、プラグインの設定でセーブは成功しても
動作時に、The document could not be saved となってしまいます。

X http://owncloud:8080/
O http://owncloud:8080/owncloud


### 詳細は[The document could not be saved](https://github.com/ONLYOFFICE/onlyoffice-owncloud/issues/234)をご覧ください
issuesで指摘されるまで、解らなかった ;(
ローカルで連携の練習してただけなので、セキュリティ関連とかの設定は参考にしないでください。
そもそもオレオレ証明書で試してただけですので:sweat_drops:
Kafka 管理 メモ

## Topics確認

背景：Kafkaクラスタ管理

```
cd /usr/hdp/current/kafka-broker/

# Access Kafka Cluster
bin/kafka-topics.sh  --zookeeper zzeng-hdp-1.field.hortonworks.com:2181,zzeng-hdp-2.field.hortonworks.com:2181,zzeng-hdp-3.field.hortonworks.com:2181 --describe
```

## Topics 新規作成
```
bin/kafka-topics.sh --create --zookeeper  zzeng-hdp-1.field.hortonworks.com:2181,zzeng-hdp-2.field.hortonworks.com:2181,zzeng-hdp-3.field.hortonworks.com:2181 --replication-factor 3 --partitions 1 --topic zzeng01
```


## Topics 一覧表示
```
bin/kafka-topics.sh --zookeeper  zzeng-hdp-1.field.hortonworks.com:2181,zzeng-hdp-2.field.hortonworks.com:2181,zzeng-hdp-3.field.hortonworks.com:2181 --list 

```

## Topic内容を見る：Consumer
```
### Kafka 1.x
bin/kafka-console-consumer.sh --zookeeper zzeng-hdp-1.field.hortonworks.com:2181,zzeng-hdp-2.field.hortonworks.com:2181,zzeng-hdp-3.field.hortonworks.com:2181 --from-beginning --topic meetup_rsvp_avro

### Kafka 2.x
bin/kafka-console-consumer.sh --bootstrap-server zzeng-hdp-1.field.hortonworks.com:6667 --topic meetup_rsvp_avro

```
brewでインストールしたwgetを使うとSIGABRTで落ちる場合

# 起きたこと
以下のようにbrewでwgetをインストールした後、実行すると死にました。

```sh
$ brew install wget
$ wget
dyld: Library not loaded: /usr/local/opt/pcre/lib/libpcre.1.dylib
  Referenced from: /usr/local/bin/wget
  Reason: image not found
fish: 'wget' terminated by signal SIGABRT (Abort)
```


# 解決策
pcreという正規表現に関するライブラリが入ってないよと怒られているので入れてやります。

```sh
$ brew install pcre
$ wget
wget: missing URL
Usage: wget [OPTION]... [URL]...

Try `wget --help' for more options.
```

やったね！
fine tuning と転移学習

Fine tuning: 既存の学習済モデル（出力層以外の部分）を、重みデータを一部再学習して特徴量抽出機として利用する。
転移学習: 既存の学習済モデル（出力層以外の部分）を、重みデータは変更せずに特徴量抽出機として利用する。

#出典
https://teratail.com/questions/125496