/// <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); } }
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 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 /(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); }
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 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); }
/// <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); }