/// <summary> /// 保存したデータを基に学習開始 /// </summary> public bool Learning(bool isNowTrain) { //データが無いなら学習しない if (situationDatas.Get().Count == 0 && isNowTrain == false) { return(false); } isTrain = isNowTrain; if (isNowTrain) { isTrain = nn.Train(epochs, learningRate, isNowTrain); } else { nn.InputData(situationDatas, teachDatas); //入っているデータを削除 situationDatas = new NumYArray(); teachDatas = new NumYArray(); isTrain = nn.Train(epochs, learningRate, isNowTrain); } if (!isTrain) { nn.SaveLearningData(charName + "/"); } return(isTrain); }
/// <summary> /// 意思決定 /// </summary> public int DecideIntention() { NumYArray xData = new NumYArray(); xData.Add(situation); //ニューラルネットワークによる結果表示 NumYArray resultArray = new NumYArray(nn.Predict(xData)); List <List <float> > resultList = resultArray.Get(); //ランダムによる意思決定 float n = Random.Range(0.0f, NumY.Sum(resultArray).Get()[0][0]); float offset = 0.0f; for (int i = 0; i < resultList[0].Count; i++) { offset += resultList[0][i]; if (n <= offset) { intention = i; break; } } return(this.intention); }
//予測結果のデバッグ表示 public void DisplayPredict(NumYArray data) { string[] name = new string[] { "立ち弱", "立ち強", "しゃがみ弱", "しゃがみ強", "波動", "昇竜", "ガード", "しゃがみガード", "前進", "後退", "ダッシュ", "ジャンプ", "前ジャンプ", "後ジャンプ" }; for (int i = 0; i < name.Length; i++) { Debug.Log(name[i] + " : " + Mathf.Round(data.Get()[0][i] * 100) / 100); } }
/// <summary> /// データを元に結果を予測する /// </summary> /// <param name="xData">予測する状況</param> /// <returns>予測結果</returns> public NumYArray Predict(NumYArray xData) { //順伝播・フォワードプロパゲーション NumYArray layerZ1 = new NumYArray(NumY.Dot(xData, this.w1) + this.b1); NumYArray layerA1 = new NumYArray(NumY.Sigmoid(layerZ1)); NumYArray layerZ2 = new NumYArray(NumY.Dot(layerA1, this.w2) + this.b2); NumYArray layerA2 = new NumYArray(NumY.Sigmoid(layerZ2)); NumYArray returnArray = new NumYArray(layerA2); return(returnArray); }
// CSVデータを文字列型2次元配列に変換する // ファイルパス,変換される配列の値(参照渡し) public static NumYArray readCSVData(string path) { TextAsset csv; csv = Resources.Load(path) as TextAsset; StringReader reader = new StringReader(csv.text); string strStream = reader.ReadToEnd(); // StringSplitOptionを設定(要はカンマとカンマに何もなかったら格納しないことにする) System.StringSplitOptions option = StringSplitOptions.RemoveEmptyEntries; // 行に分ける string[] lines = strStream.Split(new char[] { '\r', '\n' }, option); // カンマ分けの準備(区分けする文字を設定する) char[] spliter = new char[1] { ',' }; // 行数設定 int h = lines.Length; // 列数設定 int w = lines[1].Split(spliter, option).Length; // 返り値の2次元配列の要素数を設定 List <List <float> > sdata = new List <List <float> >(); // 配列の要素確保 for (int i = 0; i < h - 1; i++) { sdata.Add(new List <float>()); for (int j = 0; j < w; j++) { sdata[i].Add(0); } } // 行データを切り分けて,2次元配列へ変換する for (int i = 1; i < h; i++) { string[] splitedData = lines[i].Split(spliter, option); for (int j = 0; j < w; j++) { sdata[i - 1][j] = float.Parse(splitedData[j]); } } NumYArray returnArray = new NumYArray(sdata); return(returnArray); }
public NumYArray(NumYArray n) { array = new List <List <float> >(); List <List <float> > nArray = n.Get(); for (int i = 0; i < nArray.Count; i++) { array.Add(new List <float>()); List <float> subList = nArray[i]; for (int j = 0; j < subList.Count; j++) { array[i].Add(subList[j]); } } }
/// <summary> /// 行列の積を求める /// </summary> /// <param name="a">自作行列</param> /// <param name="b">自作行列</param> /// <returns>計算された自作行列</returns> public static NumYArray Dot(NumYArray a, NumYArray b) { int[] sizeA = a.Size; int[] sizeB = b.Size; NumYArray copyA = new NumYArray(a); NumYArray copyB = new NumYArray(b); List <List <float> > arrayA = copyA.Get(); List <List <float> > arrayB = copyB.Get(); List <List <float> > array = new List <List <float> >(); //配列の要素確保 for (int i = 0; i < sizeA[0]; i++) { array.Add(new List <float>()); for (int j = 0; j < sizeB[1]; j++) { array[i].Add(0); } } //行列の内積計算 if (sizeA[1] == sizeB[0]) { for (int i = 0; i < array.Count; i++) { for (int j = 0; j < array[i].Count; j++) { float term = 0; for (int k = 0; k < sizeA[1]; k++) { term += arrayA[i][k] * arrayB[k][j]; } array[i][j] = term; } } } else { //Debug.Log("Error : Argument size does not match."); } NumYArray returnArray = new NumYArray(array); return(returnArray); }
/// <summary> /// シグモイド関数による計算 /// </summary> /// <param name="a">自作配列</param> /// <returns>計算された自作配列</returns> public static NumYArray Sigmoid(NumYArray a) { NumYArray copyArray = new NumYArray(a); List <List <float> > array = copyArray.Get(); for (int i = 0; i < array.Count; i++) { for (int j = 0; j < array[i].Count; j++) { array[i][j] = 1 / (1 + Mathf.Exp(-array[i][j])); } } NumYArray returnArray = new NumYArray(array); return(returnArray); }
public NeuralNetwork(int inputUnits, int hiddenUnits, int outpuUnits, string folderName) { //学習値のデータがあるならそこから読み込む if (System.IO.File.Exists(@"Assets/Resources/AIData/" + folderName + "/LearningDataCSVw1.csv")) { w1 = NeuralReadCSV.readCSVData("AIData/" + folderName + "/LearningDataCSVw1"); b1 = NeuralReadCSV.readCSVData("AIData/" + folderName + "/LearningDataCSVb1"); w2 = NeuralReadCSV.readCSVData("AIData/" + folderName + "/LearningDataCSVw2"); b2 = NeuralReadCSV.readCSVData("AIData/" + folderName + "/LearningDataCSVb2"); } else { w1 = NumY.RandomArray(inputUnits, hiddenUnits, 1.0f, -1.0f); b1 = NumY.RandomArray(1, hiddenUnits, 1.0f, -1.0f); w2 = NumY.RandomArray(hiddenUnits, outpuUnits, 1.0f, -1.0f); b2 = NumY.RandomArray(1, outpuUnits, 1.0f, -1.0f); } }
public static NumYArray RandomArray(int columnNum, int cellNum, float max, float min) { List <List <float> > list = new List <List <float> >(); //ランダム配列の生成 for (int i = 0; i < columnNum; i++) { list.Add(new List <float>()); for (int j = 0; j < cellNum; j++) { list[i].Add(Random.Range(min, max)); } } NumYArray returnArray = new NumYArray(list); return(returnArray); }
public static NumYArray operator /(NumYArray a, NumYArray b) { int[] sizeA = a.Size; int[] sizeB = b.Size; NumYArray copyA = new NumYArray(a); NumYArray copyB = new NumYArray(b); List <List <float> > arrayA = copyA.Get(); List <List <float> > arrayB = copyB.Get(); //行列の割り算(配列の要素がすべて同じの場合) if (sizeA[0] == sizeB[0]) { for (int i = 0; i < sizeA[0]; i++) { for (int j = 0; j < sizeA[1]; j++) { arrayA[i][j] /= arrayB[i][j]; } } } //(配列の要素の1次元目のみ違う場合) else if (sizeA[1] == sizeB[1]) { for (int i = 0; i < sizeA[0]; i++) { for (int j = 0; j < sizeA[1]; j++) { arrayA[i][j] /= arrayB[0][j]; } } } else { Debug.Log("Error : Argument size does not match."); } NumYArray array = new NumYArray(arrayA); return(array); }
public static NumYArray operator /(NumYArray a, float b) { int[] sizeA = a.Size; NumYArray copyA = new NumYArray(a); List <List <float> > arrayA = copyA.Get(); for (int i = 0; i < sizeA[0]; i++) { for (int j = 0; j < sizeA[1]; j++) { arrayA[i][j] /= b; } } NumYArray array = new NumYArray(arrayA); return(array); }
public static void SaveCSVData(NumYArray array, string csvName) { StreamWriter sw = new StreamWriter(@"Assets/Resources/AIData/" + csvName + ".csv", false, Encoding.GetEncoding("Shift_JIS")); //ヘッダー書き込み sw.WriteLine(csvName); string[] data = new string[array.Size[1]]; //データ書き込み for (int i = 0; i < array.Size[0]; i++) { for (int j = 0; j < array.Size[1]; j++) { data[j] = array.Get()[i][j].ToString(); } string str = string.Join(",", data); sw.WriteLine(str); } sw.Flush(); sw.Close(); }
public static NumYArray operator /(float a, NumYArray b) { int[] sizeB = b.Size; NumYArray copyB = new NumYArray(b); List <List <float> > arrayB = copyB.Get(); for (int i = 0; i < sizeB[0]; i++) { for (int j = 0; j < sizeB[1]; j++) { arrayB[i][j] = a / arrayB[i][j]; } } NumYArray array = new NumYArray(arrayB); return(array); }
// Use this for initialization void Start() { NumYArray xData = new NumYArray(NeuralReadCSV.readCSVData(inputDataName)); NumYArray yData = new NumYArray(NeuralReadCSV.readCSVData(outputDataName)); int epochs = 2000; float learningRate = 0.1f; //ニューラルネットワークの生成 NeuralNetwork nn = new NeuralNetwork(xData.Size[1], 8, yData.Size[1], "Aoi"); //時間計測 float startTime = Time.realtimeSinceStartup; bool a = false; nn.InputData(xData, yData); a = nn.Train(epochs, learningRate, a); //データを基にトレーニング while (a) { a = nn.Train(epochs, learningRate, a); } float endTime = Time.realtimeSinceStartup; //トレーニング時間の表示 Debug.Log(endTime - startTime); //仮データによる結果の予測 float[][] testList = { new float[] { 0.1f, 0.5f, 0.5f, 0.5f, 0.0f } }; NumYArray testData = new NumYArray(testList); NumYArray result = new NumYArray(nn.Predict(testData)); //予測結果の表示 DisplayPredict(result); //学習した重みの保存 nn.SaveLearningData("Aoi/"); }
/// <summary> /// 初期化 /// </summary> void Start() { charName = gameObject.name.Replace("IntentionObj", ""); string filePath = @"Assets/Resources/AIData/" + charName + "/LearningDataCSVw1.csv"; //csvファイルからデータの読み込み NumYArray xData = new NumYArray(NeuralReadCSV.readCSVData("AIData/" + inputDataName)); NumYArray yData = new NumYArray(NeuralReadCSV.readCSVData("AIData/" + outputDataName)); //ニューラルネットワークの生成 nn = new NeuralNetwork(xData.Size[1], 8, yData.Size[1], charName); //学習値のデータがないなら初期学習をする if (!System.IO.File.Exists(filePath) && !isTrain) { nn.InputData(xData, yData); //データを基にトレーニング nn.Train(this.epochs, this.learningRate, false); nn.SaveLearningData(charName + "/"); } }
/// <summary> /// 入力されたデータを元にトレーニング /// </summary> /// <param name="epochs">トレーニング回数</param> /// <param name="learningRate">学習率</param> /// <returns></returns> public bool Train(int epochs, float learningRate, bool isTrainNow) { if (!isTrainNow) { NumYArray layerZ1 = new NumYArray(); NumYArray layerA1 = new NumYArray(); NumYArray layerZ2 = new NumYArray(); NumYArray layerA2 = new NumYArray(); NumYArray dlayerZ1 = new NumYArray(); NumYArray dlayerZ2 = new NumYArray(); NumYArray dw1 = new NumYArray(); NumYArray db1 = new NumYArray(); NumYArray dw2 = new NumYArray(); NumYArray db2 = new NumYArray(); totalTrainNum = 0; maxTrainNum = Mathf.RoundToInt(100 / xData.Get().Count); if (maxTrainNum <= 0) { maxTrainNum = 1; } learnSpeed = 1; } nowTrainNum = 0; //規定回数学習させ、他処理のために途中で抜ける while (nowTrainNum < maxTrainNum * learnSpeed) { //許容値を超えているか判定する用出力結果 //Array a = Predict(xData); int m = xData.Get()[0].Count; //順伝播・フォワードプロパゲーション layerZ1 = NumY.Dot(xData, this.w1) + this.b1; layerA1 = NumY.Sigmoid(layerZ1); layerZ2 = NumY.Dot(layerA1, this.w2) + this.b2; layerA2 = NumY.Sigmoid(layerZ2); //誤差逆伝播法・バックプロパゲーション dlayerZ2 = (layerA2 - yData) / m; dw2 = NumY.Dot(layerA1.T, dlayerZ2); db2 = NumY.Sum(dlayerZ2, 0); dlayerZ1 = NumY.Dot(dlayerZ2, w2.T) * NumY.SigmoidDerivative(layerZ1); dw1 = NumY.Dot(xData.T, dlayerZ1); db1 = NumY.Sum(dlayerZ1, 0); //パラメータ更新 w2 -= learningRate * dw2; b2 -= learningRate * db2; w1 -= learningRate * dw1; b1 -= learningRate * db1; nowTrainNum++; totalTrainNum++; if (totalTrainNum >= epochs) { this.xData = new NumYArray(); this.yData = new NumYArray(); totalTrainNum = 0; nowTrainNum = 0; return(false); } } nowTrainNum = 0; return(true); }
/// <summary> /// シグモイド関数の微分 /// </summary> /// <param name="a">自作配列</param> /// <returns>微分された自作配列</returns> public static NumYArray SigmoidDerivative(NumYArray a) { NumYArray copyArray = new NumYArray(a); return(Sigmoid(copyArray) * (1 - Sigmoid(copyArray))); }
public static NumYArray NumYArray(NumYArray n) { return(new NumYArray(n)); }
public void InputData(NumYArray xData, NumYArray yData) { this.xData = new NumYArray(xData); this.yData = new NumYArray(yData); }
public static NumYArray Sum(NumYArray a, int axis = -1) { int[] sizeA = a.Size; NumYArray copyArray = new NumYArray(a); List <List <float> > copyList = copyArray.Get(); List <List <float> > list = new List <List <float> >(); //全ての数値を足す if (axis == -1) { float sumNum = 0; for (int i = 0; i < sizeA[0]; i++) { for (int j = 0; j < sizeA[1]; j++) { sumNum += copyList[i][j]; } } list.Add(new List <float>()); list[0].Add(sumNum); } //指定された計算方法による加算 else { //列の和を求める if (axis == 0) { list.Add(new List <float>()); for (int i = 0; i < sizeA[1]; i++) { float sumNum = 0; for (int j = 0; j < sizeA[0]; j++) { sumNum += copyList[j][i]; } list[0].Add(sumNum); } } //行の和を求める else if (axis == 1) { for (int i = 0; i < sizeA[0]; i++) { list.Add(new List <float>()); float sumNum = 0; for (int j = 0; j < sizeA[1]; j++) { sumNum += copyList[i][j]; } list[i].Add(sumNum); } } else { Debug.Log("Error : Argument size does not match."); } } NumYArray returnArray = new NumYArray(list); return(returnArray); }