在写BP神经网络时候碰到的小问题:UCI iris数据集是按顺序排的,我取的是前130行训练,后20行测试。因为到最后训练也是第三类,测试也都是第三类,是对于第三类的局部最优解,所以最后不用几轮训练就能达到>0.9的准确率,但全局上就不对。
于是写了个小程序随机改数据集的训练顺序。
因为只改行的顺序,对应的列不变。思想是用random的shuffle函数随机改行号,再把后面的列对应过去,以此实现乱序。
UCI iris数据集:
https://download.csdn.net/download/pvfeldt/18123868?spm=1001.2014.3001.5503
代码
下面是代码,有些地方写的不是很好,比如实现读文件时候数据和分类分开存读了两遍,如果是开个全局变量或者搞个class就可以避免;或者是这个想法本身就有点麻烦,水平有限见谅。
#include <iostream>
#include <fstream>
#include <random>
#include <vector>
#include <algorithm>
#include <chrono>
using namespace std;
//read file,store 4 feature columns in 2D double array;
double** irisData(string filename, int lines)
{
ifstream file(filename, ios::binary);
double** irisData = new double* [lines];
for (int i = 0; i < lines; i++)
{
irisData[i] = new double[4];
}
for (int i = 0; i < lines; i++)
{
double numTmp = 0;
char commaTmp = ' ';
string classificationTmp = " ";
for (int j = 0; j < 4; j++)
{
file >> numTmp >> commaTmp;
irisData[i][j] = numTmp;
}
file >> classificationTmp;
}
file.close();
return irisData;
}
//read file,store classification column in 1D string array;
string* irisClassification(string filename, int lines)
{
ifstream file(filename, ios::binary);
string* irisClassification = new string[lines];
for (int i = 0; i < lines; i++)
{
double numTmp = 0;
char commaTmp = ' ';
string classificationTmp = " ";
for (int j = 0; j < 4; j++)
{
file >> numTmp >> commaTmp;
}
file >> classificationTmp;
irisClassification[i] = classificationTmp;
}
file.close();
return irisClassification;
}
//randomly change the line index;
vector<int> changeLineIndexOrder(int lines)
{
vector<int> lineIndex(lines);
for (int i = 0; i < lines; i++)
{
lineIndex[i] = i;
}
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
shuffle(lineIndex.begin(), lineIndex.end(), default_random_engine(seed));
return lineIndex;
}
//change feature array according to the change of line index;
double** changeDataOrder(double** irisD, vector<int> lineI, int lines)
{
double** newIrisData = new double* [lines];
for (int i = 0; i < lines; i++)
{
newIrisData[i] = new double[4];
}
for (int i = 0; i < lines; i++)
{
for (int j = 0; j < 4; j++)
{
newIrisData[i][j] = irisD[lineI[i]][j];
}
}
return newIrisData;
}
//change classification array according to the change of line index;
string* changeClassificationOrder(string* irisC, vector<int> lineI, int lines)
{
string* newIrisClassification = new string[lines];
for (int i = 0; i < lines; i++)
{
newIrisClassification[i] = irisC[lineI[i]];
}
return newIrisClassification;
}
int main()
{
int lines = 150;
double** irisDataReading = irisData("iris.data", lines);
string* irisClassificationReading = irisClassification("iris.data", lines);
vector<int> lineIndex = changeLineIndexOrder(lines);
double** newIrisDataReading = changeDataOrder(irisDataReading, lineIndex, lines);
string* newIrisClassificationReading = changeClassificationOrder(irisClassificationReading, lineIndex, lines);
cout << "original data sequence:" << endl;
for (int i = 0; i < lines; i++)
{
cout << i << " ";
for (int j = 0; j < 4; j++)
{
cout << irisDataReading[i][j] << " ";
}
cout << irisClassificationReading[i] << endl;
}
cout << "changed data sequence:" << endl;
for (int i = 0; i < lines; i++)
{
cout << lineIndex[i] << " ";
for (int j = 0; j < 4; j++)
{
cout << newIrisDataReading[i][j] << " ";
}
cout << newIrisClassificationReading[i] << endl;
}
for (int i = 0; i < lines; i++)
{
delete[] irisDataReading[i];
delete[] newIrisDataReading[i];
}
delete[] irisDataReading;
delete[] newIrisDataReading;
delete[] irisClassificationReading;
delete[] newIrisClassificationReading;
system("pause");
return 0;
}
Over.