他の回答はパターンを正しく示していますが、十分に明確ではないと思います。残念ながら、私が提供したリンクは同じことを行うので、戦略の精神、私見が何であるかを実証しようとします.
戦略に関する主なことは、一般的な手順を持ち、その詳細 (動作) の一部を抽象化し、それらを透過的に変更できるようにすることです。
勾配降下最適化アルゴリズムを考えてみましょう。基本的には、次の 3 つのアクションで構成されます。
通常、これらのステップのどれを抽象化して構成可能にする必要があるかを選択します。この例では、目的関数の評価は複数の方法で実行できるものではないようです。常に関数を評価するだけです。
したがって、これは 2 つの異なる戦略 (またはポリシー) ファミリーを導入します。
interface GradientStrategy
{
double[] CalculateGradient(Function objectiveFunction, double[] point);
}
interface StepStrategy
{
double[] Step(double[] gradient, double[] point);
}
もちろん、次のFunction
ようなものです:
interface Function
{
double Evaluate(double[] point);
}
interface FunctionWithDerivative : Function
{
double[] EvaluateDerivative(double[] point);
}
次に、これらすべての戦略を使用するソルバーは次のようになります。
interface Solver
{
double[] Maximize(Function objectiveFunction);
}
class GradientDescentSolver : Solver
{
public Solver(GradientStrategy gs, StepStrategy ss)
{
this.gradientStrategy = gs;
this.stepStrategy = ss;
}
public double[] Maximize(Function objectiveFunction)
{
// choosing starting point could also be abstracted into a strategy
double[] currentPoint = ChooseStartingPoint(objectiveFunction);
double[] bestPoint = currentPoint;
double bestValue = objectiveFunction.Evaluate(bestPoint);
while (...) // termination condition could also
// be abstracted into a strategy
{
double[] gradient = this.gradientStrategy.CalculateGradient(
objectiveFunction,
currentPoint);
currentPoint = this.stepStrategy.Step(gradient, currentPoint);
double currentValue = objectiveFunction.Evaluate(currentPoint);
if (currentValue > bestValue)
{
bestValue = currentValue;
bestPoint = currentPoint;
}
else
{
// terminate or step back and reduce step size etc.
// this could also be abstracted into a strategy
}
}
return bestPoint;
}
private GradientStrategy gradientStrategy;
private StepStrategy stepStrategy;
}
つまり、要点は、アルゴリズムの概要を把握し、このアルゴリズムの特定の一般的な手順を戦略またはポリシーに委任することです。(キャストダウン)GradientStrategy
に対してのみ機能するものを実装し、関数の分析導関数を使用して勾配を取得することができます。FunctionWithDerivative
または、勾配推定の確率的バージョンを実装する別のものを用意することもできます。メイン ソルバは、勾配がどのように計算されているかを知る必要はなく、勾配だけが必要であることに注意してください。同じことが にも当てはまりますStepStrategy
- これは、単一のステップ サイズを持つ典型的なステップ ポリシーである可能性があります。
class SimpleStepStrategy : StepStrategy
{
public SimpleStepStrategy(double stepSize)
{
this.stepSize = stepSize;
}
double[] Step(double[] gradient, double[] point)
{
double[] result = new double[point.Length];
for (int i = 0;i < result.Length;++i)
{
result[i] = point[i] + this.stepSize * gradient[i];
}
return result;
}
private double stepSize;
}
、またはそれが進むにつれてステップサイズを調整する複雑なアルゴリズム。
また、コード内のコメントに記載されている動作についても考えてみてください: TerminationStrategy
, DeteriorationPolicy
.
名前は単なる例です。おそらく最適ではありませんが、意図を伝えてくれることを願っています。また、通常は 1 つのバージョン (戦略またはポリシー) に固執するのが最善です。