0% found this document useful (0 votes)
2 views10 pages

Image Classification

The document is a C# program for image classification using a neural network, specifically designed for the CIFAR-10 dataset. It includes methods for initializing weights, loading data, training the model through forward and backward passes, and evaluating accuracy. The program implements convolutional and fully connected layers, along with necessary functions for data manipulation and model training.

Uploaded by

youritguy1987
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views10 pages

Image Classification

The document is a C# program for image classification using a neural network, specifically designed for the CIFAR-10 dataset. It includes methods for initializing weights, loading data, training the model through forward and backward passes, and evaluating accuracy. The program implements convolutional and fully connected layers, along with necessary functions for data manipulation and model training.

Uploaded by

youritguy1987
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 10

...os\ImageClassification\ImageClassification\Program.

cs 1
1 using System;
2 using System.IO;
3 using static System.Net.Mime.MediaTypeNames;
4
5 namespace ImageClassification
6 {
7 class Program
8 {
9 static int ImageSize = 32 * 32 * 3; // CIFAR-10 image size
10 static int NumClasses = 10; // 10 output classes
11 static int HiddenSize = 128; // Hidden layer size
12 static double LearningRate = 0.001;
13 static int Epochs = 10;
14
15 static double[,] WeightsInputHidden = new double[ImageSize,
HiddenSize];
16 static double[,] WeightsHiddenOutput = new double[HiddenSize,
NumClasses];
17 static double[] BiasHidden = new double[HiddenSize];
18 static double[] BiasOutput = new double[NumClasses];
19
20 static Random random = new Random();
21
22 static void Main(string[] args)
23 {
24 // Step 1: Initialize weights and biases
25 InitializeWeights();
26
27 // Step 2: Load CIFAR-10 dataset
28 double[][] trainingData = LoadTrainingData();
29 int[] trainingLabels = LoadTrainingLabels();
30
31 // Step 3: Train the neural network
32 for (int epoch = 0; epoch < Epochs; epoch++)
33 {
34 double totalLoss = 0.0;
35 for (int i = 0; i < trainingData.Length; i++)
36 {
37 // Prepare data
38 double[,] input2D = ConvertTo2D(trainingData[i]); //
Convert 1D to 2D
39 var (hiddenOutput, cnnOutput) = ForwardPassCNN
(input2D); // Get both hiddenOutput and output
40
41 // Compute loss and gradients
42 double[] target = new double[NumClasses];
43 target[trainingLabels[i]] = 1.0; // One-hot encoding
44 double[] lossGradient = new double[NumClasses];
45 for (int j = 0; j < NumClasses; j++)
...os\ImageClassification\ImageClassification\Program.cs 2
46 {
47 lossGradient[j] = cnnOutput[j] - target[j];
48 totalLoss += 0.5 * Math.Pow(lossGradient[j], 2);
49 }
50
51 // Flatten the input2D for Backpropagate
52 double[] flattened = Flatten(input2D);
53
54 // Pass the correct hiddenOutput to Backpropagate
55 Backpropagate(flattened, hiddenOutput, cnnOutput,
lossGradient);
56 }
57 Console.WriteLine($"Epoch {epoch + 1}: Loss = {
totalLoss / trainingData.Length}");
58 }
59
60 // Step 4: Evaluate the model with micro-accuracy
61 double[][] testData = LoadTestData();
62 int[] testLabels = LoadTestLabels();
63 double correctPredictions = 0;
64
65 for (int i = 0; i < testData.Length; i++)
66 {
67 double[,] input2D = ConvertTo2D(testData[i]);
68 var (_, cnnOutput) = ForwardPassCNN(input2D); // Get only
the output
69
70 int predictedLabel = Array.IndexOf(cnnOutput, MaxValue
(cnnOutput)); // Predict the label
71 if (predictedLabel == testLabels[i])
72 {
73 correctPredictions++;
74 }
75 }
76
77 double microAccuracy = correctPredictions / testData.Length;
78 Console.WriteLine($"Micro-Averaged Accuracy: {(
microAccuracy * 100):.2f}%");
79 }
80
81
82 static void InitializeWeights()
83 {
84 for (int i = 0; i < ImageSize; i++)
85 for (int j = 0; j < HiddenSize; j++)
86 WeightsInputHidden[i, j] = random.NextDouble() * 0.01;
87
88 for (int i = 0; i < HiddenSize; i++)
89 for (int j = 0; j < NumClasses; j++)
...os\ImageClassification\ImageClassification\Program.cs 3
90 WeightsHiddenOutput[i, j] = random.NextDouble() *
0.01;
91 }
92
93
94 static double[] Softmax(double[] inputs)
95 {
96 double[] outputs = new double[inputs.Length];
97 double expSum = 0.0;
98
99 foreach (double value in inputs)
100 {
101 expSum += Math.Exp(value);
102 }
103
104 for (int i = 0; i < inputs.Length; i++)
105 {
106 outputs[i] = Math.Exp(inputs[i]) / expSum;
107 }
108
109 return outputs;
110 }
111 static void Backpropagate(double[] flattenedInput, double[]
hiddenOutput, double[] output, double[] lossGradient)
112 {
113 //Console.WriteLine("Starting Backpropagate...");
114 //Console.WriteLine($"FlattenedInput size:
{flattenedInput.Length}");
115 //Console.WriteLine($"HiddenOutput size:
{hiddenOutput.Length}");
116 //Console.WriteLine($"Output size: {output.Length}");
117 //Console.WriteLine($"LossGradient size:
{lossGradient.Length}");
118
119 if (hiddenOutput.Length != HiddenSize)
120 {
121 throw new Exception($"Mismatch: hiddenOutput size
({hiddenOutput.Length}) does not match HiddenSize
({HiddenSize}).");
122 }
123
124 double[] hiddenGradient = new double[HiddenSize];
125
126 // Update output layer weights
127 for (int col = 0; col < NumClasses; col++)
128 {
129 for (int row = 0; row < HiddenSize; row++)
130 {
131 WeightsHiddenOutput[row, col] -= LearningRate *
...os\ImageClassification\ImageClassification\Program.cs 4
lossGradient[col] * hiddenOutput[row];
132 }
133 BiasOutput[col] -= LearningRate * lossGradient[col];
134 }
135
136 // Compute hidden layer gradient
137 for (int row = 0; row < HiddenSize; row++)
138 {
139 for (int col = 0; col < NumClasses; col++)
140 {
141 hiddenGradient[row] += lossGradient[col] *
WeightsHiddenOutput[row, col];
142 }
143 hiddenGradient[row] *= (1 - Math.Pow(hiddenOutput[row],
2)); // Derivative of tanh
144 }
145
146 // Update input layer weights
147 for (int row = 0; row < HiddenSize; row++)
148 {
149 for (int col = 0; col < flattenedInput.Length; col++)
150 {
151 WeightsInputHidden[col, row] -= LearningRate *
hiddenGradient[row] * flattenedInput[col];
152 }
153 BiasHidden[row] -= LearningRate * hiddenGradient[row];
154 }
155 }
156
157
158 static double MaxValue(double[] array)
159 {
160 double max = array[0];
161 foreach (double value in array)
162 if (value > max) max = value;
163 return max;
164 }
165
166 // Load training data
167 public static double[][] LoadTrainingData()
168 {
169 string[] batches = {
170 "data_batch_1.bin",
171 "data_batch_2.bin",
172 "data_batch_3.bin",
173 "data_batch_4.bin",
174 "data_batch_5.bin"
175 };
176
...os\ImageClassification\ImageClassification\Program.cs 5
177 return LoadBatchData(batches);
178 }
179
180 // Load training labels
181 public static int[] LoadTrainingLabels()
182 {
183 string[] batches = {
184 "data_batch_1.bin",
185 "data_batch_2.bin",
186 "data_batch_3.bin",
187 "data_batch_4.bin",
188 "data_batch_5.bin"
189 };
190
191 return LoadBatchLabels(batches);
192 }
193
194 // Load test data
195 public static double[][] LoadTestData()
196 {
197 string[] batches = { "test_batch.bin" };
198 return LoadBatchData(batches);
199 }
200
201 // Load test labels
202 public static int[] LoadTestLabels()
203 {
204 string[] batches = { "test_batch.bin" };
205 return LoadBatchLabels(batches);
206 }
207
208 // Helper method to load batch data
209
210 private static double[][] LoadBatchData(string[] batchFiles)
211 {
212 var images = new System.Collections.Generic.List<double[]>();
213
214 foreach (var file in batchFiles)
215 {
216 if (!File.Exists(file))
217 throw new FileNotFoundException($"File not found:
{file}");
218
219 using (var reader = new BinaryReader(File.Open(file,
FileMode.Open)))
220 {
221 while (reader.BaseStream.Position <
reader.BaseStream.Length)
222 {
...os\ImageClassification\ImageClassification\Program.cs 6
223 // Read label (1 byte, discard here)
224 reader.ReadByte();
225
226 // Read image data (3072 bytes)
227 byte[] imageBytes = reader.ReadBytes(ImageSize);
228
229 // Debug raw values before normalization
230 //Console.WriteLine($"Raw Pixel Values:
{string.Join(", ", imageBytes.Take(10))}");
231
232 // Normalize image data to [0, 1]
233 double[] image = new double[ImageSize];
234 for (int i = 0; i < ImageSize; i++)
235 {
236 image[i] = imageBytes[i] / 255.0;
237 }
238
239 // Debug normalized values
240 //Console.WriteLine($"Normalized Pixel Values:
{string.Join(", ", image.Take(10))}");
241
242 images.Add(image);
243 }
244 }
245 }
246
247 return images.ToArray();
248 }
249 // Helper method to load batch labels
250 private static int[] LoadBatchLabels(string[] batchFiles)
251 {
252 var labels = new System.Collections.Generic.List<int>();
253
254 foreach (var file in batchFiles)
255 {
256 using (var reader = new BinaryReader(File.Open(file,
FileMode.Open)))
257 {
258 while (reader.BaseStream.Position <
reader.BaseStream.Length)
259 {
260 // Read label (1 byte)
261 labels.Add(reader.ReadByte());
262
263 // Skip image data (3072 bytes)
264 reader.BaseStream.Seek(ImageSize,
SeekOrigin.Current);
265 }
266 }
...os\ImageClassification\ImageClassification\Program.cs 7
267 }
268
269 return labels.ToArray();
270 }
271 #region ADDED CODE
272 static (double[] hiddenOutput, double[] output) ForwardPassCNN
(double[,] image)
273 {
274 //Console.WriteLine("Starting ForwardPassCNN...");
275
276 // Step 1: Apply convolution
277 double[,] kernel = InitializeKernel();
278 // Console.WriteLine("Kernel initialized.");
279 double[,] convOutput = Convolve(image, kernel);
280 // Console.WriteLine($"Convolution output size:
{convOutput.GetLength(0)}x{convOutput.GetLength(1)}");
281
282 // Step 2: Apply pooling
283 double[,] pooledOutput = MaxPool(convOutput, 2);
284 // Console.WriteLine($"Pooling output size:
{pooledOutput.GetLength(0)}x{pooledOutput.GetLength(1)}");
285
286 // Step 3: Flatten pooled output
287 double[] flattened = Flatten(pooledOutput);
288 //Console.WriteLine($"Flattened output size:
{flattened.Length}");
289
290 // Step 4: Pass through fully connected layers
291 var (hiddenOutput, output) = ForwardPassFullyConnected
(flattened);
292 //Console.WriteLine("Completed ForwardPassCNN.");
293 return (hiddenOutput, output);
294 }
295 static double[,] Convolve(double[,] input, double[,] kernel)
296 {
297 int kernelSize = kernel.GetLength(0);
298 int outputSize = input.GetLength(0) - kernelSize + 1;
299 double[,] output = new double[outputSize, outputSize];
300
301 for (int i = 0; i < outputSize; i++)
302 {
303 for (int j = 0; j < outputSize; j++)
304 {
305 double sum = 0.0;
306 for (int ki = 0; ki < kernelSize; ki++)
307 {
308 for (int kj = 0; kj < kernelSize; kj++)
309 {
310 sum += input[i + ki, j + kj] * kernel[ki, kj];
...os\ImageClassification\ImageClassification\Program.cs 8
311 }
312 }
313 output[i, j] = Math.Max(0, sum); // ReLU activation
314 }
315 }
316 return output;
317 }
318 static double[,] MaxPool(double[,] input, int poolSize)
319 {
320 int outputSize = input.GetLength(0) / poolSize;
321 double[,] output = new double[outputSize, outputSize];
322
323 for (int i = 0; i < outputSize; i++)
324 {
325 for (int j = 0; j < outputSize; j++)
326 {
327 double max = double.MinValue;
328 for (int pi = 0; pi < poolSize; pi++)
329 {
330 for (int pj = 0; pj < poolSize; pj++)
331 {
332 max = Math.Max(max, input[i * poolSize + pi,
j * poolSize + pj]);
333 }
334 }
335 output[i, j] = max;
336 }
337 }
338 return output;
339 }
340 static double[] Flatten(double[,] pooledOutput)
341 {
342 int rows = pooledOutput.GetLength(0);
343 int cols = pooledOutput.GetLength(1);
344 double[] flattened = new double[rows * cols];
345
346 for (int i = 0; i < rows; i++)
347 {
348 for (int j = 0; j < cols; j++)
349 {
350 flattened[i * cols + j] = pooledOutput[i, j];
351 }
352 }
353 return flattened;
354 }
355 static double[,] InitializeKernel()
356 {
357 int kernelSize = 3; // Example: 3x3 kernel
358 double[,] kernel = new double[kernelSize, kernelSize];
...os\ImageClassification\ImageClassification\Program.cs 9
359
360 Random random = new Random();
361 for (int i = 0; i < kernelSize; i++)
362 {
363 for (int j = 0; j < kernelSize; j++)
364 {
365 kernel[i, j] = random.NextDouble() * 0.01; // Small
random values
366 }
367 }
368
369 return kernel;
370 }
371 static (double[] hiddenOutput, double[] output)
ForwardPassFullyConnected(double[] flattened)
372 {
373 if (flattened.Length == 0)
374 {
375 throw new Exception("Flattened input is empty. Check your
CNN pipeline.");
376 }
377
378 double[] hiddenOutput = new double[HiddenSize];
379 for (int i = 0; i < HiddenSize; i++)
380 {
381 for (int j = 0; j < flattened.Length; j++)
382 {
383 hiddenOutput[i] += flattened[j] * WeightsInputHidden
[j, i];
384 }
385 hiddenOutput[i] += BiasHidden[i];
386 hiddenOutput[i] = Math.Tanh(hiddenOutput[i]); // Apply
activation
387 }
388
389 double[] output = new double[NumClasses];
390 for (int i = 0; i < NumClasses; i++)
391 {
392 for (int j = 0; j < HiddenSize; j++)
393 {
394 output[i] += hiddenOutput[j] * WeightsHiddenOutput[j,
i];
395 }
396 output[i] += BiasOutput[i];
397 }
398
399 return (hiddenOutput, Softmax(output)); // Return both
hiddenOutput and output
400 }
...os\ImageClassification\ImageClassification\Program.cs 10
401 static double[,] ConvertTo2D(double[] input)
402 {
403 int imageSize = 32; // CIFAR-10 images are 32x32
404 double[,] output = new double[imageSize, imageSize];
405
406 for (int i = 0; i < imageSize; i++)
407 {
408 for (int j = 0; j < imageSize; j++)
409 {
410 output[i, j] = input[i * imageSize + j];
411 }
412 }
413
414 return output;
415 }
416 #endregion
417
418 }
419 }

You might also like