scikit-learnで混同行列を求める
python向け機械学習ライブラリであるscikit-learnを使って、混同行列を計算します。
scikit-learnのインストール
多くの場合は下記コマンドでインストール可能です。 より詳しいインストール方法は公式ドキュメントを参照してください。
pipの場合
pip install -U scikit-learn
Anacondaの場合
conda install -c conda-forge scikit-learn
import
scikit-learnからconfusion_matrix関数を読み込みます。
from sklearn.metrics import confusion_matrix
使用するデータの定義
y_true = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1] y_pred = [0, 1, 0, 0, 0, 1, 0, 1, 0, 1]
y_true
が正解ラベル、y_pred
が予測ラベルです。
陽性を1、陰性を0とします。
混同行列の計算
confusion_matrix関数の第一引数に正解ラベル、第二引数に予測ラベルを与え、混同行列を計算します。
# 混同行列の計算 ((tn, fp), (fn, tp)) = confusion_matrix(y_true, y_pred) # 結果表示 print("TP", tp) print("TN", tn) print("FP", fp) print("FN", fn)
結果は次の通りになります。
TP 3 TN 4 FP 1 FN 2
- True Positive(TP):正解が陽性で予測も陽性
- True Negative(TN):正解が陰性で予測も陰性
- False Positive(FP):正解が陰性で予測が陽性
- False Negative(FN):正解が陽性で予測が陰性
その他評価指標の計算
混同行列さえ計算できれば、あとは単純な数値計算によりAccuracy、Precision、Recallの計算が可能です。
# 評価指標計算 accuracy = (tp + tn) / (tp + tn + fp + fn) recall = tp / (tp + fn) precision = tp / (tp + fp) # 結果表示 print("Acc", accuracy) print("Rec", recall) print("Pre", precision)
結果は次の通りになります。
Acc 0.7 Rec 0.6 Pre 0.75
- Accuracy:全データ中、陽性・陰性を正しく当てられたものの割合
- Recall:正解が陽性であるもののうち、予測で陽性と判定されたものの割合
- Precision:予測で陽性と判定されたもののうち、正解が陽性であるものの割合
PythonのNetworkXパッケージを使って重み付き有向グラフの最短経路をダイクストラ法で求める
Pythonのネットワーク計算パッケージ「NetworkX」を使用して重み付き有向グラフの最短経路をダイクストラ法で求めます。
NetworkXのインストール
下記のようにpipでインストールができます。
pip install networkx
今回はNetworkX2.2を使用しました。
グラフ
下図のノードAからノードEまでの最短経路を求めます。 有向グラフのため矢印を逆戻りすることはできません。
コード
# coding:utf-8 import networkx as nx # ノード(頂点)のリスト NODE_LIST = ["A", "B", "C", "D", "E"] # エッジ(辺)のリスト # (始点, 終点, 重み) EDGE_LIST = [ ("A", "B", 2), ("A", "C", 5), ("A", "D", 9), ("B", "C", 2), ("B", "D", 7), ("C", "D", 4), ("D", "E", 1) ] # グラフの定義 DG = nx.DiGraph() DG.add_nodes_from(NODE_LIST) DG.add_weighted_edges_from(EDGE_LIST) # 出発地ノードと目的地ノードを設定 start = "A" end = "E" # ダイクストラ法で最短経路とその重みを求める shortest_path = nx.dijkstra_path(DG, start, end) shortest_path_weight = nx.dijkstra_path_length(DG, start, end) # 出力 print("Shortest Path:", shortest_path) print("Weight:", shortest_path_weight)
出力結果
最短経路とその重みを求めることができました。
Shortest Path: ['A', 'B', 'C', 'D', 'E'] Weight: 9
「ファイルを開く」や「名前を付けて保存」のコモンダイアログの動作が遅くなる問題
「ファイルを開く」や「名前を付けて保存」のコモンダイアログの動作が遅くなる問題を解決した。 私の場合はKDriveが原因だったが、おそらくこれレアケースで通常は別の個所に問題がある。 今回はレアケースなだけあってネット上に適切な解決方法が一切なかったため、誰かの役に立つことを願って解決までの道筋を公開する。
現象
Windows7からWindows10にアップグレードしたところ、一部のアプリケーション(Firefox, Chrome, Visual Studio Code等)で
- ①「ファイルを開く」や「名前を付けて保存」のダイアログの表示が遅くなった
- ② 前触れなく突然クラッシュするようになった
ネットにある解決法をいろいろ試したが、どれも効果がでなかった。 どうやら「ファイル数が多すぎる」「サムネイル表示に時間がかかっている」「メモリ破損」「システムファイル破損」といった一般的事象が原因ではないようだ。
原因究明
================ 障害が発生しているアプリケーション名: firefox.exe、バージョン: 61.0.2.6793、タイム スタンプ: 0x5b69def1 障害が発生しているモジュール名: ntdll.dll、バージョン: 10.0.17134.228、タイム スタンプ: 0x6d15b6d7 例外コード: 0xc0000005 障害オフセット: 0x00000000000182cd 障害が発生しているプロセス ID: 0x2a00 障害が発生しているアプリケーションの開始時刻: 0x01d44073be6f066e 障害が発生しているアプリケーション パス: C:\Program Files (x86)\Mozilla Firefox\firefox.exe 障害が発生しているモジュール パス: C:\WINDOWS\SYSTEM32\ntdll.dll レポート ID: 7f9c82a9-0fb1-40b6-a56b-cb75bf2e15ee 障害が発生しているパッケージの完全な名前: 障害が発生しているパッケージに関連するアプリケーション ID: ================
(例外コード0xc0000005はメモリアクセス違反)
- また、クラッシュした瞬間には次のようなエラーログが出ていた。
================ 障害が発生しているアプリケーション名: firefox.exe、バージョン: 61.0.2.6793、タイム スタンプ: 0x5b69def1 障害が発生しているモジュール名: kliveshellext64.dll_unloaded、バージョン: 1.21.0.918、タイム スタンプ: 0x4e7940ca 例外コード: 0xc0000005 障害オフセット: 0x0000000000025700 障害が発生しているプロセス ID: 0x2a00 障害が発生しているアプリケーションの開始時刻: 0x01d44073be6f066e 障害が発生しているアプリケーション パス: C:\Program Files (x86)\Mozilla Firefox\firefox.exe 障害が発生しているモジュール パス: kliveshellext64.dll レポート ID: 5c46cb9c-e6c9-45dd-8880-d4625617f47b 障害が発生しているパッケージの完全な名前: 障害が発生しているパッケージに関連するアプリケーション ID: ================
解決
- プリインストールされていたKDriveをアンインストールしたところ現象①②ともに発生しなくなった。
dockerを使ってMattermostを立ち上げる
mattermost/mattermost-dockerのReadmeに沿ってdockerを使ってMattermostをセットアップしたメモ。 思いのほか簡単にできた。
試した環境
- OS:Ubuntu 16.04
- 使用したリポジトリ:mattermost/mattermost-docker(コミットea79d25)
- 非プロキシ環境
手順
必要なソフトとファイルの準備
docker及びdocker-composeを下記コマンドでインストールする。
sudo apt update && sudo apt upgrade -y sudo apt install docker docker-compose
下記A、BのどちらかでMattermostのdockerファイル群を取得
- (A) gitが使える場合は、下記コマンドでclone
git clone https://github.com/mattermost/mattermost-docker.git
- (B) gitが使えない場合はGitHubのリポジトリにブラウザでアクセスし、画面右部の緑色の「Clone or download」をクリックし、「Download ZIP」をクリックしてダウンロードする。その後unzip等で展開する。
mattermost-dockerディレクトリへ移動
cd mattermost-docker
以後、mattermost-dockerディレクトリをカレントディレクトリとして説明する
初期設定
docker-compose.ymlを下記コマンドで開く。エディタはnanoでなくとも、viでもvimでもemacsでもなんでもOK。
nano docker-compose.yml
下記2行がコメントアウトされているので解除する。それぞれ行の#とその直後の半角スペース1つを削除すればOK。
args: - edtion=team
下記2行を探し、mmuser_password(データベースのパスワード)を別のものに変える。2つとも同じものにすること。
POSTGRES_PASSWORD=mmuser_password
MM_PASSWORD=mmuser_password
ここまでできたら保存し、エディタを閉じる。
Mattermostがデータを保存するために使うディレクトリを作成する
下記コマンドでディレクトリを作成し、所有権を変更する。
mkdir -p ./volumes/app/mattermost/{data,logs,config} sudo chown -R 2000:2000 ./volumes/app/mattermost/
初回起動
下記コマンドでコンテナを生成し起動する。
sudo docker-compose up
コンテナが起動したら、ブラウザでhttp://localhost/にアクセスするとMattermostが起動している。
一時停止
一時的にコンテナを停止したい場合は下記のコマンドを使う。
sudo docker-compose stop
2回目以降の起動
すでにコンテナを生成済みである場合(upしてstopしたときなど)は、下記コマンドで再開できる。
sudo docker-compose start
停止してコンテナを削除
コンテナを停止して削除したい場合は下記のコマンドを使う。
docker-compose stop docker-compose rm
Mattermostが生成したデータもすべて消す場合は、追加で下記コマンドを実行する。
sudo rm -rf volumes
Python3でコードを並列実行して高速化する
コードを並列実行する方法はマルチスレッドを使う方法とマルチプロセスを使う方法がありますが、Pythonはグローバルインタプリタロック(GIL)と呼ばれる仕組みにより同一プロセス内では常に1スレッドしか進行できません。そのため、マルチスレッドを使う方法は高速化につながりません(ブロッキングI/Oを使う場合を除く)。 高速化を目的として並列実行している場合はマルチプロセスを使いましょう。
コード
適当な重い処理を「並列実行なし」、「マルチスレッド」、「マルチプロセス」で実行して所要時間を表示します。 マルチスレッドとマルチプロセスの実現にはpython3.2で追加されたconcurrent.futuresモジュールを使用しました。
import concurrent.futures import time # 適当な重い処理 def allsum(num): a = 0 for i in range(num): a += i return a def main(): nums = [4927814, 4142984, 6154248, 4149289, 4421984, 4812798, 4724198, 4421949] # 並列実行なし start = time.time() ans1 = list(map(allsum, nums)) end = time.time() print("normal = %.3f sec" % (end-start)) # マルチスレッドによる並列実行 start = time.time() with concurrent.futures.ThreadPoolExecutor(max_workers=8) as pool: ans2 = list(pool.map(allsum, nums)) # <= ThreadPoolExecutorのmapを呼ぶ end = time.time() print("thread pool = %.3f sec" % (end-start)) # マルチプロセスによる並列実行 start = time.time() with concurrent.futures.ProcessPoolExecutor(max_workers=8) as pool: ans3 = list(pool.map(allsum, nums))# <= ProcessPoolExecutorのmapを呼ぶ end = time.time() print("process pool = %.3f sec" % (end-start)) if __name__ == '__main__': main()
実行結果
論理コア数8のCPUを搭載したマシンでプログラムを実行した結果です。 並列実行なしとマルチスレッドの所要時間はほぼ同じで、マルチプロセスのみ高速化に成功していることが読み取れます。
normal = 1.838 sec thread pool = 1.859 sec process pool = 0.752 sec
Pythonでパケットキャプチャ(Windows用)
RAWソケットを使ってWindowsでパケットキャプチャを行います。 実行には管理者権限が必要です。このスクリプトでキャプチャできるのはIPから上位のレイヤーであり、Ethernetヘッダはキャプチャできません。
コード
import socket MYHOST = "自分のIPアドレスを入れる" def hexdump(data): result = [] for i in range(0, len(data), 16): binary = " ".join(["%02X" % x for x in data[i:i+16]]) text = "".join(chr(x) if 0x20 <= x <= 0x7E else "." for x in data[i:i+16]) result.append("[%04X] %-48s %s" % (i, binary, text)) print("\n".join(result)) with socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP) as sock: sock.bind((MYHOST, 0)) sock.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) sock.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) try: while True: hexdump(sock.recvfrom(65536)[0]) print("") except: pass finally: sock.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
pythonでマウスカーソルを移動させる(Windows API使用)
Windows APIのSetCursorPosをpythonのctypesライブラリから呼び出し、マウスカーソルの座標を指定します。
コード
下記コードはx座標100・y座標50の地点へマウスカーソルを移動させます
import ctypes # 座標(x, y)にマウスカーソルを移動させる def SetCursorPos(x, y): ctypes.windll.user32.SetCursorPos(x, y) # 使用例 def main(): x = 100 y = 50 SetCursorPos(x, y) if __name__ == '__main__': main()