【Laravel/Vue】postのパラメータの書き方ミスって419エラーと勘違いした話
はじめに
現在Laravel/Vue.jsでマッチングサイトを作っており、その際認証周りの経験が浅くしょうもないところで詰まってしまった話。
環境
vue@2.6.11
Laravel Framework 6.5.0
Firefox 73.0.1
起こったこと
php/laravel/vueを使ったSPAのマッチングサイトを作っており、お気に入り機能実装時にaxiosのpostメソッドを追加。
別の部分に書かれてるgetメソッドを一旦コピペしてpostに変え、パラメータを以下のように修正しました。
※コードはサンプル。
#コピペ元 getBandList() { axios.get("/matching", { params: { offset: this.offset, limit: this.limit } }) .then(res => { this.records = res.data.recordList; }); }, #コピペ後 addFavoriteList() { axios.post("/addFavorite", { params: { //※ここが間違い hoge: 'hoge', fuga: 'fuga', } }) .then(res => { this.message = res.data }); }, #コントローラー class FavoriteListController extends Controller { public function addFavorite(Request $request) { $id = Auth::id(); $hoge = $request->input('hoge'); $fuga = $request->input('fuga'); //なにかしらの処理 .... } #web.php Route::group(['middleware' => 'auth'], function () { Route::get('/addFavorite', 'FavoriteListController@addFavorite'); ... }
getメソッドをコピッたのでparamsを消し忘れており、500エラーが発生。問題はここから。
firefoxのデベロッパーツールで確認しており、ネットワークから500の部分をダブルクリックして、別タブでエラーの内容を確認しようとしました。
すると、419 Page Expired が。
ここで、419エラーと勘違いし、CSRF token関連のエラー記事を参考に試行錯誤を繰り返してしまいました。
※ちなみに、元のネットワーク画面の応答にサーバーのエラー内容ががっつりのってますw
色々と試してるうちに、他のpostメソッドでもネットワークをダブルクリックすると419ページに飛ぶことから、別タブで開いたことがCSRF token認証に失敗の原因であることに気が付きました。
ちなみに、上記操作をchromeで行うと500エラーの内容が表示されました。
firefoxではネットワークから別タブで開いた場合 token情報を持っていませんでしたが、chromeはtoken情報を持っていたため419が発生せず。
ブラウザ間でこういう違いもあるんですね。 ( ̄- ̄)フーン ナルホド
終わりに
ちゃんとコンソール見ましょう。あと疲れたら早く寝ましょう。
【NGS】velvet・SPADesを使ったアセンブル
OS Ubuntu 18.04.2
conda 4.7.11
velvet インストール
# Anacondaでインストール conda install -c bioconda velvet
アセンブル (k-mer 21)
k-mer は奇数しか指定できないので注意。
#処理するデータの準備。(fastaでもok) velveth vel_21 21 -shortPaired -fastq **.fastq #コンティグ作成 velvetg vel_21 -ins_length 300 -read_trkg yes -amos_file yes #結果ファイル less vel_21/Log
SPADes インストール
# Anacondaでインストール conda install -c bioconda spades
アセンブル (kmer 21 ~ 55)
spades.py -k 21,33,55,77 --careful --only-assembler **.fastq -o spades_output
isucon手順まとめ
isucon9に出場し予選落ちしました。
isucon7の問題を多少練習したので(isucon8もちょっと)、チーム内のwikiが消えても大丈夫なようその時の手順をメモします。
自分用なので雑。
初期設定
alp 導入
#ダウンロード wget https://github.com/tkuchiki/alp/releases/download/v0.3.1/alp_linux_amd64.zip unzip alp_linux_amd64.zip #インストール sudo install ./alp /usr/local/bin #nginxの設定ファイルを修正 sudo vim /etc/nginx/nginx.conf #設定ファイルのhttp {の部分に以下の内容を追加します。 http { log_format ltsv "time:$time_local" "\thost:$remote_addr" "\tforwardedfor:$http_x_forwarded_for" "\treq:$request" "\tmethod:$request_method" "\turi:$request_uri" "\tstatus:$status" "\tsize:$body_bytes_sent" "\treferer:$http_referer" "\tua:$http_user_agent" "\treqtime:$request_time" "\truntime:$upstream_http_x_runtime" "\tapptime:$upstream_response_time" "\tcache:$upstream_http_x_cache" "\tvhost:$host"; access_log /var/log/nginx/access.log ltsv; } #元のアクセスログを削除し、リロード sudo rm /var/log/nginx/access.log && sudo systemctl reload nginx #ベンチ実行 /home/isucon/torb/bench/bin/bench -data=/home/isucon/torb/bench/data -remotes=localhost -output=result.json #alp確認 alp -f /var/log/nginx/access.log alp --sum -f /var/log/nginx/access.log
netdata インストール (使わんかったけど一応)
#ワンライナーで起動までしてくれる。 bash <(curl -Ss https://my-netdata.io/kickstart.sh) all --dont-wait #firewall ポート穴あけ firewall-cmd --zone=public --add-port=19999/tcp --permanent systemctl reload firewalld.service #ブラウザで確認 http://127.0.0.1:19999/ #停止 systemctl stop netdata #起動 systemctl start netdata
slow-log出力
MYSQL系の設定ファイルである/etc/my.cnfに以下のように設定を追加する
[mysqld] # 以下の3行を追加する slow_query_log slow_query_log_file = mysql-slow.log long_query_time = 0.5 このように設定すると、/var/lib/mysql配下にmysql-slow.logが出力されるようになるはず サービスの再起動を忘れずにね systemctl restart mariadb
pt-query-digestのインストール
以下のコマンドでインストールできる! #cent0s yum install http://www.percona.com/downloads/percona-release/redhat/0.1-3/percona-release-0.1-3.noarch.rpm yum install percona-toolkit #ubuntu wget https://www.percona.com/downloads/percona-toolkit/3.0.10/binary/debian/xenial/x86_64/percona-toolkit_3.0.10-1.xenial_amd64.deb sudo apt-get install gdebi sudo gdebi percona-toolkit_3.0.10-1.xenial_amd64.deb あとは上記で出力したスロークエリログを解析する pt-query-digest /var/lib/mysql/mysql-slow.log
mysql ダンプ
サーバ内の初期データをdumpにする
以下のコマンドでisubataテーブルだけを対象にdumpを作成する mysqldump --single-transaction -u isucon -p isubata > /tmp/isubata_init.dump 出力したdumpを適当にWinSCPとかでローカルに持ってくる
サービスをPythonに変更する
# サービスを停止する systemctl stop torb.perl.service # サーバ起動時に起動するサービスから除外する systemctl disable torb.perl.service # サービスを開始する # sudo systemctl start torb.go.service sudo systemctl start torb.python.service systemctl enable torb.python.service
DB回り改善
インデックス確認、作成
#テーブル名、カラム名などは適宜置き換えてください。 mysql>explain SELECT COUNT(*) as cnt FROM message WHERE channel_id = 10 #type が ALL/indexだと遅い。 #インデックス追加 ※カラムの順番重要 mysql>ALTER TABLE message ADD INDEX index_name(channel_id, id); #インデックス削除※間違った時用 mysql>ALTER TABLE message DROP INDEX index_name; https://qiita.com/katsukii/items/3409e3c3c96580d37c2b http://tech.aainc.co.jp/archives/4634
外部mySQLへの接続
#mysqlのデフォルトポート3306の通信を許可する sudo ufw allow 3306 ※firewallが無効になっていたら無視。 mysqld.cnfの編集 sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf #bind-addressをコメントアウトする。 bind-address = 127.0.0.1 #rootユーザはどのIPからもアクセス可能に mysql> grant all privileges on [データベース名].* to root@"%" identified by 'パスワード' with grant option #外部mySQLへの接続が確認できたら、app側のsqlへの接続設定も変更する。
nginx周り改善
#ヘッダーへCache-Control追加 #/etc/nginx/sites-available/default server{ add_header Cache-Control public; } https://qiita.com/syou007/items/3e2d410bbe65a364b603 #ロードバランサ振り分け処理 #/etc/nginx/nginx.conf 追記 http { upstream degumainux.com { #ip_hash; #least_conn; server [ip]:[port]; server [ip]:[port]; } server { location / { proxy_set_header Host $http_host; proxy_pass http://degumainux.com; } } }
カーネル回り
#somaxconn数変更 #確認 sysctl net.core.somaxconn #somaxconn書き換え(一時的) sysctl -w net.core.somaxconn=1024 #somaxconn書き換え(永続化) #/etc/sysctl.confに追加 net.core.somaxconn = 1024 #リロード sysctl -p http://tetsuyai.hatenablog.com/entry/20111220/1324466655
dbrp、uniprotのapiをつかってpythonでデータ取得
自分用メモ ちょっと修正
dbrp_data_get.py
import json import os.path import sys import requests # 引数に指定したゲノム情報のアクセッション番号を検索し、accessibilityAPIの値からfastaファイルを取得するスクリプト。 # python dbrp_get.py [input_list] def main(): args = sys.argv file_name = args[1] print(file_name) url = 'https://www.nite.go.jp/nbrc/dbrp/api/dataget' data_format = '.zip' params = {'data_id': file_name} response = requests.get(url, params=params) dict = response.json() data_body_str = dict['result']['data_body'] data_body = json.loads(data_body_str) accessibility_api = data_body['@graph'][0]['DataDownload']['accessibilityAPI'] url2 = 'https://www.nite.go.jp/nbrc/dbrp/api/fileget' params2 = {'file_id': accessibility_api} download_data = requests.get(url2, params=params2) if not os.path.exists('./data/dbrp/'): os.makedirs('./data/dbrp/') with open('./data/dbrp/' + file_name + data_format, 'wb') as f: f.write(download_data.content) print("finish!") if __name__ == '__main__': main()
uniprot_data_get.py
import requests import os.path import sys def main(): # 引数に指定したアクセッション番号のリストを指定し、uniprotのAPIでデータを取得するスクリプト。 # python uniprot_data_get.py [input_list] args = sys.argv list_name = args[1] base_url = 'https://www.uniprot.org/uniprot/' format = '.fasta' list = open(list_name, 'r') if not os.path.exists('./data/uniprot/'): os.makedirs('./data/uniprot/') lines = list.readlines() for line in lines: print(line) accession_id = line.rstrip('\n') url = base_url + accession_id + format response = requests.get(url) with open('./data/uniprot/' + accession_id + format, 'wb') as f: f.write(response.content) print("finish!") if __name__ == '__main__': main()
NCBIのE-utilsについて簡単にまとめてみた。
仕事でNCBIのデータをAPIで取得して、もろもろ作業したので、備忘のためにメモ。
その前に簡単にE-utilsについて説明を。
●E-utilsとは?
NCBIのEntrezデータベースからデータを利用するためのAPIのことです。
NCBIではgenomeやenzyme、論文等の情報が利用できますが、それらを取得するためのAPIとしてE-utilsというサービスが公開されています。
●E-utils使い方
以下のような形式のurlをcurlやブラウザで検索することでNCBIの各種データを取得できます。
サンプル:
https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&term=science[journal]+AND+breast+cancer+AND+2008[pdat]
・EInfo (database statistics)
指定したDBの各フィールドのレコード数、DBの最新アップデート日付、他のEntrez DBへのリンクを取得できる。
サンプル:
https://eutils.ncbi.nlm.nih.gov/entrez/eutils/einfo.fcgi?db=protein
・ESearch (text searches)
指定したDBにキーワード検索をかけ、対象のIDリストが取得できる。後述のESummary, EFetch, ELink等でそのIDが使える。
サンプル:
https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&term=science[journal]+AND+breast+cancer+AND+2008[pdat]&usehistory=y
・ESummary (document summary downloads)
指定したDBにIDで検索をかけ、対象の情報のサマリを取得する。ブラウザの検索ページの検索結果表示画面の情報に相当する。
サンプル:
https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=protein&id=6678417,9507199,28558982,28558984,28558988,28558990
・EFetch (data record downloads)
指定したDBにIDで検索をかけ、対象の全情報を取得する。
サンプル:
https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=nuccore&id=34577062,24475906&rettype=fasta&retmode=text
・EGQuery (global query)
それぞれのEntrez DBへキーワード検索をかけ、DBごとのヒットした結果の件数が取得できる。
サンプル:
https://eutils.ncbi.nlm.nih.gov/entrez/eutils/egquery.fcgi?term=mouse[orgn]
・ELink (Entrez links)
検索したIDと関連のあるENtrezデータベースのIDリストを取得する。
サンプル:
https://eutils.ncbi.nlm.nih.gov/entrez/eutils/elink.fcgi?dbfrom=nuccore&db=gene&id=34577062,24475906
・EPost (UID uploads)
IDをアップロードするAPI。アップロードされたIDリストは後の工程で利用できる。リクエストを分割したい時などに。
サンプル:
https://eutils.ncbi.nlm.nih.gov/entrez/eutils/epost.fcgi?db=gene&id=7173,22018,54314,403521,525013
・ESpell (spelling suggestions)
検索キーワードに対して指定したDBから類似したのキーワードを提案してくれる。
サンプル:
https://eutils.ncbi.nlm.nih.gov/entrez/eutils/espell.fcgi?term=fiberblast+cell+grwth&db=pmc
・ECitMatch (batch citation searching in PubMed)
ジャーナル名や著者名、出版年等からpubmed IDリストを取得できる。
サンプル:
https://eutils.ncbi.nlm.nih.gov/entrez/eutils/ecitmatch.cgi?db=pubmed&retmode=xml& bdata=proc+natl+acad+sci+u+s+a|1991|88|3248|mann+bj|Art1|%0Dscience|1987|235|182|palmenberg+ac|Art2|
bdata のフォーマット:
journal_title|year|volume|first_page|author_name|your_key|
●パラメータについて
上記例で出てきたパラメータについて簡単に説明。詳しくは公式ドキュメントで。
db={database}
nuccore, pubmed, proteinなど検索するDBを指定。
term={query}
検索キーワードを指定。
id={uid_list}
IDのリストを指定。
rettype={retrieval_type}
データを取得する際の形式を指定。xml, fasta, gbなど。
retmode={retrieval_mode}
データを取得するファイルの形式を指定。text, xml, htmlなど。
参考:
分からないところは公式ドキュメントのドキュメント内検索でだいたいどうにかなる。
E-utilities Quick Start - Entrez Programming Utilities Help - NCBI Bookshelf
あとこのスライドがすごい分かりやすい。
E-Utilities
Pythonではじめる機械学習で機械学習を学習してみた ~~第2章②~~
・ニューラルネットワーク
from sklearn.neural_network import MLPClassifier #散布図と決定境界の描画 mlp = MLPClassifier(solver='lbfgs', activation='tanh', max_iter=200, random_state=0, hidden_layer_sizes=[10, 10], alpha=0.1).fit(X_train, y_train) mglearn.plots.plot_2d_separator(mlp, X_train, fill=True, alpha=.3) mglearn.discrete_scatter(X_train[:, 0], X_train[:, 1], y_train) #評価、予測 print(mlp.score(X_train, y_train)) print(mlp.score(X_test, y_test)) print(mlp.predict(Xtest))
参考:
10分でわかる深層学習のニューラルネットワーク - Qiita
・MLPClassifier()の引数について
solver : パラメータ学習アルゴリズム
activation : 活性化関数、デフォルトではrelu
hidden_layer_sizes : 隠れユニットの配列、配列の数が隠れ層の数となる。
alpha : 正則化(l2)パラメータ
max_iter : 学習繰り返し回数
・活性化関数について
pynote.hatenablog.com
・データ前処理
SVCと同様特徴量のサイズが異なる場合、同じくらいのスケールとなるようにそれぞれスケール変換する。
・solverについて
'adam'(Adaptive moment estimation):
期待値計算に指数移動平均を使う現在最も評価されている手法。
過去の学習によって更新されてこなかったパラメータを優先的に更新するようなアルゴリズムになっている。
'lbfgs'(limited memory BFGS):
準ニュートン法を省メモリにて実現した手法。
1000以下の小さいデータセットの場合に高パフォーマンスで、高速にトレーニングが可能。
'sgd'(Stochastic Gradient Descent : 確率的勾配降下法):
訓練データをランダムにシャッフルし、重みを更新する。
この手法は確率的に局所解にはまりにくくなるという長所や、オンライン学習で使いやすいという長所を持っている。
参考:
ニューラルネットワークのパラメータ設定方法(scikit-learnのMLPClassifier) | SPJ
・クラス分類器の不確実性推定、確率の予測
decision_function()メソッドを使うことで、クラス分類の振り分けを正負の値で表すことができる。scikit-learnのクラス分類器ほとんどがこれを有している。
クラス分類の確率の予測にはpredict_prob()が使われる。
gbrt = GradientBoostingClassifier(random_state=0) gbrt.fit(X_train, y_train_named) print(gbrt.decision_function(X_test)) print(gbrt.predict_prob(X_test))
・pd.astype(...)
カッコ内のデータ型にキャストするメソッド。
参考:
pandasのデータ型dtype一覧とastypeによる変換(キャスト) | note.nkmk.me
・np.argmax()
配列の最大値のインデックスを取得。
第二章完了。長かった。。なんとなく機械学習の特徴をつかめてきた気もするが、座学だけでは実感がわかない。
勉強と並行して実際に機械学習を実装しようと思う。
Pythonではじめる機械学習で機械学習を学習してみた ~~第2章①~~
2週間くらいで一通り学習終わるだろと思っていたが、二章だけで2週間以上かかっている。がんばってペース上げたい。
・mglearn.discrete_scatter(X[:, 0], X[:, 1], y_train) #x値、y値、label
ndarray[a, b] で普通の2次配列のlリスト list[a][b]と同じような意味。
・plt.legend(["Class 0", "Class 1"], loc=4)
凡例。loc=1~4で表示する四隅を指定
参考:
Python - mglearnにおけるdiscrete_scatterとlegendについて|teratail
・{n: v for n, v in zip(cancer.target_names, np.bincount(cancer.target))}
内包表記。整理するとこんな感じ
(n: v) for (n, v) in ...
・zip(...)
複数のリストやタプルなどをまとめる関数。多い分の要素が無視される。
参考:
Python, zip関数の使い方: 複数のリストの要素をまとめて取得 | note.nkmk.me
・np.bincount(array)
要素内の最頻値を求める。今回は"malignant" が0、"benign"が1のため、0と1の個数を取得している。
参考:
numpyでarrayの要素内の最頻値を求める - Qiita
・plt.subplots(rows、cols、axes)
figをrows * colsに分割し、axesにてfigを表示する位置を決定。
本章では側だけ3つ作って、for文でfigを作成して中にいれてる。
参考:
matplotlib の figure(図) と axes(座標軸)-python | コード7区
・mglearn.plots.plot_2d_separator(classifier, X, fill=False, ax=None, eps=None, alpha=1,cm=cm2, linewidth=None, threshold=None, linestyle="solid")
指定されたn_neighborsの値とXに渡されたデータから、分類結果の境界線(決定境界)を作成するメソッド。
参考:
https://github.com/amueller/mglearn/blob/master/mglearn/plot_2d_separator.py
・k-近傍回帰
k-近傍法の回帰モデル。特徴量に連続性があるデータを対象とした近傍法。以下サンプル。
from sklearn.neighbors import KNeighborsRegressor reg = KNeighborsRegressor(n_neighbors=3) reg.fit(X_train, y_train) reg.score(X_test, y_test) reg.predict(X_test)
・線形回帰(通常最小二乗法)
予測と回帰ターゲットyとの平均二乗誤差が最小となるような線形モデルを作る。LinearRegressionクラスを用いる。
モデル式: y=w[0]*x[0] + w[1]*x[1] + ... +w[p]*x[p] + b
from sklearn.linear_model import LinearRegression lr = LinearRegression().fit(X_train, y_train) print(lr.coef_) #係数(傾き)、各特徴量に対する値が配列で格納。 print(lr.intercept_) #切片 print(lr.score(X_train, y_train)) #スコア
・リッジ回帰
係数(w)の絶対値の大きさをできるかぎり小さくし、個々の特徴量が出力に与える影響をなるべく小さくすることで過剰適合を防ぎたい線形回帰のモデル。Ridgeクラス。
from sklearn.linear_model import Ridge ridge = Ridge(alpha=1).fit(X_train, y_train) #alphaで係数への制約の強さを指定する。 print(ridge.score(X_train, y_train)) print(ridge.score(X_test, y_test))
・plt.hlines([value1, value2, ...], xmin, xmax, linestyle="dashed")
補助線を作成するメソッド。
【Python@matplotlib】matplotlib にて横、縦の補助線を描く方法について - Qiita
・plt.xlim(x1, x2) plt.ylim(y1, y2)
ある特定の範囲を見せる等、グラフの横軸、縦軸を調整するメソッド。それぞれy軸、x軸
・Lasso
リッジと同様係数の値を0に近づけるのだが、制約のかけ方が異なる。L1正則化。(リッジ回帰はL2正則化)
いくつかn係数が完全に0になる。
from sklearn.linear_model import Lasso lasso001= Lasso(alpha=0.01, max_iter=100000).fit(X_train, y_train) print(lasso001.score(X_train, y_train)) print(lasso001.score(X_test, y_test))
・ロジスティック回帰
予測モデルをシグモイド関数を使って作成するクラス分類アルゴリズム
from sklearn.linear_model import LogisticRegression logreg100 = LogisticRegression(C=1, penalty="l2").fit(X_train, y_train) #C:正則化パラメータ, penalty="l2" print(logreg100.score(X_train, y_train)) print(logreg100.score(X_test, y_test))
参考:
やる夫で学ぶ機械学習 - ロジスティック回帰 - · けんごのお屋敷
・線形サポートベクターマシン
サポートベクタマシン(SVM)を使った線形クラス分類アルゴリズム。
SVMとは各クラスのデータ集合が決定境界からどの程度離れているかを分類の良さの基準として、訓練データからモデルを作成する手法。
from sklearn.svm import LinearSVC linear_svc = LinearSVC(penalty='l2', loss='squared_hinge', dual=True, tol=1e-4, C=1.0).fit(X, y) linear_svc = LinearSVC().score(X_test, y_test)
参考:
線形SVM - Qiita
・ナイーブベイズ
線形モデルより高速。汎化性能は他線形モデルより劣る。
GuassianNB:任意の連続値データ
BernoulliNB:2値データ
MultinomialNB:カウントデータ
参考:
ナイーブベイズについて勉強したのでざっくりまとめ | DevelopersIO
・決定木
DecisionTreeClassifierを使った決定木
from sklearn.tree import DecisionTreeClassifier from sklearn.tree import export_graphviz import graphviz tree = DecisionTreeClassifier(max_depth=4, random_state=0) #max_depthで指定した階層で分岐を止める。 tree.fit(X_train, y_train) print(tree.score(X_train, y_train)) print(tree.score(X_test, y_test)) export_graphviz(tree, out_file="tree.dot", class_names=["malignant", "benign"], feature_names=cancer.feature_names, impurity=False, filled=True) #可視化 with open("tree.dot") as f: dot_graph = f.read() graphviz.Source(dot_graph) print(tree.feature_importances_) #特徴量の重要度 tree.predict(X)
mglearn.plots.plot_animal_tree()と打つとimport graphvizでエラー。モジュールないとのこと。
conda list python-graphvizで調べるとモジュールが入ってなかったのでインストールするも解消されない。
python-graphvizがあるところにパスを通して無事解決。
以下サイトを参考:
Graphvizパッケージのエラーの対処法(Windows) - The Cinema, Actually
・ランダムフォレスト
異なった方向に過剰適合した決定木をたくさんつくり、結果を平均する感じ。
決定木建築課程で乱数を導入し、差異を導入。
from sklearn.ensemble import RandomForestClassifier forest = RandomForestClassifier(n_estimators=5, random_state=2) #n_estimators 決定木の本数 forest.fit(X_train, y_train) print(forest.score(X_train, y_train)) print(forest.score(X_test, y_test)) print(forest.prediect(X_test))
・勾配ブースティングマシン
複数の決定木を順番に作っていき、ひとつ前の決定木の誤りを次の木が修正していく手法。
gbrt = GradientBoostingClassifier(n_estimators=100, random_state=0, max_depth=3, learning_rate=0.1) #max_depth 最大の枝の数 #learning_rate 学習率 #n_estimatorsデフォルトで100 gbrt.fit(X_train, y_train) print(gbrt.score(X_train, y_train)) print(gbrt.score(X_test, y_test))
・カーネル法を用いたサポートベクターマシン
平面だけでなく、より複雑なモデルを可能とするため線形SVMを拡張したもの。
・LinearSVCの特徴量を追加(z軸)して決定境界を作成
X_new = np.hstack([X, X[:, 1:] ** 2]) #3つ目の特徴量 X[:1]^2 を追加 from mpl_toolkits.mplot3d import Axes3D, axes3d figure = plt.figure() ax = Axes3D(figure, elev=-152, azim=-26) #elev:z軸方向から見た仰角 #azim:x, y軸方向の方位角 linear_svm_3d = LinearSVC().fit(X_new, y) coef, intercept = linear_svm_3d.coef_.ravel(), linear_svm_3d.intercept_ xx = np.linspace(X_new[:, 0].min() - 2, X_new[:, 0].max() + 2, 50) yy = np.linspace(X_new[:, 1].min() - 2, X_new[:, 1].max() + 2, 50) XX, YY = np.meshgrid(xx, yy) #x,yの格子点を作成 ZZ = (coef[0] * XX + coef[1] * YY + intercept) / -coef[2] ax.plot_surface(XX, YY, ZZ, rstride=8, cstride=8, alpha=0.3) mask = y == 0 ax.scatter(X_new[mask, 0], X_new[mask, 1], X_new[mask, 2], c= 'b', cmap=mglearn.cm2, s=60) ax.scatter(X_new[~mask, 0], X_new[~mask, 1], X_new[~mask, 2], c='r', marker='^', cmap=mglearn.cm2, s=60) #[~mask] の~はビット反転子
・np.hstack(tup)
水平方向にタプルを結合。
参考:
配列同士を連結する、NumPyのvstackとhstack関数の使い方 - DeepAge
・カーネルトリックを使ったSVM
個々のデータポイントが、2つのクラスの決定境界を表現するのにどの程度重要かを学習する。
多くは境界線付近のデータポイントが決定境界を決定する。これらのデータポイントをサポートベクタと呼ぶ。
from sklearn.svm import SVC #C 正則化パラメータ #gamma ガウネシアンカーネルの幅(データポイントの距離が遠いと判定された場合サポートベクタになるってことだと思う) svm = SVC(kernel='rbf', C=10, gamma=0.1).fit(X, y) mglearn.plots.plot_2d_separator(svm, X, eps=.5) mglearn.discrete_scatter(X[:, 0], X[:, 1], y) sv = svm.support_vectors_ #サポートベクタ sv_labels = svm.dual_coef_.ravel() > 0 mglearn.discrete_scatter(sv[:, 0], sv[:, 1], sv_labels, s=15, markeredgewidth=3) #サポートベクタを描画 print(svm.score(X_test, y_test)) print(svm.predict(X_test))
・svmのためのデータ前処理
特徴量が桁違いにサイズが異なる場合、だいたい同じスケールとなるようにそれぞれスケール変換する。
・MinMaxScalar すべての特徴量を0-1の間となるよう変換
第二章は量が多いので分割。。