sutefunaのブログ

juliaと機械学習を勉強中

juliaで最小二乗法を解く

ファイルの読み込みに少し悪戦苦闘しつつも最小二乗法が完成した。

次のようなファイルデータから最小二乗法で線形回帰を行う。

x y
5.6 30
5.8 26
6.0 33
6.2 31
6.4 33
6.4 35
6.4 37
6.6 36
6.8 33

y = ax + b
として、一番いいabを求める。

i番目のデータをx_i, y_iとしたときの次のJを最小化するabを求める。
\[
J=\frac{1}{2}\sum_{i=1}^n(y_i - (ax_i+b))^2
\]
それぞれ偏微分すると次のようになる。
\[
\begin{cases}
\frac{\partial J}{\partial a} = \sum_{i=1}^n(y_i - (ax_i+b))(-x_i) \\
\frac{\partial J}{\partial b} = \sum_{i=1}^n(y_i - (ax_i+b))(-1)
\end{cases}
\]
これらを0とおいて整理すると次のようになるから、左から逆行列を掛ければ解ける。
\[
\left(
\begin{array}{cc}
\sum_{i=1}^nx_i^2 & \sum_{i=i}^nx_i \\
\sum_{i=1}^nx_i & n \\
\end{array}
\right)
\left(
\begin{array}{cc}
a \\
b \\
\end{array}
\right) =
\left(
\begin{array}{cc}
\sum_{i=1}^nx_iy_i \\
\sum_{i=1}^ny_i \\
\end{array}
\right)
\]

io = open("data.txt", "r")
n = countlines(io) #サンプル数
data = zeros(Float64, n, 2) # n*2行列

seekstart(io)
for i = 1:n
    line = split(readline(io))
    data[i, 1] = parse(Float64, line[1])
    data[i, 2] = parse(Float64, line[2])
end

x = data[:,1]
y = data[:,2]
X = sum(x) # Σxi
Y = sum(y) # Σyi
X2 = x'x # Σ(xi^2)
XY = x'y # Σxiyi

A = [X2 X; X n]
B = [XY; Y]

print(A\B) # A^-1 * B = [6.03383, -5.01128]

本当に1からjuliaを触っているのでしょうもないことで時間が取られてる印象。
次は多変量。