データサイエンスと生命科学

医学・生命科学分野のデータ解析手法の研究と、数理・データサイエンス的なアプローチを用いた老化・寿命のメカニズム解明のための研究をしています。このブログでは、主に、データサイエンスや生命科学に関する解説記事などを発信します。

ニュートン法を使って方程式を解く[R][データサイエンス]

ニュートン法とは、実数値関数の根を数値的に計算する代表的なアルゴリズムです。

実数値関数の根を求めるとは、例えば以下のような方程式の解を求めることです。

$$ x^{3} + x - 8 = 0 $$

関数の根とは、f(x) = 0になるxの値のことです。たとえば、中学校の数学の方程式の授業では、x2 - 4 = 0を解け、というような問題が出ます。答えは、x = 2またはx = -2のときです。これらの点が、関数f(x) = x2 - 4の根になります。

方程式の解き方には、解析的に解くやり方と数値的に解くやり方があります。解析的に解く方法は、数式をきちんと立て、その数式を変形して正確な解を示すことです。たとえば、関数f(x) = x2 - 4の場合、式変形によって正確な解を求めることができるので、解析的な計算ができます。中学校や高校で習う方程式の計算は、基本的には全てこの解析的な解を求めています。でも、方程式が複雑な場合は、解析的に解くことが難しい場合もあります。

数値的に解くとは、方程式の解を具体的な数字として計算機を使って力づくで答えを導き出す方法です。例えば、いろいろな値をxに代入してみて、しらみつぶしに探す、というのは最もシンプルな数値的な解き方ですが、効率が悪いです。そのため、情報科学では、効率的に計算するためのアルゴリズムが研究されており、ニュートン法はその1つです。数値的に解くときには、演算回数が少なく精度がよいことなどが望ましいです。

ニュートン法では、初めに適当な推測値からスタートして、より正確な解の近似値を探索します。 反復を繰り返すことにより、正解に非常に近い値を得ることができます。

例として、以下の3次方程式の解をニュートン法を使ってどのように解くか考えてみましょう。

$$ x^{3} + x - 8 = 0 $$

この関数 (f(x) = x3 + x - 8)をRで視覚化してみると、方程式の解であるf(x) =0となるxは2の周辺にあるように見えます。

#Rでf(x)を描画してみる
x <- seq(-3, 3, length=100)
fx <- x^3 + x - 8
plot(x, fx, type="l")
abline(h=0,col="red")

f(x) = x3 + x - 8を描画した図。赤線はf(x) = 0を表す。交点のx座標の値から、f(x)=0を満たすxの値は2の近くであることがわかる。

ニュートン法は必ず解が求める保証はありませんが(その条件は複雑)、真の解に近い初期値を使えば多くの場合収束します。上の描画より、初期値x_0を2としてニュートン法を使って解を探します。

初期値が決まったら、反復プロセスを使用してより良い正確な値を計算していきます。 ニュートン法では、$x_n$が現在の暫定解である場合、次の暫定解$x_{n+1}$は以下の式によって与えられます。

$$ x_{n+1} = x_n - \frac{f(x_n)}{f'(x_n)} $$

f'(x)は、対象となる関数を微分して得られた導関数で、以下のように求められます。

$$ f(x) = x^{3} + x - 8 \\ f'(x) = 3x^{2} + 1 \\ $$

現在、初期値x_0=2が与えれれているので、上の式を使ってx_1が計算できます。

$$ x_{1} = x_0 - \frac{f(x_0)}{f'(x_0)} $$

同様に、x_2は

$$ x_{2} = x_1- \frac{f(x_1)}{f'(x_1)} $$

です。

これを繰り返していくと、どんどん真の解に近づいていく、ということです。 そのため、初期値x_0, f(x) , f'(x)がきまれば、コンピューターで計算を繰り返していけば解を探索できます。 本当にできるか、実際にRでやってみます。

f <- function(x){x^3 + x - 8}
fd <- function(x){3 * x^2 + 1} #f'(x)
n_iter <- 10
xn <- 2 #初期値x_0を設定する
xn_hist <- NULL
for(i in 1:n_iter){
    xn_hist <- c(xn_hist, xn)
    xn <- xn - (f(xn)/fd(xn))
}
plot(xn_hist, xlab="n", ylab="x_n", cex.lab=2)

x_nの値の変化。x_0は初期値の2であるが、nが増えていくごとに一定の値に収束していく。

x_nのnの値が大きくなるごとに、一定の値に収束していきます。 10回反復すると、x_10の値は1.833751になっていました。 この時のf(x)はゼロになっていることも以下のようなコマンドで確かめられます。

#Solution
cat("x_n: ", xn, "\n")
cat("f(x): ", f(xn))

以上より、方程式x3 + x - 8 = 0の解は、x = 1.833751と計算できました。

DockerとRでmethylclock packageをインストール

RでBioconductorのmethylclockを使いたい。

www.bioconductor.org

まず、Docker上で最新版のR環境を構築。

hub.docker.com

 

 

docker run -it --name "methylclock" r-base /bin/bash

R

 

 

でRを起動する。

しかし、ここでいきなりインストールしようとしても、足りないパッケージが多くてうまくいかない。そこでまず、以下をインストールする。

apt install libxml2-dev

apt install libcurl4-openssl-dev

apt install cmake

apt install libssl-dev

apt install libfontconfig1-dev

apt install libharfbuzz-dev libfribidi-dev

apt install libfreetype6-dev libpng-dev libtiff5-dev libjpeg-dev

 

そのあと、R上で以下コマンドでインストールできる。

if (!require("BiocManager", quietly = TRUE))
    install.packages("BiocManager")

BiocManager::install("methylclock")

R3.6にscDDパッケージをインストール

R3.6に、BioconductorのscDDパッケージをインストールすると詰まったのでメモ。

こんなエラーがでる。

In file included from annoy.cpp:1:0:
annoy.h:33:63: error: wrong number of template arguments (4, should be 5)
typedef AnnoyIndex<Index_t, Data_t, Distance, Kiss64Random> _index;
^
In file included from annoy.h:17:0,
from annoy.cpp:1:

 

解決策としては、RcppAnnoyのバージョンを最新版の0.0.18ではなく、0.0.16をインストールすること。ここが参考になった。

 

github.com

arXiv備忘録

arxivに原稿を投稿する際、ハマった所をメモ。

・article classを使う際には、先頭に%&articleを付加する。

・ファイル名にアンダーバーを含むとエラー

pngなども使えるがエラーになったりする。epsだけで統一するとなおった。

任意のサイズで画像切り出し

まずはpictcutterで画像をトリミング。

http://hp.vector.co.jp/authors/VA020302/html/dev_pc/index.html

縮尺だけ併せて、いったん保存。

次に、GIMPでそれを取り込んで任意の30mm by 60mmなどで縮小、拡大する。

epsも含む色々な形式で書き出し可能。