- 投稿日:2020-09-11T19:16:02+09:00
C#学習時のメモ (随時修正)
標準入力
using System; class Sample{ static void Main(){ //文字列 var date = Console.ReadLine(); //int型 var num = int.Parse(Console.ReadLine()); } }出力
using System; class Sample{ static void Main(){ //改行なし Console.Write(/*出力値*/); //改行あり Console.WriteLine(/*出力値*/); } }if文
using System; class Sample{ static void Main(){ if (/*条件式*/) { /*処理*/ } else if (/*条件式*/) { /*処理*/ } else { /*処理*/ } } }while文
using System; class Sample{ static void Main(){ //以下カウンタ変数の宣言 var i = 0; while (/*条件式*/) { /*ループ処理*/ //以下カウンタ変数の更新 i+=1 } } }for文
using System; class Sample{ static void Main(){ //forの後に(カウンタ変数の宣言; 条件式; カウンタ変数を更新) for (var i = 0; i<10; i+=1) { /*繰り返し処理*/ } } }Lengthメソッド(配列や文字列の長さを取得)
var word = "hello" var snum = "1234567" var num = 1234567 string[] ary = {"A","B","C"} word.Length // 5 snum.Length // 7 num.Length // 変数numの値が文字列では無いのでエラー ary.Length // 3
- 投稿日:2020-09-11T18:27:01+09:00
ML-Agentsでカートポールを実装2
はじめに
前回の記事の続きです。今回は作成した3Dオブジェクトを動かすスクリプトを書いていきます。
エージェントのスクリプトを記述する
今回はカートポールのカートに力を加えてポールを制御していきます。つまり、カートが学習させるエージェントになります。
まず初めにScriptフォルダにCartPoleAgentというC# Scriptを作成してください。エージェントのスクリプトではAgentクラスを継承し、以下の関数を記述します。
- Initialize() : 初期値を取得
- CollectObservations() : 観測データをセンサーに送る
- OnActionReceived() : 行動する
- OnEpisodeBegin() : ステップ開始の条件を決定
- Heuristic() : キーボードから操作する
- SetResetParameters() : パラメータをリセット
CartPoleAgent.csの全体
はじめにスクリプトの全体のコードを載せます。
using UnityEngine; using Unity.MLAgents; using Unity.MLAgents.Sensors; using System.Collections; using System.Collections.Generic; public class CartPoleAgent : Agent { //学習用 public GameObject pole; Rigidbody poleRB; Rigidbody cartRB; EnvironmentParameters m_ResetParams; //初期値 public override void Initialize() { //学習の初期化 poleRB = pole.GetComponent<Rigidbody>(); cartRB = gameObject.GetComponent<Rigidbody>(); m_ResetParams = Academy.Instance.EnvironmentParameters; SetResetParameters(); } //センサーにデータを送る public override void CollectObservations(VectorSensor sensor) { sensor.AddObservation(gameObject.transform.localPosition.z); sensor.AddObservation(cartRB.velocity.z); sensor.AddObservation(pole.transform.localRotation.eulerAngles.x); sensor.AddObservation(poleRB.angularVelocity.x); } //各ステップでの行動 public override void OnActionReceived(float[] verctorAction) { //カートに力を加える var actionZ = 200f * Mathf.Clamp(verctorAction[0], -1f, 1f); cartRB.AddForce(new Vector3(0.0f, 0.0f, actionZ), ForceMode.Force); //カートの位置、ポールの角度と角速度 float cart_z = this.gameObject.transform.localPosition.z; float angle_x = pole.transform.localRotation.eulerAngles.x; //angle_zを-180~180に変換 if(180f < angle_x && angle_x < 360f) { angle_x = angle_x - 360f; } //カートが+-45度いないなら報酬+0.1 それ以外は -1 if((-180f < angle_x && angle_x < -45f) || (45f < angle_x && angle_x < 180f)) { SetReward(-1.0f); EndEpisode(); } else{ SetReward(0.1f); } //カートの位置が-10~10の範囲を超えたら報酬-1 if(cart_z < -10f || 10f < cart_z) { SetReward(-1.0f); EndEpisode(); } } //ステップ開始の初期条件を決定 public override void OnEpisodeBegin() { //エージェントの状態をリセット gameObject.transform.localPosition = new Vector3(0f, 0f, 0f); pole.transform.localPosition = new Vector3(0f, 2.5f, 0f); pole.transform.localRotation = Quaternion.Euler(0f, 0f, 0f); poleRB.angularVelocity = new Vector3(0f, 0f, 0f); poleRB.velocity = new Vector3(0f, 0f, 0f); //ポールにランダムな傾きを与える poleRB.angularVelocity = new Vector3(Random.Range(-0.1f, 0.1f), 0f, 0f); SetResetParameters(); } //キーボードから操作する場合 public override void Heuristic(float[] actionsOut) { actionsOut[0] = Input.GetAxis("Horizontal"); } //ポールの条件をリセット public void SetPole() { poleRB.mass = m_ResetParams.GetWithDefault("mass", 1.0f); pole.transform.localScale = new Vector3(0.4f, 2f, 0.4f); } //パラメータをリセットする関数 public void SetResetParameters() { SetPole(); } }public class CartPoleAgent : AgentAgentクラスを継承します。
public GameObject pole; Rigidbody poleRB; Rigidbody cartRB; EnviromentParameters m_ResetParams;で PoleオブジェクトやCart, Pole の rigidbody をいれる変数を定義します。Poleオブジェクトはスクリプト外から取得するので public にします。
Initialize()
Initialize()では学習の初期値を取得します。今回はCart と Pole のrigidbody と環境のパラメータです。また最後の行で各パラメータをリセットしています。
public override void Initialize() { //学習の初期化 poleRB = pole.GetComponent<Rigidbody>(); cartRB = gameObject.GetComponent<Rigidbody>(); m_ResetParams = Academy.Instance.EnvironmentParameters; SetResetParameters(); }CollectObservations()
CollectionObservations()ではエージェントが得た観測情報をセンサーに追加します。
public override void CollectObservations(VectorSensor sensor) { sensor.AddObservation(gameObject.transform.localPosition.z); sensor.AddObservation(cartRB.velocity.z); sensor.AddObservation(pole.transform.localRotation.eulerAngles.x); sensor.AddObservation(poleRB.angularVelocity.x); }今回は上から、「Cartの位置」、「Cartの速度」、「Poleの角度」、「Poleの角速度」を与えています。
この値の選択は学習モデルによって変わります。この値が適切なのかわからないので、いろいろ試してみてください。OnActionReceived()
OnActionReceived()では各ステップでのエージェントの動きについて記述します。今回はカートに移動方向の力を加えます。
また、報酬の設定などもここで行います。//各ステップでの行動 public override void OnActionReceived(float[] verctorAction) { //カートに力を加える var actionZ = 200f * Mathf.Clamp(verctorAction[0], -1f, 1f); cartRB.AddForce(new Vector3(0.0f, 0.0f, actionZ), ForceMode.Force); //カートの位置、ポールの角度と角速度 float cart_z = this.gameObject.transform.localPosition.z; float angle_x = pole.transform.localRotation.eulerAngles.x; //angle_zを-180~180に変換 if(180f < angle_x && angle_x < 360f) { angle_x = angle_x - 360f; } //カートが+-45度いないなら報酬+0.1 それ以外は -1 if((-180f < angle_x && angle_x < -45f) || (45f < angle_x && angle_x < 180f)) { SetReward(-1.0f); EndEpisode(); } else{ SetReward(0.1f); } //カートの位置が-10~10の範囲を超えたら報酬-1 if(cart_z < -10f || 10f < cart_z) { SetReward(-1.0f); EndEpisode(); } }カートを動かすコードです。入力値がvectorActionになっています。この値を -200~200 に変換し、加える力の大きさにします。この値の幅は適当です。CartのrigidbodyのAddForceをいじることでカートに力を加えることができます。今回はZ方向に力を加えます。
//カートに力を加える var actionZ = 200f * Mathf.Clamp(verctorAction[0], -1f, 1f); cartRB.AddForce(new Vector3(0.0f, 0.0f, actionZ), ForceMode.Force);エージェント(カート)の報酬に関するコードです。今回はポールの角度が -45°~45° 以内だと報酬として +0.1, それ以外だと報酬を -1.0 与えゲームを終了させます。また、カートが横に動きすぎないようにカートの位置が -10~10 の範囲から出ると -1.0 の報酬を与えゲームを終了させます。
//カートが+-45度いないなら報酬+0.1 それ以外は -1 if((-180f < angle_x && angle_x < -45f) || (45f < angle_x && angle_x < 180f)) { SetReward(-1.0f); EndEpisode(); } else{ SetReward(0.1f); } //カートの位置が-10~10の範囲を超えたら報酬-1 if(cart_z < -10f || 10f < cart_z) { SetReward(-1.0f); EndEpisode(); }OnEpisodeBegin()
OnEpisodeBegin()ではゲームの初期条件を決めます。今回はカートは初期位置に戻し、ポールにランダムな傾きを与えます。
//ステップ開始の初期条件を決定 public override void OnEpisodeBegin() { //エージェントの状態をリセット gameObject.transform.localPosition = new Vector3(0f, 0f, 0f); pole.transform.localPosition = new Vector3(0f, 2.5f, 0f); pole.transform.localRotation = Quaternion.Euler(0f, 0f, 0f); poleRB.angularVelocity = new Vector3(0f, 0f, 0f); poleRB.velocity = new Vector3(0f, 0f, 0f); //ポールにランダムな傾きを与える poleRB.angularVelocity = new Vector3(Random.Range(-0.1f, 0.1f), 0f, 0f); SetResetParameters(); }Heuristic()
Heuristic()ではキーボード入力でモデルを動かすときに使用します。今回は十字キーの左右の入力に対応しています。
//キーボードから操作する場合 public override void Heuristic(float[] actionsOut) { actionsOut[0] = Input.GetAxis("Horizontal"); }Behavior Parametersの設定、実際に動かしてみる
このスクリプトをCartオブジェクトに追加してください。このときPoleにPoleオブジェクトを追加してください。
また、Add Component から、Behavior Parameters と Decision Requester を追加してください。これは強化学習時に必要になります。Behavior Parameters / Behavior Type でモデルのモードを変更することができます。今回はキーボード入力を使用したいので Heuristic Only にしてください。学習時は Defaults, 学習済みモデルを使用するときは Inference Only にします。(Inference Onlyを使用する場合は学習済みモデルをModelに追加する必要があります。)
以下の画像のようにパラメータを設定してください。
この状態でモデルを実行するとキーボードで操作することができると思います。しっかり、ポールの角度でリセットされていればOKです。
ここまでで学習に必要な準備は完了しました。あとはサンプルと同じように学習されれば完成になります。
学習させる
実際にカートポールを学習させます。学習させるため、Behavior Parameters / Behavior Type を Defaults にしてください。
また学習の効率化のためカートポールを複数台にします。今回は10台にしました。コピペで簡単に増やすことができます。
学習パラメータを設定するYAMLファイルをconfigフォルダに作成してください。3DBallのパラメータを参考にしました。
モデルの学習方法の詳しい解説はこの記事を参考にしてください。
25万回ぐらいで学習が完了します。学習が完了すると CartPole.nn というファイルが作成されています。このファイルを TFModels に追加してください。
TrainingArea(1)~(9)を非アクティブにして学習済みモデルを実行した動画です。ポールを倒さないように制御できていることが確認できます。
まとめ
カートポールのモデルを作成し、学習させませた。ML-Agentsでは基本的にエージェントのスクリプトを書くだけで強化学習モデルを簡単に実装することができます。まだわからないことが多いので知識が増えたらまた記事を書きたいと思います。
- 投稿日:2020-09-11T15:43:20+09:00
ML-Agentsでカートポールを実装2
概要
ML-Agentsでカートポールを実装し、学習させます。自分でML-Aegentsを使って学習させるモデルを作成したい人の助けになればいいと思っています。
はじめに
ML-Agentsのサンプルのようなモデルを自作します。学習方法は前回の記事で説明したので、今回は学習させるモデルの作り方を中心に記事にしました。公式のドキュメントを参考にしました。細かいところはこちらを確認してください。
全体の流れ
モデルの作成、学習には主に4つ工程があります。
- unityで3Dモデルを作成
- 学習させるエージェントのスクリプトを記述する
- Behavior Parameterを設定する
- 学習させる
実際に作成しながら説明していきます。
記事が長くなるので今回は3Dモデルの作成まで説明します。unityで3Dモデルを作成
はじめにunityで学習させたい3Dモデルを作成します。今回はカートポールを実装します。カートポールとはカートについているポールが倒れないように制御する問題のことです。
最終的には以下のモデルを作成します。学習を効率化するために複数のモデルを置いてます。
カートポール作成
左下のProjectで以下の画像のようにCartPoleというファイルを作成してください。また、File/New Sceneから新しいシーンを作成しCart Poleと名付けて作成したファイルに保存してください。
Materialにはカートやポール、床の材料特性を設定するものが入ります。Scriptには作成したオブジェクトを動かすスクリプトが入ります。最後のTFModelsは学習済みモデルを入れるファイルになります。次にsceneを開いて以下のように3D Objectを追加してください。
追加する3D Objectは cube, sylinder, plane をそれぞれ一つづつ追加してください。また追加したら cubeをCartに、sylinderをPoleに名前を変更してください。また、CartとPoleはTrainingAreaという空のObjectを作成し、そこに入れてください。
それぞれのスケールなどは以下の画像を参考にしてください。
次にcomponentを追加していきます。
Componentの追加
unity では作成したオブジェクトにcomponentを追加することで様々な特性を持たせることができます。今回は rigidbody と Hinge Joint を追加します。 rigidbody を追加することによって、オブジェクトを物理特性によって制御することができるようになります。具体的には重力を付加したり、力を加えたり、空気抵抗などを設定することができます。Hinge Joint を追加するとCart と Pole がヒンジで結合されます。
componentの追加方法は、追加したいオブジェクトを選択し、画面の右下にある Add Component をクリックし追加したい物を選択します。
rigidbodyの追加
「rigidbody」を選択します。
CartとPoleにそれぞれ追加してください。追加されると以下の画像のようになると思います。
パラメータをそれぞれ画像のように設定してください。(適当でもいいです)
Mass はオブジェクトの質量[Kg]です。
Drag は空気抵抗を表しています。値が大きくなるほど抵抗が大きくなります。0の場合は真空状態となります。
Angular Drag はオブジェクトが回転する時の空気抵抗です。値が大きいほど回転しにくくなります。
Constraints / Freeze Position はオブジェクトの動きを制限させます。今回Cartは横方向(Z方向)に動いて欲しいので、手前方向(X方向)にチェックを入れます。
Freeze Rotation はオブジェクトの回転を制限します。今回はCartは回転しないので全てにチェックを入れてください。
Hinge Joint の追加
Add Component / Physics / Hinge Joint から追加してください。
パラメータを画像のように設定してください。また Connected Body に Cart を追加してください。Materialの設定
次にオブジェクトのMaterialの設定をします。Cart と Pole は色を設定するだけなので各自設定してください。今回はPlaneで摩擦を設定します。Materialフォルダの中にPhysic Material を追加して、Planeという名前に変更してください。真ん中の黄緑色のやつができると思います。
Dynamic Friction で動摩擦を設定します。値は 0~inf で大きいほどオブジェクトが動かなくなります。
Static Friction は静止摩擦を設定します。
今回摩擦のパラメータは適当でいいです(大きすぎるとCartが動かなくなります)。作成した Physic Material を Plane オブジェクトに追加してください。Planeオブジェクトを選択し、そこにドラッグアンドドロップすればいいです。画像の印のようになっていればOKです。
これで3Dオブジェクトは完成になります。
まとめ
今回はunityで3DオブジェクトのCart Pole を作成しました。これで学習させるモデルはほぼ完成しました。次回はスクリプトを書いていきます。
- 投稿日:2020-09-11T15:43:20+09:00
ML-Agentsでカートポールを実装1
概要
ML-Agentsでカートポールを実装し、学習させます。自分でML-Aegentsを使って学習させるモデルを作成したい人の助けになればいいと思っています。
はじめに
ML-Agentsのサンプルのようなモデルを自作します。学習方法は前回の記事で説明したので、今回は学習させるモデルの作り方を中心に記事にしました。公式のドキュメントを参考にしました。細かいところはこちらを確認してください。
全体の流れ
モデルの作成、学習には主に4つ工程があります。
- unityで3Dモデルを作成
- 学習させるエージェントのスクリプトを記述する
- Behavior Parameterを設定する
- 学習させる
実際に作成しながら説明していきます。
記事が長くなるので今回は3Dモデルの作成まで説明します。unityで3Dモデルを作成
はじめにunityで学習させたい3Dモデルを作成します。今回はカートポールを実装します。カートポールとはカートについているポールが倒れないように制御する問題のことです。
最終的には以下のモデルを作成します。学習を効率化するために複数のモデルを置いてます。
カートポール作成
左下のProjectで以下の画像のようにCartPoleというフォルダを作成してください。また、File/New Sceneから新しいシーンを作成しCart Poleと名付けて作成したフォルダに保存してください。
Materialにはカートやポール、床の材料特性を設定するものが入ります。Scriptには作成したオブジェクトを動かすスクリプトが入ります。最後のTFModelsは学習済みモデルを入れるフォルダになります。次にsceneを開いて以下のように3D Objectを追加してください。
追加する3D Objectは cube, sylinder, plane をそれぞれ一つづつ追加してください。また追加したら cubeをCartに、sylinderをPoleに名前を変更してください。また、CartとPoleはTrainingAreaという空のObjectを作成し、そこに入れてください。
それぞれのスケールなどは以下の画像を参考にしてください。
次にcomponentを追加していきます。
Componentの追加
unity では作成したオブジェクトにcomponentを追加することで様々な特性を持たせることができます。今回は rigidbody と Hinge Joint を追加します。 rigidbody を追加することによって、オブジェクトを物理特性によって制御することができるようになります。具体的には重力を付加したり、力を加えたり、空気抵抗などを設定することができます。Hinge Joint を追加するとCart と Pole がヒンジで結合されます。
componentの追加方法は、追加したいオブジェクトを選択し、画面の右下にある Add Component をクリックし追加したい物を選択します。
rigidbodyの追加
「rigidbody」を選択します。
CartとPoleにそれぞれ追加してください。追加されると以下の画像のようになると思います。
パラメータをそれぞれ画像のように設定してください。(適当でもいいです)
Mass はオブジェクトの質量[Kg]です。
Drag は空気抵抗を表しています。値が大きくなるほど抵抗が大きくなります。0の場合は真空状態となります。
Angular Drag はオブジェクトが回転する時の空気抵抗です。値が大きいほど回転しにくくなります。
Constraints / Freeze Position はオブジェクトの動きを制限させます。今回Cartは横方向(Z方向)に動いて欲しいので、手前方向(X方向)にチェックを入れます。
Freeze Rotation はオブジェクトの回転を制限します。今回はCartは回転しないので全てにチェックを入れてください。
Hinge Joint の追加
Add Component / Physics / Hinge Joint から追加してください。
パラメータを画像のように設定してください。また Connected Body に Cart を追加してください。Materialの設定
次にオブジェクトのMaterialの設定をします。Cart と Pole は色を設定するだけなので各自設定してください。今回はPlaneで摩擦を設定します。Materialフォルダの中にPhysic Material を追加して、Planeという名前に変更してください。真ん中の黄緑色のやつができると思います。
Dynamic Friction で動摩擦を設定します。値は 0~inf で大きいほどオブジェクトが動かなくなります。
Static Friction は静止摩擦を設定します。
今回摩擦のパラメータは適当でいいです(大きすぎるとCartが動かなくなります)。作成した Physic Material を Plane オブジェクトに追加してください。Planeオブジェクトを選択し、そこにドラッグアンドドロップすればいいです。画像の印のようになっていればOKです。
これで3Dオブジェクトは完成になります。
まとめ
今回はunityで3DオブジェクトのCart Pole を作成しました。これで学習させるモデルはほぼ完成しました。次回はスクリプトを書いていきます。
- 投稿日:2020-09-11T12:14:10+09:00
C#で簡易的な暗号化ソフトを作る
C#で簡易的な暗号化ソフトを作ってみました。
今回は、暗号化したい元の文章を、Keyを使って暗号化、復号化する簡易的なソフトです。
Xorを使っています。Cを暗号化されたデータ、Oを元のデータ、Kをキーだとすると
C = O xor K
で、暗号化し
O = C xor K
で復号化できます。
このXorの性質を利用した暗号化です。プログラム
クラスにまとめたので、ライブラリにしたり、埋め込んだりできます。
code.csusing System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Ango { class code { public string encrypt(string original,string key) { string str = original; byte[] arr = Encoding.GetEncoding("Shift_JIS").GetBytes(str); string str2 = key; byte[] arr2 = Encoding.GetEncoding("Shift_JIS").GetBytes(str2); string out_string = ""; int str2_index = 0; int str2_next_index; for (int i = 0; i < arr.Length; i++) { str2_next_index = str2_index + 1; if (str2_next_index >= arr2.Length) str2_next_index = 0; arr2[str2_index] = (byte)((arr2[str2_index] + arr2[str2_next_index]) ^ arr2[str2_next_index]); arr2[str2_next_index] = (byte)(arr2[str2_index] + arr2[str2_next_index]); out_string = out_string + (arr[i] ^ arr2[str2_index]).ToString() + ","; str2_index++; if (str2_index >= arr2.Length) str2_index = 0; } return out_string; } public string decrypt(string cryptogram,string key) { string[] arr = cryptogram.Split(','); byte[] byte_arr = new byte[arr.Length]; string str2 = key; byte[] arr2 = Encoding.GetEncoding("Shift_JIS").GetBytes(str2); int str2_index = 0; int str2_next_index; for (int i = 0; i < arr.Length - 1; i++) { str2_next_index = str2_index + 1; if (str2_next_index >= arr2.Length) str2_next_index = 0; arr2[str2_index] = (byte)((arr2[str2_index] + arr2[str2_next_index]) ^ arr2[str2_next_index]); arr2[str2_next_index] = (byte)(arr2[str2_index] + arr2[str2_next_index]); byte_arr[i] = Convert.ToByte(arr[i]); byte_arr[i] = (byte)(byte_arr[i] ^ arr2[str2_index]); str2_index++; if (str2_index >= arr2.Length) str2_index = 0; } string out_str = Encoding.GetEncoding("Shift_JIS").GetString(byte_arr); return out_str; } } }解説
関数
encrypt
は暗号化します。
引数に、元の文章、キーを渡します。
暗号化されたものがテキスト形式で返されます。まず、元の文章と、キーを、
String
からByte[]
にします。
2つのByte[]
を1バイトずつずらしながらXorします。これだけだと、キーが推測されやすいらしいので、キーを常に変更しています。
arr2[str2_index] = (byte)((arr2[str2_index] + arr2[str2_next_index]) ^ arr2[str2_next_index]); arr2[str2_next_index] = (byte)(arr2[str2_index] + arr2[str2_next_index]);関数
decrypt
は復号化する関数です。
引数に、暗号化されたテキスト、キーを渡します。
復号化された文章が返されます。後は、暗号化の時と、ほぼ同じです。
使用例
読者に挑戦?
今回、暗号化のアルゴリズムを知られても、キーを推測して復号化できないと思います。
どこからそんな自信が来るのか分かりませんが、キーを常に変更しているため、非常に困難だと思います。(ド素人感覚)
もし、できそうだと思う方がいらしたら、以下の暗号化されたものを解読してください。ちなみにキーは日本語も使えます。
135,168,181,167,173,90,27,45,183,0,220,38,143,140,145,252,201,93,82,34,227,101,95,234,150,153,76,118,94,33,1,93,20,74,41,192,184,27,143,147,163,76,95,170,199,9,222,177,50,45,233,232,244,49,173,221,229,158,220,65,132,217,75,38,221,150,20,152,149,2,64,172,236,151,155,98,78,22,237,202,107,47,40,205,107,160,67,237,166,173,235,46,249,188,154,9,241,140,222,211,209,101,136,149,175,224,113,128,100,233,145,140,153,104,201,230,10,165,140,115,161,124,85,76,206,185,67,158,7,201,153,124,44,29,200,170,132,29,145,4,228,15,230,139,19,78,71,91,193,93,225,154,