空飛ぶロボットのつくりかた

ロボットをつくるために必要な技術をまとめます。ロボットの未来についても考えたりします。

threadのお勉強(with python)

ROS x thread x pythonのコードを読みながらthreadの理解、実装方法を学ぶ

python並列化

  1. threading.Thread

  2. multiprocessing.Process

Pythonのマルチスレッド処理:threading, multiprocessing | UX MILK

python x threadについて

Pythonのthreading.Threadとmultiprocessing.Process [ pLog ] 👈イイね!

Pythonでマルチスレッド処理 - Qiita

Python の threading.Lock を試してみる | CUBE SUGAR STORAGE

pythonのcopyについて

8.10. copy — 浅いコピーおよび深いコピー操作 — Python 3.5.3 ドキュメント

https://teratail.com/questions/40811

pythonの値渡し、参照渡しについて

Pythonの値渡しと参照渡し - amacbee's blog

copy – オブジェクトのコピー - Python Module of the Week

pythonのselfについて

和訳 なぜPythonのメソッド引数に明示的にselfと書くのか | TRIVIAL TECHNOLOGIES 4 @ats のイクメン日記

お気楽 Python プログラミング入門

ROS x thread x pythonのコード

jsk_robot/OdometryFeedbackWrapper.py at master · jsk-ros-pkg/jsk_robot · GitHub

self.lock = threading.Lock()

~

def source_odom_callback(self, msg):
    with self.lock:
    ~

のようにlockを用いてthread safeを実現

    def feedback_odom_callback(self, msg):
        if not self.odom:
            return
        self.feedback_odom = msg
        with self.lock:
            # check distribution accuracy
            nearest_odom = copy.deepcopy(self.odom)
            nearest_dt = (self.feedback_odom.header.stamp - self.odom.header.stamp).to_sec()

lockした状態のself.odomの中身を深いcopyでnearest_odomに格納。

参考:Python の threading.Lock を試してみる | CUBE SUGAR STORAGE

dynamic_reconfigure/server.py at master · ros/dynamic_reconfigure · GitHub

mutex: 排他制御 http://wa3.i-3-i.info/word13360.html

上記と同じ。lockを使用。

ドローン画像取得 (Erle-Copter, ArduPilot) - Qiita

from threading import Thread, Lock
VERBOSE=True
import copy
mutex = Lock()
topic_name = "/camera/image/compressed"
class web_video_server:
    def __init__(self):
        '''Initialize ros publisher, ros subscriber'''
        # subscribed Topic
        self.subscriber = rospy.Subscriber(topic_name,
            CompressedImage, self.callback,  queue_size = 1)
        if VERBOSE :
            print "subscribed to " + topic_name
    def getCompressedImage(self):
        mutex.acquire(1)
        result = copy.deepcopy(self.np_arr);
        mutex.release()
        return result;
    def callback(self, ros_data):
        '''Callback function of subscribed topic. '''
        mutex.acquire(1)
        self.np_arr = ros_data.data;
        mutex.release()

acquireとreleaseを使用。上記の with self.lock: でも良い。

lockした状態のself.np_arrの中身を深いcopyでresultに格納。

画像をgetするとき、callbackで更新するときそれぞれlockしている。

Pythonメモ: スレッドをロックする

robot_blockly/image_server.py at master · erlerobot/robot_blockly · GitHub

http://files.cnblogs.com/files/cv-pr/ros_by_example_vol2_indigo.pdf

全体参考

Pythonで学ぶ 基礎からのプログラミング入門 (33) マルチスレッド処理を理解しよう(後編) | マイナビニュース

Python: fasteners の便利な排他ロックを試す - CUBE SUGAR CONTAINER

機械学習のお勉強(モデルの評価とパラメータのチューニング)

教科書

GitHub - rasbt/python-machine-learning-book: The "Python Machine Learning (1st edition)" book code repository and info resource

Data準備

import pandas as pd
import urllib

try:
    df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases'
                     '/breast-cancer-wisconsin/wdbc.data', header=None)

except urllib.error.URLError:
    df = pd.read_csv('https://raw.githubusercontent.com/rasbt/'
                     'python-machine-learning-book/master/code/'
                     'datasets/wdbc/wdbc.data', header=None)

if Version(sklearn_version) < '0.18':
    from sklearn.cross_validation import train_test_split
else:
    from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = \
    train_test_split(X, y, test_size=0.20, random_state=1)

PipeLine

パイプラインを使うと変換を一つにまとめて行うことができる。

以下はスケーリング、主成分分析、ロジスティック回帰をパイプラインで繋いで実行している。

from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline

pipe_lr = Pipeline([('scl', StandardScaler()),
                    ('pca', PCA(n_components=2)),
                    ('clf', LogisticRegression(random_state=1))])

pipe_lr.fit(X_train, y_train)
print('Test Accuracy: %.3f' % pipe_lr.score(X_test, y_test))
y_pred = pipe_lr.predict(X_test)

結果

Test Accuracy: 0.947

f:id:robonchu:20171028170058p:plain

モデルの評価

モデル選択:未知のデータへの予測性能を上げるため、パラメータ設定のチューニングや比較を行う。ここでのチューニングパラメータをハイパーパラメータということがある。

ホールドアウト法

ホールドアウト法でのモデル選択での効果を上げるには、データセット

  1. トレーニングデータセット:学習時

  2. 検証データセット:モデル選択時

  3. テストデータセット:性能評価

の3つにわける。

f:id:robonchu:20171028171105p:plain

問題はデータのサンプル数や分割の仕方に影響を受けることである。

k分割交差検証

非復元抽出を用いて、トレーニングデータセットをk個に分割し、k-1個をトレーニングに使用し、1個をテストに使用する。一般的には10分割することが多いが、小さいデータセットの場合などは1個抜き交差検証などが使用される。

非復元抽出:選んだ対象をサンプルに戻さない

f:id:robonchu:20171028172403p:plain

層化k分割交差検証

各クラスの比率が均等でない時に、評価のバイアスとバリアンスが改善される。

import numpy as np

if Version(sklearn_version) < '0.18':
    from sklearn.cross_validation import StratifiedKFold
else:
    from sklearn.model_selection import StratifiedKFold
    

if Version(sklearn_version) < '0.18':
    kfold = StratifiedKFold(y=y_train, 
                            n_folds=10,
                            random_state=1)
else:
    kfold = StratifiedKFold(n_splits=10,
                            random_state=1).split(X_train, y_train)

scores = []
for k, (train, test) in enumerate(kfold):
    pipe_lr.fit(X_train[train], y_train[train])
    score = pipe_lr.score(X_train[test], y_train[test])
    scores.append(score)
    print('Fold: %s, Class dist.: %s, Acc: %.3f' % (k+1,
          np.bincount(y_train[train]), score))
    
print('\nCV accuracy: %.3f +/- %.3f' % (np.mean(scores), np.std(scores)))

結果

CV accuracy: 0.950 +/- 0.029

skkearnで簡略化すると

if Version(sklearn_version) < '0.18':
    from sklearn.cross_validation import cross_val_score
else:
    from sklearn.model_selection import cross_val_score

scores = cross_val_score(estimator=pipe_lr,
                         X=X_train,
                         y=y_train,
                         cv=10,
                         n_jobs=1) #CPUのコア数を指定できる
print('CV accuracy scores: %s' % scores)
print('CV accuracy: %.3f +/- %.3f' % (np.mean(scores), np.std(scores)))

結果

CV accuracy scores: [ 0.89130435  0.97826087  0.97826087  0.91304348  0.93478261  0.97777778
  0.93333333  0.95555556  0.97777778  0.95555556]
CV accuracy: 0.950 +/- 0.029
参考

http://www.jmlr.org/papers/volume6/markatou05a/markatou05a.pdf

Improvements on Cross-Validation: The .632+ Bootstrap Method on JSTOR

アルゴリズムの診断

学習曲線

サンプルサイズの値の変化による評価

f:id:robonchu:20171028174053p:plain

バイアスが高い:トレーニングと検証の正解率が低い

バリアンスが高い:トレーニングと交差検証の精度に大きな差がある

import matplotlib.pyplot as plt

if Version(sklearn_version) < '0.18':
    from sklearn.learning_curve import learning_curve
else:
    from sklearn.model_selection import learning_curve



pipe_lr = Pipeline([('scl', StandardScaler()),
                    ('clf', LogisticRegression(penalty='l2', random_state=0))])

train_sizes, train_scores, test_scores =\
                learning_curve(estimator=pipe_lr,
                               X=X_train,
                               y=y_train,
                               train_sizes=np.linspace(0.1, 1.0, 10),
                               cv=10,
                               n_jobs=1)

train_mean = np.mean(train_scores, axis=1)
train_std = np.std(train_scores, axis=1)
test_mean = np.mean(test_scores, axis=1)
test_std = np.std(test_scores, axis=1)

plt.plot(train_sizes, train_mean,
         color='blue', marker='o',
         markersize=5, label='training accuracy')

plt.fill_between(train_sizes,
                 train_mean + train_std,
                 train_mean - train_std,
                 alpha=0.15, color='blue')

plt.plot(train_sizes, test_mean,
         color='green', linestyle='--',
         marker='s', markersize=5,
         label='validation accuracy')

plt.fill_between(train_sizes,
                 test_mean + test_std,
                 test_mean - test_std,
                 alpha=0.15, color='green')

plt.grid()
plt.xlabel('Number of training samples')
plt.ylabel('Accuracy')
plt.legend(loc='lower right')
plt.ylim([0.8, 1.0])
plt.tight_layout()
# plt.savefig('./figures/learning_curve.png', dpi=300)
plt.show()

結果

f:id:robonchu:20171028174518p:plain

fill_betweenによって標準偏差に色が塗られている

検証曲線

モデルのパラメータの変化に対する評価

if Version(sklearn_version) < '0.18':
    from sklearn.learning_curve import validation_curve
else:
    from sklearn.model_selection import validation_curve



param_range = [0.001, 0.01, 0.1, 1.0, 10.0, 100.0]
train_scores, test_scores = validation_curve(
                estimator=pipe_lr, 
                X=X_train, 
                y=y_train, 
                param_name='clf__C', 
                param_range=param_range,
                cv=10)

train_mean = np.mean(train_scores, axis=1)
train_std = np.std(train_scores, axis=1)
test_mean = np.mean(test_scores, axis=1)
test_std = np.std(test_scores, axis=1)

plt.plot(param_range, train_mean, 
         color='blue', marker='o', 
         markersize=5, label='training accuracy')

plt.fill_between(param_range, train_mean + train_std,
                 train_mean - train_std, alpha=0.15,
                 color='blue')

plt.plot(param_range, test_mean, 
         color='green', linestyle='--', 
         marker='s', markersize=5, 
         label='validation accuracy')

plt.fill_between(param_range, 
                 test_mean + test_std,
                 test_mean - test_std, 
                 alpha=0.15, color='green')

plt.grid()
plt.xscale('log')
plt.legend(loc='lower right')
plt.xlabel('Parameter C')
plt.ylabel('Accuracy')
plt.ylim([0.8, 1.0])
plt.tight_layout()
# plt.savefig('./figures/validation_curve.png', dpi=300)
plt.show()

結果 f:id:robonchu:20171028175051p:plain

C = 0.1あたりが最適だと見てとれる

グリッドサーチによるチューニング

機械学習にはデータから学習されるパラメータと個別に最適されるパラメータがある。後者はハイパーパラメータと呼ばれ、チューニングパラメータである。

グリッドサーチ:しらみつぶしの網羅的探索手法

from sklearn.svm import SVC
if Version(sklearn_version) < '0.18':
    from sklearn.grid_search import GridSearchCV
else:
    from sklearn.model_selection import GridSearchCV

pipe_svc = Pipeline([('scl', StandardScaler()),
            ('clf', SVC(random_state=1))])

param_range = [0.0001, 0.001, 0.01, 0.1, 1.0, 10.0, 100.0, 1000.0]

param_grid = [{'clf__C': param_range, 
               'clf__kernel': ['linear']},
                 {'clf__C': param_range, 
                  'clf__gamma': param_range, 
                  'clf__kernel': ['rbf']}]

gs = GridSearchCV(estimator=pipe_svc, 
                  param_grid=param_grid, 
                  scoring='accuracy', 
                  cv=10,
                  n_jobs=-1)
gs = gs.fit(X_train, y_train)
print(gs.best_score_)
print(gs.best_params_)

clf = gs.best_estimator_
clf.fit(X_train, y_train)
print('Test accuracy: %.3f' % clf.score(X_test, y_test))

結果

0.978021978022
{'clf__C': 0.1, 'clf__kernel': 'linear'}

Test accuracy: 0.965

欠点としては、考えられるすべての組み合わせについて評価するためコストが高くつく。

sk-learnにはRandomizedSearchCVというランダムサーチの手法を用いることができる。

入れ子式の交差検証によるアルゴリズムの選択

5x2交差検証の例

f:id:robonchu:20171028180655p:plain

SVM

gs = GridSearchCV(estimator=pipe_svc,
                  param_grid=param_grid,
                  scoring='accuracy',
                  cv=2)

# Note: Optionally, you could use cv=2 
# in the GridSearchCV above to produce
# the 5 x 2 nested CV that is shown in the figure.

scores = cross_val_score(gs, X_train, y_train, scoring='accuracy', cv=5)
print('CV accuracy: %.3f +/- %.3f' % (np.mean(scores), np.std(scores)))

結果

CV accuracy: 0.965 +/- 0.025

決定木分類器

from sklearn.tree import DecisionTreeClassifier

gs = GridSearchCV(estimator=DecisionTreeClassifier(random_state=0),
                  param_grid=[{'max_depth': [1, 2, 3, 4, 5, 6, 7, None]}],
                  scoring='accuracy',
                  cv=2)
scores = cross_val_score(gs, X_train, y_train, scoring='accuracy', cv=5)
print('CV accuracy: %.3f +/- %.3f' % (np.mean(scores), np.std(scores)))

結果

CV accuracy: 0.921 +/- 0.029

SVMのほうが性能が良いことがわかる

様々な性能評価指標

正解率以外にも様々な評価する指標が存在する

混同行列

真陽陰性(TP,TN)、偽陽陰性(FP,FN)を表現する行列

真偽:予測があたったかどうか

陽陰:予測されたクラス

ex: 偽陽性は予測は陽だが間違えた

f:id:robonchu:20171028181804p:plain

sklearn -> confusion_matrix(y_true=,y_pred=)

で作成できる

from sklearn.metrics import confusion_matrix

pipe_svc.fit(X_train, y_train)
y_pred = pipe_svc.predict(X_test)
confmat = confusion_matrix(y_true=y_test, y_pred=y_pred)
print(confmat)

fig, ax = plt.subplots(figsize=(2.5, 2.5))
ax.matshow(confmat, cmap=plt.cm.Blues, alpha=0.3)
for i in range(confmat.shape[0]):
    for j in range(confmat.shape[1]):
        ax.text(x=j, y=i, s=confmat[i, j], va='center', ha='center')

plt.xlabel('predicted label')
plt.ylabel('true label')

plt.tight_layout()
# plt.savefig('./figures/confusion_matrix.png', dpi=300)
plt.show()

結果

f:id:robonchu:20171028181955p:plain

誤分類率、正解率

  • ERR = (FP + FN) / (FP + FN + TP + TN)

  • ACC = 1 - ERR

真陽性、偽陽性

不均衡なクラスの問題に役立つ指標

  • FPR = FP / (FP + TN)

  • TPR = TP / (FN + TP)

 適合率、再現率

  • PRE = TP / (TP + FP)

  • REC = TP / (FN + TP)

F1スコア

適合率や再現率を組み合わせた評価指標。よく使用される。

F1 = 2 * (PRE * REC) / (PRE + REC)

sklearnでの評価手法の実装

from sklearn.metrics import precision_score, recall_score, f1_score

print('Precision: %.3f' % precision_score(y_true=y_test, y_pred=y_pred))
print('Recall: %.3f' % recall_score(y_true=y_test, y_pred=y_pred))
print('F1: %.3f' % f1_score(y_true=y_test, y_pred=y_pred))

結果

Precision: 0.976
Recall: 0.952
F1: 0.964

sk-learnではmake_scorerで自作の性能評価関数を作成できる

from sklearn.metrics import make_scorer

scorer = make_scorer(f1_score, pos_label=0)

c_gamma_range = [0.01, 0.1, 1.0, 10.0]

param_grid = [{'clf__C': c_gamma_range,
               'clf__kernel': ['linear']},
              {'clf__C': c_gamma_range,
               'clf__gamma': c_gamma_range,
               'clf__kernel': ['rbf']}]

gs = GridSearchCV(estimator=pipe_svc,
                  param_grid=param_grid,
                  scoring=scorer,
                  cv=10,
                  n_jobs=-1)
gs = gs.fit(X_train, y_train)
print(gs.best_score_)
print(gs.best_params_)

結果

0.982798668208
{'clf__C': 0.1, 'clf__kernel': 'linear'}

ROC曲線

受信者操作特性:性能に基づいて分類モデルを選択するための便利なツール

AUC:曲面下面積

from sklearn.metrics import roc_curve, auc
from scipy import interp

pipe_lr = Pipeline([('scl', StandardScaler()),
                    ('pca', PCA(n_components=2)),
                    ('clf', LogisticRegression(penalty='l2', 
                                               random_state=0, 
                                               C=100.0))])

X_train2 = X_train[:, [4, 14]]


if Version(sklearn_version) < '0.18':
    cv = StratifiedKFold(y_train, 
                         n_folds=3, 
                         random_state=1)
    
else:
    cv = list(StratifiedKFold(n_splits=3, 
                              random_state=1).split(X_train, y_train))

fig = plt.figure(figsize=(7, 5))

mean_tpr = 0.0
mean_fpr = np.linspace(0, 1, 100)
all_tpr = []

for i, (train, test) in enumerate(cv):
    probas = pipe_lr.fit(X_train2[train],
                         y_train[train]).predict_proba(X_train2[test])

    fpr, tpr, thresholds = roc_curve(y_train[test],
                                     probas[:, 1],
                                     pos_label=1)
    mean_tpr += interp(mean_fpr, fpr, tpr)
    mean_tpr[0] = 0.0
    roc_auc = auc(fpr, tpr)
    plt.plot(fpr,
             tpr,
             lw=1,
             label='ROC fold %d (area = %0.2f)'
                   % (i+1, roc_auc))

plt.plot([0, 1],
         [0, 1],
         linestyle='--',
         color=(0.6, 0.6, 0.6),
         label='random guessing')

mean_tpr /= len(cv)
mean_tpr[-1] = 1.0
mean_auc = auc(mean_fpr, mean_tpr)
plt.plot(mean_fpr, mean_tpr, 'k--',
         label='mean ROC (area = %0.2f)' % mean_auc, lw=2)
plt.plot([0, 0, 1],
         [0, 1, 1],
         lw=2,
         linestyle=':',
         color='black',
         label='perfect performance')

plt.xlim([-0.05, 1.05])
plt.ylim([-0.05, 1.05])
plt.xlabel('false positive rate')
plt.ylabel('true positive rate')
plt.title('Receiver Operator Characteristic')
plt.legend(loc="lower right")

plt.tight_layout()
# plt.savefig('./figures/roc.png', dpi=300)
plt.show()

f:id:robonchu:20171028184903p:plain

AUCの計算

pipe_lr = pipe_lr.fit(X_train2, y_train)
y_labels = pipe_lr.predict(X_test[:, [4, 14]])
y_probas = pipe_lr.predict_proba(X_test[:, [4, 14]])[:, 1]
# note that we use probabilities for roc_auc
# the `[:, 1]` selects the positive class label only

from sklearn.metrics import roc_auc_score, accuracy_score
print('ROC AUC: %.3f' % roc_auc_score(y_true=y_test, y_score=y_probas))
print('Accuracy: %.3f' % accuracy_score(y_true=y_test, y_pred=y_labels))

多クラス分類の性能指標

sk-learnでは以下が実装されている

  1. マクロ平均法

  2. マイクロ平均法

マイクロ平均

インスタンスまたは予測を平等に重みつけしたいとき

PREmicro = (TP1 + ... + TPk) / (TP1 + ... + TPk + FP1 + ... + FPk)

マクロ平均

最も出現するクラスラベルに過度に影響を受けることがないよう評価したいとき

PREmacro = (PRE1 + ... + PREk) / k

pre_scorer = make_scorer(score_func=precision_score, 
                         pos_label=1, 
                         greater_is_better=True, 
                         average='micro')

proxyのお勉強

プロキシとは、企業などの内部ネットワークとインターネットの境界にあり、内部のコンピュータの「代理」(proxy)としてインターネット上のコンピュータへ接続を行うコンピュータのこと。また、そのような機能を持つサーバソフトウェア。

http://wa3.i-3-i.info/word1752.html

e-words.jp

わかりやすい参考

proxy環境下の設定(ubuntu 14.04) - Qiita

$ export https_proxy="http://username:password@your.proxy.address:proxy.port/"

環境変数の引き継ぎ

sudo -E apt-get ~

環境変数の削除

$ unset https_proxy

avahiのお勉強

f:id:robonchu:20171025213237p:plain

avahi

Avahi(アバヒ)は、Zeroconfのフリーソフトウェア実装であり、マルチキャストDNS/DNS-SD サービスディレクトリのためのシステムを含む。

Avahi - Wikipedia

avahi-daemon - The Avahi mDNS/DNS-SD daemon - Linux Man Pages (8)

[Ubuntu] Avahiのコマンド一覧 - Life with IT

avahiとmDNS - Qiita

hostnameの重複を許す

enable-reflector=yes

ホスト名のコンフリクトについて

avahi daemonは、起動時にはコンフリクトメッセージを出さずにホスト名を取得します。 また、一度ホスト名を決定した後は、ホスト名をキャッシュし、ifup/downで同じホスト名を使い続けるので 一度ホスト名が決まってしまえば 下記のような場合を除いてifup/downで衝突は起きません。

hostname conflict with avahi (post 3.0) · Issue #1426 · pi-hole/pi-hole · GitHub

avahi-daemonのシステムログの内容について | アットマークテクノ ユーザーズサイト

linux - Avahi Hostname Resolution: Is it caching somewhere? - Stack Overflow

linux.die.net

How do I flush out the DNS resolver cache? - Ask Ubuntu

Re: [DNG] how to clear DNS cache

-> /etc/resolv.conf

DNSキャッシュのクリア

How To: Flush Your Local DNS Cache – Liquid Web Knowledge Base

sudo service dns-clean restart

/etc/hosts

127.0.1.1 robonchu

/etc/nsswitch.conf

名前解決の参照順位が設定されている

hosts: files mdns4_minimal [NOTFOUND=return] dns nis

filesは/etc/hostsファイルをdnsは、DNSサーバーを意味します。

mdns:マルチキャストDNS

JVNVU#98589419: マルチキャスト DNS (mDNS) 実装が外部からのユニキャストクエリに応答する問題

nis

ネットワーク・インフォメーション・サービス - Wikipedia

UNIXコマンド、シェルスクリプトのお勉強

Unix Command

  • mkdir app{1..40}

  • pwd

  • clear

  • cd

  • rmdir

  • ls

  • cat text.txt : 全文表示

  • less text.txt

    • /<検索したいワード>
  • mv

  • ctrl+r :直近のコマンドを探す

  • history : 履歴を呼び出す

  • !<historyで出たID> : 履歴のコマンドを実行

  • cd !$ : commadに渡した最後の文字を利用する

  • !pw : pwから始まる直近のコマンドを実行できる

  • man ls

  • mkdir --help

  • touch

vim

  • vi

  • command mode: esc key

    • 保存->:w

    • 抜ける->:q

  • 編集モード: i

  • ln -s

  • unlink

user, group

  • cat /etc/passwd

  • cat /etc/group

  • groups

permission

rwxrw-r--

  • rwx : user

  • rw- : group

  • r-- : other

read,write,execute

  • chmod g+x

  • chmod go+x

  • chmod a-x

  • rwx : 4+2+1 = 7

  • rw- : 4+2+0 = 6

  • r-- : 4+0+0 = 4

  • chmod 764

command make

  • type cat

  • vi hi

#!/bin/bash
echo "hi!"
  • chmod u+x hi

  • ./hi

pathを通す

  • echo $PATH

ここから探してコマンドを実行する

  • printenv

  • export PATH=/:$PATH

  • hi

  • which hi

管理者user

  • ls -l /var/log/message

  • cat !$

  • su -l : root userに切り替える

  • cat /var/log/messages

  • sudo cat /var/log/messages

chown

  • cp /var/log/messages .

  • sudo !!

  • cat messages

  • sudo chown : messages

  • cat messages

text operation

  • wc -l messages

  • head messages

  • head -n 3 messages

  • tail -n 3 messages

  • grep 'etc' messages

redirection,pipe

  • echo "date" > cmd.txt

  • cat cmd.txt

  • echo "free" >> cmd.txt

  • bash < cmd.txt

  • bash < cmd.txt > result.txt

  • cat result.txt

  • ls -l /etc | grep "php" | wc -l

ワイルドカード

  • ls /etc/*.conf

  • ls /etc/c??.*

find,xargs

  • find /etc -name "http*"

  • sudo !!

  • find /etc -name "http*" -type f -exec wc -l {} +

  • find /etc -name "http*" -type f | xargs wc -l

ブレース展開

  • echo {a,b,c}

  • echo {1..10}

  • echo {1..10}{a..g}

  • make test && cd test

  • mkdir app{1..5}

  • touch app{1..5}/test{1..3}{.txt,.jpeg,.gif}

  • rm app{1..5}/test{1..3}{.jpeg,.gif}

shell

./hello a aa aaa

#!/bin/bash
# comment

# $1, $2, ...

echo "hello $1"
echo $0  # ./hello
echo $#  # 3
echo $@  # $* a aa aaa

greeting="hello" #space入れちゃダメ!

echo "hello world"
echo 'hello world'
echo "hello robot"

echo "$greeting world"
echo '$greeting world' #展開されない
echo "${greeting}robot"

echo "foo"; echo "bar"

ディレクト

bin:実行コマンド

etc:設定

home:各ユーザー

sbin:システム管理用のコマンド

usr:一般的なアプリケーション

var:システムのログファイル

参考

https://dotinstall.com/lessons/basic_unix_v2

https://dotinstall.com/lessons/basic_shellscript_v2

Dockerのお勉強

f:id:robonchu:20171023214405p:plain

概要

Build once, run anywhere

Docker - Build, Ship, and Run Any App, Anywhere

VagrantUbuntuを用意する

Vagrantは、開発環境の構築と共有を簡単に行うためのツールです。どこでも同じ環境を再現できるように仮想マシン環境を管理する機能と、Atlasを通して共有する仕組みが提供されています。

開発環境の構築・共有を簡単にするVagrant入門 | Think IT(シンクイット)

A list of base boxes for Vagrant - Vagrantbox.es

Official Ubuntu 14.04 daily Cloud Image amd64 (Development release, No Guest Additions) をインストール

sudo apt-get install vagrant

vagrant box add trusty64 https://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box

sudo apt-get install virtualbox

mkdir Docker && cd Docker

vagrant init

vagrant up

vagrant ssh

こうするとvagrant user で以下のように起動できていることが確認できる

vagrant@vagrant-ubuntu-trusty-64:~$

Dockerで環境構築

docker-ceのインストール

Get Docker CE for Ubuntu | Docker Documentation

UbuntuにDocker CEをインストールする - Qiita

確認:sudo docker --version

imageの操作

sudo docker search centos

sudo docker pull centos

sudo docker images

sudo docker inspect centos:latest

sudo docker rmi <id>

sudo docker run centos echo "hello world"

sudo docker ps -a -n=5  (a:過去を表示、-n:最新5つ)

sudo docker rm <id>

sudo docker run -d centos free -s 3

sudo docker ps

sudo docker logs <id>

sudo docker attach --sig-proxy=false <id>

sudo docker kill <id>

sudo docker start <id>

sudo docker run -i -t centos /bin/bash  (-i:インタラクティブ, -t:ターミナル)

touch hello.txt

exit

sudo docker ps -a

sudo docker commit <id> robonchu/hello

sudo docker images

sudo docker run -i -t robonchu/hello /bin/bash

ls

これでhello.txtがあることが確認できる

docker build

emacs -nw Dockerfile

FROM centos

MAINTAINER robonchu <robonchu@gmail.com>

# RUN: build時に実行

RUN echo "now building..."

# CMD: run時に実行

# CMD echo "now running..."

CMD ["echo", "now running..."]

以下でrun commitの動作、つまりimageからcontainer、そして、imageにする動作が行えることが確認できる

sudo docker build -t robonchu/echo .

sudo docker run robonchu/echo

さらに emacs -nw Dockerfile

RUN yum install -y httpd
ADD ./index.html /var/www/html/
EXPOSE 80
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]

emacs -nw index.html

<html>
hello from Docker!
</html>
sudo docker build -t robonchu/httpd .

sudo docker run -p 8080:80 -d robonchu/httpd

ウェブページを開いて、192.168.55.44:8080でhello from Docker!がでていることを確認

Imageをpush

https://hub.docker.com/

上記の登録が必要

sudo docker login

sudo docker push robonchu/httpd

参考

https://dotinstall.com/lessons/basic_docker

Dockerにおけるコンテナのライフサイクル - めもめも

Dockerでよく使うコマンドまとめ | 酒と涙とRubyとRailsと

さわって理解するDocker入門 第1回 | オブジェクトの広場

Dockerコンテナとイメージの仕組みを視覚化してみた | FAworksブログ

Dockerコンテナとイメージの仕組みを視覚化してみた | FAworksブログ

機械学習のお勉強(自作データセットでCNN by pytorch)

f:id:robonchu:20171017221616p:plain

CNNを用いた簡単な2class分類をしてみる

Pytorch tutorial

Training a Classifier — PyTorch Tutorials 1.4.0 documentation

Transfer Learning for Computer Vision Tutorial — PyTorch Tutorials 1.4.0 documentation

Writing Custom Datasets, DataLoaders and Transforms — PyTorch Tutorials 1.4.0 documentation

DataSetの作成

https://download.pytorch.org/tutorial/hymenoptera_data.zip

ここからアリさんとハチさんのデータセットをダウンロード

ディレクトリ構成

  • train

    • ants
    • bees
  • val

    • ants
    • beets

となっている。

このように自分で作ったデータセットを用意してあげる。

DataLoader

# -*- coding: utf-8 -*-
import torch
from torchvision import transforms, datasets

# 取り込んだデータに施す処理を指定
data_transform = transforms.Compose([
        transforms.RandomSizedCrop(224),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406],
                             std=[0.229, 0.224, 0.225])
    ])

# train data読み込み
hymenoptera_dataset = datasets.ImageFolder(root='hymenoptera_data/train',
                                           transform=data_transform)
dataset_loader = torch.utils.data.DataLoader(hymenoptera_dataset,
                                             batch_size=4, shuffle=True,
                                             num_workers=4)

# test data読み込み
hymenoptera_testset = datasets.ImageFolder(root='hymenoptera_data/val',
                               transform=data_transform)
dataset_testloader = torch.utils.data.DataLoader(hymenoptera_testset, batch_size=4,
                                         shuffle=False, num_workers=4)

classes = ('ants', 'bees')

データセットの形は

for i, data in enumerate(dataset_loader, 0):
    inputs, labels = data
    print inputs.size()
    print labels.size()

->
(4L, 3L, 224L, 224L)
(4L,)

となる。

自作transformsの使い方

class Crop(object):
    """Crop the image.

    Args:
        left_up (tuple): Desired crop left up position.
        right_down (tuple): Desired crop right down position.
    """
    def __init__(self, left_up, right_down):
        self._left_up = left_up
        self._right_down = right_down

    def __call__(self, img):
        image = img.crop((self._left_up[0], self._left_up[1], self._right_down[0], self._right_down[1]))
        return image

これを以下のように使用すれば良い

data_transform = transforms.Compose([
        transforms.Scale(224), 
        Crop((50,100),(100,200)),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.5, 0.5, 0.5],
                             std=[0.5, 0.5, 0.5])
    ])

PILの使い方

pytorchの画像の読み込み、処理はPILを使っている

PIL/Pillow チートシート - Qiita

Model Definition

from torch.autograd import Variable
import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 53 * 53, 120) # (((224 - 4) / 2 ) - 4) / 2 = 53
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 2)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16 * 53 * 53)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

net = Net()

Training

import torch.optim as optim

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

for epoch in range(1):  # loop over the dataset multiple times

    running_loss = 0.0
    for i, data in enumerate(dataset_loader, 0):
        # get the inputs
        inputs, labels = data

        # wrap them in Variable
        inputs, labels = Variable(inputs), Variable(labels)

        # zero the parameter gradients
        optimizer.zero_grad()

        # forward + backward + optimize
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        # print statistics
        running_loss += loss.data[0]
        if i % 10 == 9:    # print every 10 mini-batches
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 10))
            running_loss = 0.0

print('Finished Training')

total evaluation

correct = 0
total = 0
for data in dataset_testloader:
    images, labels = data
    outputs = net(Variable(images))
    _, predicted = torch.max(outputs.data, 1)
    total += labels.size(0)
    correct += (predicted == labels).sum()

print('Accuracy of the network on the test images: %d %%' % (
    100 * correct / total))

each class evaluation

class_correct = list(0. for i in range(2))
class_total = list(0. for i in range(2))
for data in dataset_testloader:
    images, labels = data
    outputs = net(Variable(images))
    _, predicted = torch.max(outputs.data, 1)
    c = (predicted == labels).squeeze()
    try:
        for i in range(4):
            label = labels[i]
            class_correct[label] += c[i]
            class_total[label] += 1
    except:
        break

for i in range(2):
    print('Accuracy of %5s : %2d %%' % (
        classes[i], 100 * class_correct[i] / class_total[i]))