I/O problem

Hello. I am trying to program a neural network, and to do this, i need to retrieve information from a custom-formatted file that has inputs and target values for the net. However, i am suddenly having problems with my code parsing in the data for the net's use. I have two methods to retrieve the input and output data.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
unsigned TFile::getNextInputs(vector<double> &inputVals)
{
	inputVals.clear();

	string line;
	getline(tfile, line);
	stringstream ss(line);

	string label;
	ss >> label;
	if (label.compare("I") == 0) {
		double val;
		while (ss >> val) {
			inputVals.push_back(val);
		}
	}

	return inputVals.size();
}

unsigned TFile::getTargetOutputs(vector<double> &targetOutputVals)
{
	targetOutputVals.clear();

	string line;
	getline(tfile , line);
	stringstream ss(line);

	string label;
	ss >> label;
	if (label.compare("O") == 0) {
		double val;
		while (ss >> val) {
			targetOutputVals.push_back(val);
		}
	}
	return targetOutputVals.size();
}


I also have a method that reads in how many inputs and how many outputs are supposed to be there.

The file I am reading from looks like this currently:
http://pastebin.com/0hac65Dj

It is only reading 1 input. I have a break statement that checks whether the number of inputs is equal to the number given at the top (the first number after T). The size I am given from the getNextInputs() method prints as 1, and the number in map[0] is 2.

The break statement (in a while loop that runs until the end of the file is reached):
1
2
3
4
5
        vector<double> inputValues;
	//If the size of inputValues is not the number given in the map
	if (trainingData.getNextInputs(inputValues) != map[0]) {
		break;
	}

I am led to believe that this modifies the inputValues vector as well as comparing the size of map[0].
I do not know whether I am doing something wrong when reading in the file. I want to read more than one line with the while loop in the methods, but it seems to just be reading one line per call of the method.


Last edited on
Hi,

Can you show the code where you call the functions?

It looks to me that input is going to stop as soon as a non-double is encountered, so it will indeed only read 1 line given your input file. Or at least the value returned will be 1, so will not match the expected value from map[0], hence the break. You can find this out for yourself by using a debugger - it will save you days of staring at code

Btw, map is not a good name for a variable - you must have using namespace std; - there is potential for confusion there. In the end it is best to pre-pend every std thing with std::

Also, your return type should be std::size_t, because this is what size() functions return.

The break statement (in a while loop that runs until the end of the file is reached):


I hope you are not looping on eof :+)

Both of your functions are nearly identical, except for the "O" or "I" , you could send those values as a parameter, and have one function. Code duplication is something to be avoided. In that case the type of operation being performed is shown by the variable name the result is assigned to, and the vector being sent as an argument.

Hope this helps :+)
Last edited on
TFile::getNextInputs() will read exactly one line from the file. That's all it can read, since you're only calling std::getline() once. If your file looks like this:
I 1.0
I 1.0
calling TFile::getNextInputs() once will make it return 1 and assign the single double 1.0 to the output vector.
If it looks like this:
I 1.0 1.0
calling TFile::getNextInputs() once will make it return 2 and assign two doubles to the output vector.
helios's method worked. Here is the full code in my main class where i train the network:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
int main(int* argc, char* argv[]) {
	TFile trainingData("data.txt");
	vector<unsigned> map;
	trainingData.getTopology(map);
	Net net(map);

	cout << "I've made a net!" << endl;

	vector<double> inputValues, outputValues, targetValues;
	int trainingPass = 0;
	vector<double> cachedErrorValues;

	//While the training data is not end of file...
	while (!trainingData.isEof()) {
		trainingPass++;
		cout << endl << "Pass: " << trainingPass;
		//If the size of inputValues is not the number given in the map
		if (trainingData.getValues(inputValues, "I") != map[0]) {
			break;
		}
		showVectorValues(": Inputs:", inputValues);
		net.feedForward(inputValues);
		
		net.getResults(outputValues);
		showVectorValues("Outputs: ", outputValues);

		assert(trainingData.getValues(targetValues, "O") != map.back());
		showVectorValues("Targets: ", targetValues);
		net.backProp(targetValues);

		for (int i = 0; i < outputValues.size(); i++) {
			double percent_error = abs(outputValues[i] - targetValues[i]);
			cout << "Error [" << i << "]: " << percent_error * 100 << "%" << endl;
			cachedErrorValues.push_back(percent_error);
		}
	}
	cout << endl << "Done training." << endl;

	//Show progression of errors.
	cout << "Writing cached errors to file..." << endl;
	ofstream error_file("error_file.txt");
	for (int i = 0; i < cachedErrorValues.size(); i++) {
		error_file << i << "''" << cachedErrorValues[i] << endl;
	}
	cout << "Done writing." << endl;
	_getch();
	return 0;
}


With the added getValues() method to remove the repetition of code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
size_t TFile::getValues(vector<double> &vals, string tag) {
	vals.clear();
	string line;
	getline(tfile, line);
	stringstream ss(line);

	string label;
	ss >> label;
	if (label.compare(tag) == 0) {
		double val;
		while (ss >> val) {
			vals.push_back(val);
		}
	}
	return vals.size();
}


Thanks.




Hello again :+)

Pass std::string by reference:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
std::size_t TFile::getValues(std::vector<double> &vals, const std::string& tag) {
	vals.clear();
	std::string line;
	std::getline(tfile, line);
	std::stringstream ss(line);

	std::string label;
	ss >> label;
	if (label.compare(tag) == 0) {
		double val;
		while (ss >> val) {
			vals.push_back(val);
		}
	}
	return vals.size();
}
Done!
Thanks a bunch.


Topic archived. No new replies allowed.