まさなみブログ

主にweb系開発の記事を適当に書いてます。

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]

・urlの形式

https://eutils.ncbi.nlm.nih.gov/entrez/eutils/{API名}.fcgi?{各パラメータ}


●各APIについて

・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

パラメータについて
The E-utilities In-Depth: Parameters, Syntax and More - Entrez Programming Utilities Help - NCBI Bookshelf

あとこのスライドがすごい分かりやすい。
E-Utilities

Pythonではじめる機械学習で機械学習を学習してみた  ~~第2章②~~


ニューラルネットワーク

・多層パーセプトロン(MLP)

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の間となるよう変換


第二章は量が多いので分割。。

Pythonではじめる機械学習で機械学習を学習してみた  ~~第1章~~

・疎行列、CRS形式とは?

疎行列とは要素のほとんどが0の行列のこと。機械学習をしていると、疎行列が頻出するだとかなんとか。
0ばかりで埋め尽くされたデータでメモリを食われるのはもったいないよねってことで、
0以外の要素が入っているところをピックアップして表示する形式のうちの一つがCRS形式。他にもCOO形式などがあるらしい。詳しくは下記参照。
www.jicfus.jp

・sparse.csr_matrix(array)
NumPyの2次元配列を疎行列のCSR形式に変換。


・numpy.linspace(start, stop, num = 50, endpoint = True, retstep = False, dtype = None)
returns: ndarray
等差数列を作成する関数。numは配列の要素数


・IPython.display.display(data)
from IPython import display
上記import文でdisplay(data)を使用すると以下のエラーが発生。
TypeError: 'module' object is not callable

調べてみると、display関数はIPython.displayモジュールのdisplay関数らしい。import文を下記に修正して解決。
from IPython.display import display


・pandas.DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)
二次元配列のクラス。表形式でindex、column等を指定できる。
deepage.net


・string[n-1:n'-1]
stringのn文字目~n'文字目までを取得。[-1]で一番後ろの文字。
Python文字列操作マスター - Qiita


・NumPy.array.shape
配列の要素数を表す関数。reshape(n,n')で配列の再編成。

IN:
array = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
print(ary.shape)
print(array.reshape(6,2))

OUT:
(4, 3)
array([[ 1,  2],
       [ 3,  4],
       [ 5,  6],
       [ 7,  8],
       [ 9, 10],
       [11, 12]])

deepage.net


・train_test_split(arrays*, options**)
return: X_train, X_test, Y_train, Y_test***
学習データとテストデータをランダムに分ける関数。
*arraysには同じ配列長の複数のarrayを指定可能
**今回はrandom_state=0 を指定
***指定配列2個の場合
newtechnologylifestyle.net


・pandas.plotting.scatter_matrix(...)
pandas.pydata.org

・k-最近傍法

 特徴が最も近い訓練データを訓練セットから探し、データを予測する方法。
KNeighborsClassifierクラスを使用。以下サンプル。

knn = KNeighborsClassifier(n_neighbors=1) #近傍点を1としたクラスを作成。
knn.fit(X_train, y_train) #訓練データをセット
print(knn.score(X_test, y_test)) #テストデータを使ってモデルの評価
knn.predict(X_new) #モデルを使って実データを予測

qiita.com

Pythonではじめる機械学習で機械学習を学習してみた  ~~第0章~~

機械学習に触れるきっかけ

 職場で機械学習を始めよう!!みたいな動きがあって、社内の勉強会に参加する機会がたびたびあり、参加してみたところ結構おもしろそうだったので勉強することにしました。
 タイトルにもある以下の本を入門書として勉強を始めることにしました。
Pythonではじめる機械学習 中田秀基著 

 とりあえずこのブログでは学習にあたり、つまったところや調べもののリファレンス替わりにできればいいなと思います。ほぼ自分用。随時更新します。

■事前知識

 ちなみに、現在の私の機械学習についての知識についてですが、以下に挙げる本を読みました。それ以上の知識はございません。
人口知能は人間を超えられるか 松尾豊著

いちばんやさしい機械学習プロジェクトの教本 韮原祐介著

どちらも一般向けで機械学習の現状や実用化について分かりやすく書かれておりおすすめです。
ちなみにpythonは未学習だったため、以下の本で1か月ほど勉強しました。多分基礎はできているかと思います。
・ゲームを作りながら楽しく学べるPythonプログラミング 田中家日郎著
amazon kindleで無料のわりに分かりやすく、サンプルコードもついている良本です。
 

■環境

Windows 10 64bit
Python 3.7.1
Anaconda 2018.12

■インストール編

 開発環境にはAnaconda を使用。pythonの勉強でpygameのライブラリが使えていたので、インストールされてるほかのやつも問題なく使えるだろうと思っていたがNumPyのimportでさっそくこんな感じのエラーが出た。

Traceback (most recent call last):
File "C:/Users/{hoge}/dev/workdir/AI_study/test.py", line 1, in <module>
import numpy as np
File "C:\Users\{hoge}\Anaconda3\envs\defenv\lib\site-packages\numpy\__init__.py", line 140, in <module>
from . import _distributor_init
File "C:\Users\{hoge}\Anaconda3\envs\defenv\lib\site-packages\numpy\_distributor_init.py", line 34, in <module>
from . import _mklinit
ImportError: DLL load failed: 指定されたモジュールが見つかりません。

Process finished with exit code 1

上記はvsCodeで書いたコードを実行した際に生じたエラー。anaconda promptで同様のコードを実行すると問題なくうまくいった。
色々調べたところ、原因はNumpyにpathが通っていないことでした。Anaconda導入時にC:\Users\{hoge}\Anaconda3\Library\binにpathを通していなかった。
note.nkmk.me
上記サイトを参考に、sys.path.append(... を使ってモジュールへのpathを通したがなぜかうまくいかない。。。

しょうがないので環境変数にpathを追加しました。現状仮想環境の使い分けをする必要も特にないので、とりあえずこのまま進めます。
うーん、後でまたこの問題と直面するんだろうなあ。いったん解決。

 次回から本格的に学習に入っていきます。(たぶん…)