質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Mathematica

Mathematicaは、ウルフラム・リサーチによって開発されている数式処理システムです。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Q&A

解決済

5回答

1928閲覧

最小二乗法のような複数の座標から二次関数を求める方法はありますか?

John-Doe.7

総合スコア13

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Mathematica

Mathematicaは、ウルフラム・リサーチによって開発されている数式処理システムです。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

0グッド

1クリップ

投稿2018/08/23 08:15

編集2018/08/27 17:43

最小二乗法のような複数の座標から二次関数を求める方法はありますか?
積分は得意なんですが、微分はイマイチでして、微分などを使わないで複数の座標から二次関数y=ax^2+bx+cを求める方法があれば教えてください!

今更で申し訳ないのですが、最小二乗法はどんな原理で近似式を求めているのですか?
例えば、すべての座標を足して、座標の数で割ると言った平均を求める方法で求めるとかでしょうか?
うまく伝わっていないかもしれませんが原理的なものが知りたいですね。
調べるとwikiは出てくるんですが、説明が難しくって私の頭では追いつきませんでした。

編集8/28
私自身でも今現在進行形で方法を考えて三角関数とかでなんとかなるんじゃないかと考えているんですが、もしよろしければ付き合っていただけないでしょうか?
ほんの気になったことなのですが、y=(X^2+3X+1)^4を微分の定義とかを使わないで傾きを求められないかと考えています。もちろん、微分って傾き求めるもんなんだから定義を使わないなら求まるわけねーじゃんって思う方もいると思いますが、自分なりに探求しています。
もし、こんな方法もあるよって方がいらっしゃいましたら教えていただけると嬉しいです。
同時進行ではありますが、y=(X^2+3X+1)^4の傾きを微分の定義を使わないで解くアルゴリズムをプログラムにできないかとも考えています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

John-Doe.7

2018/08/23 09:14

できればcで作ろうと思ったのですが、やはり分析などはR言語でないとないのかもしれません。
swordone

2018/08/23 12:19

積分がOKで微分がダメってよくわからん…一般的には積分のほうが難しくないか?
John-Doe.7

2018/08/23 13:20

そうですか?微分は複雑な部分などがあるんで私には難しいですよ。
fana

2018/08/28 00:55

> 編集8/28 は当初と内容が違っているように見えるので,別の質問にでもした方が良いようにも思いますが…… "数値微分"は「微分の定義」に抵触する感じですか?
John-Doe.7

2018/08/28 07:48

そうします!>>数値微分"は「微分の定義」に抵触する感じですか? そうかもしれません。
guest

回答5

0

こんにちは。

最小二乗法はn次多項式でも使えますよ。

投稿2018/08/23 08:25

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

John-Doe.7

2018/08/23 09:06

!? あれ、ちなみに微分は使わなくても最小二乗法でn次多項式って導けましたっけ...。 サイトで検索してみたのですが、イマイチうまく説明しているものがなく困っていました。
Chironian

2018/08/23 11:47 編集

最小二乗法は微分値が0になる点を探すので無理ですね。 最小二乗法は使われているのだと理解していまいました。 捉え損なったようで申し訳ないです。
fana

2018/08/23 12:21

言葉の定義としては,「最小二乗法」とは「SSDを評価値としてそれを最小にするパラメタを求める」ということだと思うので,実際に用いる解法が微分を必要とするか否かは別の話ではないでしょうか.
Chironian

2018/08/23 12:39

「最小二乗法」は評価値が最小となる点として微分値=0となる点を求める手法として理解しています。 もし微分を使わない「最小二乗法」をご存知であればそれをご提示されると、John-Doe.7さんの質問への的確な回答になると思いますよ。
fana

2018/08/24 00:45 編集

最小二乗評価関数のみ(の実装)さえあれば,その導関数(の実装)が不要な解法に関しては既に回答しているつもりです. 最小二乗評価関数の各パラメタでの偏微分=0 なる連立方程式を解くのは一つの解法でしょうが,そういうアプローチでは方法次第でHessianまで導出する必要があったりして,関数の形が複雑な場合には導出がつらい.そういう場合,「最小二乗評価関数値がより小さくなる箇所を探し続ける」というシンプルなアプローチを採用すると楽なことがあります. (まぁ今回の例は線型なので,「微分がつらい」とはなりにくいと思うのですが,つらさは人次第ですし,実際につらい模様.)
fana

2018/08/24 00:48

平たく言うと, argmin 最小二乗評価関数(パラメタ) という定式化のことを「最小二乗法」と呼ぶのではないか,ということで,その後でこれをどう解くかについては自由なんじゃないかな,と. 微分がつらいなら,微分を要しない方法を探してきて使えばよいのではないかと.
Chironian

2018/08/24 02:54

「最小二乗法」という言葉の定義の問題ということですが、恐らく最小二乗法を理解している多くの人は微分値=0を使って連立方程式へ落とし込む部分まで含めて「最小二乗法」と理解していると思います。(1次の最小二乗法は高校生のころ習ったようなおぼろげな記憶がありますし。) また、用語は必ずしも定義対象の全てを表現できているとは限らないです。短い言葉で表現しますからどうしても端折る部分は出てきます。従って、用語の字面に含まれていないことは定義に含まないという結論にはなりません。 更に、目標からの乖離度を数値化してそれを最小にする点を求めるという広い意味の場合、別に二乗に限定する必要はないように思います。最小値が存在すれば良いので絶対値やその他の評価値でも良いのに何故に二乗に限定しているのか?と考えると微分して連立方程式へ落とし込むことまで含んでいるからではないかと感じます。 ですので、fanaさんの主張通りのそれなりに多くの人が支持する定義の存在を提示されない限り、私はfanaさんの主張に賛成することはできそうにないです。
fana

2018/08/24 03:20

ああ,すみません.言葉の定義がどこまで含むのか,という話に特別強い主張をしたいわけではなかったのです. 「机上での微分ができない = (私が思っている意味での)最小二乗法を使えない」みたいな認識になっちゃいそうに見えたので… 言い直せば,(既に別の回答箇所に書いているように)「微分を用いた数式導出をしたくなくても,最小二乗評価関数を導出することろまではOKなのであれば,それ相応の方法があるよ」という感じになりますかね. > 何故に二乗 …をよく使う(というか,話として出てくる)のか,については, 2乗値というのが,絶対値と同様に差分量の正負を区別なく扱えることと,外れ値に対する敏感性が絶対値よりも強くて(これが利点かどうかはその時々ですが),且つおっしゃるように微分可能で,わかりやすい関数だということではないでしょうか. (その意味では別に4乗とかでもいいけど,それだと名前が「最小四乗法」とかになるのかな) > 別に二乗に限定する必要はない おっしゃる通りです.(特に誰も限定していないと思いますが…) 実際の問題に対しては,外れ値に敏感すぎる原始的な最小二乗法をそのまま使うなんてことは稀で,別の形の評価関数を使う(M推定とか呼ぶんでしたっけ?)等することが多いですよね.
fana

2018/08/24 03:36

おそれ多くもChironian様の話を補足させていただくと, 線形な関数に関する最小二乗法を用いる場合はSVDを使うでしょうから >微分値=0を使って連立方程式へ落とし込む ところまでが一般に必要な作業と言えると思います.
Chironian

2018/08/24 03:56

議論がすれ違っているようですね。「言葉の定義としては,「最小二乗法」とは(後略)」というご指摘でしたので、てっきり用語上のご指摘と思っていました。 微分を使わないとJohn-Doe.7さんの問題が解けないということはないと思います。ただ、その解法を私は提案できないだけです。
John-Doe.7

2018/08/27 08:58

返信遅くなりすいません。私事で遅くなりました。 こんなハイレベルなお話が聞けてほんと感激です。お金を払ってもいいくらいです。 じっくり読ませていただきます。fanaさん、chironianさん、どうもありがとうございます。
guest

0

ベストアンサー

別回答のコメントで書いたやつ:

すぐ思いつく「最小二乗じゃない簡単な手段」としては,「適当な3点を選んで2次関数の係数を解いて,他の点群を用いてその結果を評価する」ことを何度も行って一番マシなやつを選ぶとか…… (これでもRANSACと呼べるのかな?)

をとても原始的に実装してみました.(下記コードはC++ですけど,やってることの意味がわかればCでも書けるかと)
データや必要精度次第ですが,とっかかりのCoarseな係数値くらいはこんな雑な方法でも求まるでしょう.
(下記コードでは,3点から係数{a,b,c}を求む処理にはOpenCVのcv::solve()を使いましたが,ここは適当な連立方程式を解く処理を入れればよいです)

  • 3点を選ぶ際に,互いにある程度離れた組合せを選ぶようにする
  • 評価の際にも,3点から一定以上離れたデータ点群だけを用いるようにする

等の工夫を入れれば,結果がマシになる率が高まるかと思います.

//2次関数 y=F(x; a,b,c) = a*x*x + b*x + c inline double F( double x, double a, double b, double c ) { return (a*x + b )*x + c; } //main int main(void) { //乱数用 std::random_device seed_gen; std::mt19937 MT(seed_gen()); //てきとーに乱数でデータ点群を用意 const int N = 50; //データ点個数 double X[N], Y[N]; //データ点座標 { //正解の係数 const double TrueA = 0.5; const double TrueB = 4.0; const double TrueC = 3.33; //PI const double PI = acos( -1.0 ); //誤差量Max const double MaxErr = 5; // std::uniform_real_distribution<double> Dist; for( int i=0; i<N; ++i ) { //正解の式上の点を求めて… X[i] = Dist(MT) * 100 - 50; Y[i] = F( X[i], TrueA,TrueB,TrueC ); //てきとーに誤差を与えてデータ点とする double ErrR = Dist(MT) * MaxErr; double ErrTheta = Dist(MT) * 2 * PI; X[i] += cos( ErrTheta ) * ErrR; Y[i] += sin( ErrTheta ) * ErrR; std::cout << X[i] << ", " << Y[i] << std::endl; } } //データ点のうち3点を選んで係数を求めることを何度も繰り返して,最も良い係数を求む double ResultA,ResultB,ResultC; //結果係数 { const double deltaTresh = 2.5; cv::Matx< double, 3,3 > A; cv::Matx< double, 3, 1 > b; cv::Matx< double, 3, 1 > x; int Indexes[N]; for( int i=0; i<N; ++i ){ Indexes[i] = i; } int CurrScore = -1; for( int i=0; i<N*3; ++i ) //てきとーな回数繰り返す { std::shuffle( Indexes, Indexes+N, MT ); //係数を解く処理を自前で書くのが面倒なのでOpenCVを使ってます for( int j=0; j<3; ++j ) { double X_ = X[ Indexes[j] ]; double Y_ = Y[ Indexes[j] ]; A( j,0 ) = X_ * X_; A( j,1 ) = X_; A( j,2 ) = 1; b( j ) = Y_; } cv::solve( A, b, x ); //残りのデータ点群を用いて係数の良さを評価 int Score = 0; for( int j=3; j<N; ++j ) { double X_ = X[ Indexes[j] ]; double Y_ = Y[ Indexes[j] ]; double delta = fabs( Y_ - F( X_, x(0),x(1),x(2) ) ); if( delta <= deltaTresh ){ ++Score; } } if( Score > CurrScore ) { CurrScore = Score; ResultA=x(0); ResultB=x(1); ResultC=x(2); } } } std::cout << ResultA << ", " << ResultB << ", " << ResultC << std::endl; // std::cin.ignore(); return 0; }

投稿2018/08/24 02:29

編集2018/08/24 02:30
fana

総合スコア11954

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2018/08/24 02:41

余談(?)ですが,関数当てはめの目的によっては,この例のように「Y座標の誤差」を評価するのではなく,「曲線からのデータ点までの距離(のようなもの)」を評価した方が良いです.(最小二乗法による直線当てはめの話とかをググればその辺の話は出てくるハズ)
John-Doe.7

2018/08/27 08:51

コードまで書いていただいてとてもうれしいです。 私には到底書けそうにないコードかもしれませんが、じっくり読ませていただきます。 どうもありがとうございます。
guest

0

最小二乗法(直線)の簡単な説明 - 高校数学の美しい物語
このリンクは直線近似の話ですが、曲線でも基本的な原理は変わりません。
要は、

  1. 直線y=ax+bを仮定する
  2. それぞれの点に対し、同じx座標を取る直線上の点とのy座標の差(いわば誤差)を求め、

その2乗の合計を計算する
0. その合計が最小になるように直線の式の係数a,bを求める

ということです。3.の「最小となる」条件に微分を利用します。
微分苦手ということですが、多項式の微分しかやらないのでやってください。

追記に対して

y=(X^2+3X+1)^4の傾きを微分の定義を使わないで解くアルゴリズム

傾きを求めたい点のx座標をaとすると、aからわずかに離れた点(a+0.01など)とのy座標との差を取り、
x座標の差で割る
例えばa=1での傾きを求めたいなら、
[{(1.01)^2+31.01+1}^4 - (1^2+31+1)^4] / 0.01
を計算する。
厳密にいうとこちらが微分係数の定義であり、数式の微分は微分の性質というか微分法の話

8/29追記

最小二乗法の3においてどうしても微分を使いたくないということならば、平方完成による手法が考えられます。

pA^2 + qB^2 + r - 2sA - 2tB + 2uAB
=p{A^2 + 2(uB - s)/p A} + qB^2 - 2tB + r
=p{A + (uB - s)/p}^2 + (Bの2次式)
以下Bについて平方完成し、2乗の中身が0になるようA,Bを決定

ただし微分に比べ計算が面倒

投稿2018/08/23 16:44

編集2018/08/28 17:33
swordone

総合スコア20669

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

John-Doe.7

2018/08/27 15:26

わかりました。簡単な微分なら理解できるので、頑張ってみます!! どうもありがとうございます。
guest

0

微分などを使わない

の意味するところがよくわかりません.
プログラムには(机上で必要な数式を導いた結果の)必要な式だけをインプリメントすれば済みますが,「その必要な式を導出する机上計算で微分などが発生するのがもう嫌!」という話なのでしょうか?

さて,単純な最小二乗法による2次関数フィッティングであれば…

  • 固有値問題の形にまで机上で求めておく形になるかと思いますが,この場合,固有値問題を解いてくれるライブラリを探す必要が発生することになるかと.
  • 上記を嫌って数値探索的に解こうとする場合,最急降下法やNewton法のような手段を用いるなら最小化対象たる目的関数の(机上での)微分作業は一般に必要ですが,これが面倒な場合には,数値微分で済ますという手もあります.
  • 探索法として勾配法的でないものを使うならば,机上での微分計算も要らなくなる可能性はあります.(例えば,Nelderらの滑降Simplex法とか)

投稿2018/08/23 10:56

編集2018/08/23 11:00
fana

総合スコア11954

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

John-Doe.7

2018/08/23 11:02

えーと、そうですね。計算過程で微分が出るだけでアレルギーがでます。
fana

2018/08/23 11:12 編集

最小化すべき関数まではアレルギー的に大丈夫ですか. ObjectiveFunc(a,b,c) = Σ{ ( ax^2 + bx + c - y )^2 } という感じですかね. この関数さえ実装できるなら,上記の滑降Simplex法とか,粒子群最適化(←ググったら出てきた)とかそういう楽しげな方法を使ってみるとか.
fana

2018/08/23 11:26 編集

すぐ思いつく「最小二乗じゃない簡単な手段」としては,「適当な3点を選んで2次関数の係数を解いて,他の点群を用いてその結果を評価する」ことを何度も行って一番マシなやつを選ぶとか…… (これでもRANSACと呼べるのかな?)
fana

2018/08/23 12:27 編集

前記のような手続きで複数個のCoarseなパラメタを得た後であれば,例えば「パラメタ空間をランダムサンプリングする」ような方法もRefinement手段としては十分に実用性があると思う. 欠点としては,普通にやるのと比べて多分遅いだろうということ. 利点としては,方法自体がやたら簡便であることと,無策に原始的な最小二乗法を用いる場合に比べて「結果を評価する」の部分を自由に決められるので,外れ値への耐性を持たせやすいであろうこと.
John-Doe.7

2018/08/23 13:23

具体的な回答?どうもありがとうございます。 いろいろ地道にやってみます!!
fana

2018/08/24 00:58

GAを挙げている方もおられますが,パラメタ空間をサンプリングしてより良い解を探すという意味では似たような話かと.
John-Doe.7

2018/08/27 08:55

なぜ、そんなに詳しいのですか?かじっているとかのレベルではないような気がしないのですが...。 ここで質問外のこと聞くのは無礼ではありますがもしよければ少し教えて欲しいです。 fanaさんは今回のような機械学習などのプログラムを作るプログラマーなのですか? もちろん、嫌でしたらお答えしていただかなくても大丈夫です。
fana

2018/08/27 09:28

うーん……私が書いている程度のことは,最小二乗法(のようなもの)を用いて何らかの観測データ等に関数を当てはめる作業を実際に行った経験があれば(その際に,外れ値の影響でうまい結果が得られないことに苦しんだり,関数の形が微分辛すぎな形で苦しんだりして,ちょうど今のあなたのように必要にせまられて色々と調べることになるので,その結果として)言える程度のことだと思いますよ. 今回の話題は「機械学習」とは直接的には関係ない話だと思いますし,私自身のことを言えば,機械学習に関わった経験はあまり無いです.
fana

2018/08/27 09:44

* データ点群の分布を曲線で表したいような話については「関数当てはめ(フィッティング)」 * この手の問題に関して探索的に解を見つけたいなら「数値計算」 * データの外れ値の影響を緩和したいなら「ロバスト推定」 あたりの単語でググると色々話が見つかるかと思います.
John-Doe.7

2018/08/27 15:27

ほんと何から何までありがとうございます! 調べさせていただきます
guest

0

「微分などを使わないで」との事ですので、GA(遺伝的アルゴリズム)を使うのはどうでしょうか?
(a,b,c)を遺伝子として、適応度は「複数の座標との二乗誤差の平均」とすれば、ある程度の解を得られるかと思います。

GAに関しては、例えば「実数値GAのフロンティア」などが参考になるかと思います。

投稿2018/08/23 08:46

rtr1950x

総合スコア298

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

John-Doe.7

2018/08/23 09:05

初めて聞いたアルゴリズムですが、勉強してみます。 また、機械学習に使えるか調べてみます! どうもありがとうございました!!
rtr1950x

2018/08/23 09:21

機械学習をするつもりでしたら、GAの勉強をするより微分の勉強をした方が後々有益かと思います。 高校レベルの微分の公式+偏微分さえ出来れば、大抵の機械学習は実装できるかと。 GAの長所は、微分不可能な関数の最適化が可能という点ですが、逆に言えば微分出来る関数に関しては微分して勾配の情報を用いるアルゴリズムの方が適している事が多いです。
John-Doe.7

2018/08/23 09:29 編集

わかりました。やっぱり微分からは逃げられない...。 実際に実装してみてどちらが精度の良い二次方程式が導けるかやってみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問