Elixir初心者向けテクニック:試行錯誤(翻訳)

生成とテストのアールゴリズム







ElixirでのAIテクニックのコーディング:生成およびテストアルゴリズム







最近、私はI.I.の分野でプロジェクトに取り組んでいます。 (人工知能)。 私の予想によると、このプロジェクトの作業にはかなりの時間がかかります。 目標はElixirで100%プロジェクトを作成することでしたが、この決定を下す前に、I.Iの分野で最も人気のあるソリューションのいくつかを実装できることを確認する必要がありました。 Elixirで。 数日間にわたって、私はI.I.の分野の研究者が使用する最も効果的な手法のいくつかを研究しました。 ソフトウェアで問題を解決します。







この記事では、 Generate and test algorithm (試行錯誤とも呼ばれる)と呼ばれるメソッドについて簡単に説明し、このメソッドのバリエーションを使用して、Elixirプログラミング言語を使用して簡単な問題を解決します。







I.I. 今日最も有名なものは、機械学習、自然言語処理、ロボット工学です。 しかし、私にとっては、IIでの私の好きな分野です。 自動推論として知られています。 私が実証するプログラムは、この領域IIに分類されます。









問題



非常に大きな自然数のグループの合計が偶数かどうかについて疑問文を作成し、この質問に対する答えを作成するプログラムを作成するタスクが与えられたとします。 自動推論の方法を使用して、この単純な問題を解決してみましょう。







解決策



自動推論アルゴリズムは、上記のような単純なタスクに最適です。 アルゴリズムの仕組みは非常に簡単です。 3つの主要なステップがあります。







1.    2.  ,     3.   ,     ,       1  3
      
      





この概念を念頭に置いて、「結果はx + yでも同じですか?」という質問に答えることができるスマートプログラムを作成しましょう。 この演習では、偶数の合計のみを対象とするため、合計をカウントした結果が偶数であることをシステムが検出すると、それに応じて期待される結果が見つかったことを確認して対応します。 通常、この手法を使用して真の答えを得た場合、すべての処理を停止する必要があります。 ただし、このケースでは、システムによって準備されたすべての質問が聞こえたときにのみ停止します。 そして最後に、偶数ではない数の合計の質問に対して、いいえと答えます。







コード



このタスクのソリューションを作成するとき、これから見るコードがElixirのコア機能のほとんどをカバーしていることに気付きました。 したがって、この時点までにElixirを使用したことがない場合、これらのコード例は、言語がどのように機能するかの実用的なアイデアを提供します。







最初のステップは、すべての実装コードを含むSumAndTest



というモジュールを作成することです。







 defmodule SumAndTest do @moduledoc """ This script is designed to show the functionality of the AI Algorithm that is known as Generate and Test. It will produce the results to a addition question and answer whether or not the answer is even. """
      
      







「結果x + yは偶数ですか?」という質問に答える必要があります。 それでは、この質問を含む関数を作成していきましょう。







  defp addition_question(first_numbaer, second_number) do "Is the result of #{first_numbaer} + #{second_number} even?" end
      
      







さて、質問があります。 次のステップでは、システムが質問に回答するための2つの可能な回答を特定します。 Elixirの機能を使用して、渡された引数に応じて同じ関数の代替定義を提供します。







  defp say_answer(true) do "YES! Even result found." end defp say_answer(false) do "No." end
      
      







私たちはイエスとノーに答える能力を生み出しました。 しかし、この応答をトリガーするものは何ですか? 2つの数の合計の結果が偶数かどうかを判断する必要があります。 対応する関数を作成します。







  defp even?(number) when is_number(number) do if rem(number, 2) == 0, do: true, else: false end
      
      





関数の本体を単にrem(number, 2) == 0



として書き換えることもできます。これは、それ自体でtrue



またはfalse



返しtrue



(およそ。)。









これで主要な構成要素の準備が整いましたが、自動推論の作成に取り組んでいます。 システムがこの質問に正しく答えていることを確認できるように、システム自体に自動的に質問が出されるようにします。 これを担当するgenerate



関数を作成しましょう。







  defp generate(amount_of_questions) when is_number(amount_of_questions) do generate(0, amount_of_questions) end defp generate(accumulator, amount_of_questions) when amount_of_questions >= 1 do question = addition_question(Enum.random(1..100_000), Enum.random(1..100_000)) build_list(question) generate(accumulator + 1, amount_of_questions - 1) end defp generate(total, 0) do IO.puts "#{total} addition questions generated." :ok end
      
      







完成間近です。 しかし、他に重要なことがあります。 generate/2



関数では、 build_list



関数を呼び出しました。 なぜこれが必要なのですか?







Elixirには不変のデータ構造があります。 これは、現在の関数以外では状態がサポートされていないことを意味します。 これは、高度な可変性を持つシステムを作成すると物事が非常に迅速に複雑になる可能性があるため、IIプログラミングに最適です。 天文学的な量の未知の可能性に対処できる分野では、ある程度の一貫性が必要です。 この一貫性はデータです。







これらの質問を作成しましたが、関数を終了した後にシステムがそれらの質問を失わないように、それらを保存する方法が必要です。 これがエリクサーエージェントの出番です。 Elixirのエージェントは、プログラムが状態を保持することを許可します。 これにより、時間に関係なくデータ構造の変更を追跡できます。 エージェントを使用するのは非常に簡単で、ジョーアームストロング(Erlangの作成者)がErlangとElixirで「データベースは必要ありません!」と言う主な理由かもしれません。 。 最初に空のリストを含むエージェントを作成しましょう。 このリストには、質問が保存されます。







  defp start_list do Agent.start(fn() -> [] end, [name: __MODULE__]) end
      
      







わあ! エージェントには初期化する機能があり、状態を含めることができるので、先に出てきたbuild_list



関数にbuild_list



で実装するのが流行です。







  defp build_list(question) do Agent.update(__MODULE__, fn(list) -> [question | list] end) end
      
      







システムが回答する必要があるすべての質問を表示するには、エージェントの現在の状態を取得する必要があります。 Agent.get/2



関数を使用するだけです。 この関数のquestions



呼び出します。







  defp questions do Agent.get(__MODULE__, &(&1)) end
      
      







ここで、すべての処理を1つの順次関数呼び出し(パイプライン)で実行できるように、このすべてのロジックをバインドする必要があります。 パイプラインは次のことを行う必要があります...







 1.          . 2.     . 3.  . 4.    . 5.  ""  "".
      
      





ここでは、パイプライン演算子(またはパイプライン演算子)を使用します。 この演算子は、Elixirプログラミング言語の筋肉組織であり、I.I。処理アルゴリズムになります LISPの場合よりもはるかに明確です。







  defp answer_to(question) do Regex.scan(~r/(\d+) \+ (\d+)/, question, [capture: :all_but_first]) |> List.flatten |> Enum.map(&String.to_integer(&1)) |> Enum.reduce(0, fn(n, acc) -> n + acc end) |> even? |> say_answer end
      
      







大きな数値をanswer_to/1



は、正規表現を変更して質問行から各数値の最後の桁のみを選択することでanswer_to/1



関数をわずかに最適化できます。合計のパリティは変わらないためです( answer_to/1



次の2つのオプションは元の記事にはありません)







  defp answer_to(question) do Regex.scan(~r/\d*(\d) \+ \d*(\d)/, question, [capture: :all_but_first]) |> List.flatten |> Enum.map(&String.to_integer(&1)) |> Enum.reduce(0, fn(n, acc) -> n + acc end) |> even? |> say_answer end
      
      





または、 Bitwiseモジュールを使用して、バイナリシステムの数値の最後の桁(1または0)のみを考慮することができます。 ^^^



演算子は、引数のビット単位のXOR演算を計算します。







  use Bitwise defp answer_to(question) do Regex.run(~r/(\d+) \+ (\d+)/, question, [capture: :all_but_first]) |> List.flatten |> Enum.map(&String.to_integer(&1)) |> Enum.reduce(0, fn(n, acc) -> acc ^^^ (n &&& 1) end) |> even? |> say_answer end
      
      





次に、システムのユーザーがシステムの動作を確認できるように、質問とその回答を表示する表示機能を作成しましょう。







  defp display_answer_for(question) do IO.puts(question) IO.puts(answer_to(question)) end
      
      







ついに! システムの最後の部分にいます。 このプロセス全体をトリガーする方法が必要です。 次のことを行うスタートアップ関数が必要です...







 1.  `start_list`,   . 2.     .    20-. 3.          .
      
      





この機能は次のようになります。







  def start do start_list generate(20) Enum.each(questions, &display_answer_for(&1)) end
      
      







準備ができました! SumAndTest.start



を呼び出すとSumAndTest.start



ますか? システムは、対応する回答を含む20のランダムな質問を生成します。 以下の結論を参照してください!!







 $ iex Erlang/OTP 18 [erts-7.3] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace] Interactive Elixir (1.3.1) - press Ctrl+C to exit (type h() ENTER for help) iex(1)> c("sum_and_test.ex") [SumAndTest] iex(2)> SumAndTest.start 20 addition questions generated. Is the result of 31956 + 95609 even? No. Is the result of 56902 + 37929 even? No. Is the result of 63154 + 23758 even? YES! Even result found. Is the result of 22268 + 66438 even? YES! Even result found. Is the result of 76068 + 36127 even? No. Is the result of 14158 + 84195 even? No. Is the result of 55174 + 13171 even? No. Is the result of 53028 + 68694 even? YES! Even result found. Is the result of 82027 + 39083 even? YES! Even result found. Is the result of 32349 + 70547 even? YES! Even result found. Is the result of 41416 + 37714 even? YES! Even result found. Is the result of 91326 + 32635 even? No. Is the result of 42663 + 21205 even? YES! Even result found. Is the result of 90054 + 71218 even? YES! Even result found. Is the result of 38305 + 69972 even? No. Is the result of 59014 + 3954 even? YES! Even result found. Is the result of 55096 + 34449 even? No. Is the result of 89363 + 16018 even? No. Is the result of 60760 + 12438 even? YES! Even result found. Is the result of 10044 + 47646 even? YES! Even result found. :ok
      
      





おわりに



これはおそらく、すべての人工知能アルゴリズムの中で最も単純です。 そのシンプルさが、Automating the Futureの最初の記事でこのアルゴリズムについて書くことにした理由です。 可能性のある結果がごく少数しか現れないという問題を扱っている場合は、試行錯誤法の使用を検討します。







投稿者:クエンティン・トーマス







ソースコード








All Articles