2

特に、次のタイプの問題を解決するための最良のアプローチを決定しようとしています。

私が興味を持っている例は、Mitchell の機械学習の本にある find-s アルゴリズムで、4 つのトレーニング例に適用されます。

基本的な考え方は、各トレーニング例 x と仮説 h について、h' を決定することです。これは、x をより一般的にすることによって x を組み込む場合に当てはまります。トレーニング セット内の x ごとに h を h' にマッピングする必要があります。私が抱えている問題は、論理プログラミング言語でこれに最もよく取り組む方法です。私はスキームに大まかにプロローグを埋め込んだミニカンレンを使用しています。

各 h' を計算したら、次に設定する必要があります。それをグローバル変数 h に代入し、次のトレーニング例 x に進みます。以下のコードは、プログラムの主要部分です。

(define h '(0 0 0 0 0 0))

(define seto
  (lambda (x)
    (project (x)
             (lambda (s) (set! h x) (succeed s)))))

(run* (q)
     (fresh (x h0 h1)
            (trainingo x)
            (== h h0)
            (find-so h0 x h1)
            (seto h1)
            (== h1 q)))

h はグローバル変数であり、seto は h0 から次に計算された仮説である h1 で h を変更し、find-s アルゴリズム (find-so) を使用して x のトレーニング例を作成します。

プロローグでは、各トレーニング例 X (前のものを上書き) の後にassert('hypothesis'(H))を呼び出し、すべてのトレーニング例が終了した後にrettract('hypothesis'(H))を呼び出すことと同等です (私が思うに)。適用。

繰り返しますが、私の質問は、これがこの種の問題を解決するための (副作用による) 最良のアプローチであるかどうかです。

編集: @mat の回答を彼のコメントと共に受け入れました。要約すると、トレーニング例をリストとして扱い、空のリストに到達するまでそのリストで前方再帰を使用する必要がありました。私が立ち往生していたのは、空になるまで繰り返すことができるリストにそれらを含めるのではなく、次の仮説を見つけることと一緒にバックトラックの一部としてトレーニングの例を持っていたことでした.

4

1 に答える 1

3

あなたの提案は魅力的assertz/0に見えるかもしれません:と でグローバルな更新をシミュレートしますretract/1

ただし、この方法で行うと、次のような大きな欠点があります。

  • グローバル状態を使用すると、述語を単独で使用およびテストできなくなります。
  • 破壊的な更新を使用すると、述語をより多くの方向で使用できなくなります。
  • グローバル状態の微妙で暗黙的な依存関係により、述語の変更は非常にエラーが発生しやすくなります。

これらの状態の変化をシミュレートする宣言的な解決策は、状態間の関係の観点から考えることです。

たとえば、 を使用して次の仮説H0を計算する場合、これをと の間の関係、場合によってはさらなるパラメーターとして表現できます。次のような述語について考えてみてください。H1H0H1

  • hypothesis_next(H0, H1)
  • algorithm_hypothesis_next(A, H0, H1)
  • parameters_hypothesis_next(Ps, H0, H1)

このような述語は読み取り可能であり、理想的にはすべての方向に実行できることに注意してください。

合計すると、ソリューション全体が一連の仮説としてモデル化されます。

H0H1H2→ … →H

詳細とポインタについては、密接に関連する質問を参照してください。

グローバル (または状態) 変数を実装するために Prolog で assert とrettractall を使用しないようにする方法

于 2016-10-21T07:15:44.037 に答える