-
Van-Tuan Bui authoredVan-Tuan Bui authored
Mean Squared Error (MSE)
Understand the code
The codebase uses a script score.py
to define metric functions. Accuracy metric was implemented for you. Run the script to see the result:
./score.py predict.txt solution.txt
Install the necessary packages:
pip install numpy
Implement MSE metric
Now your task as a developer is to implement MSE metric. Recall the formula for MSE is:
MSE = \frac{1}{N} \sum_{i=1}^{N} (predicted_i - actual_i)²
Solution
- Create a feature
a_MSE
branch:
git pull origin develop
git checkout develop
git checkout -b a_MSE
- Create a
mse_metric
function and compute its score:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
from sys import argv
import numpy as np
# ========= Useful functions ==============
def read_array(filename):
''' Read array and convert to 2d np arrays '''
array = np.genfromtxt(filename, dtype=float)
if len(array.shape) == 1:
array = array.reshape(-1, 1)
return array
def accuracy_metric(solution, prediction):
correct_samples = np.all(solution == prediction, axis=1)
return correct_samples.mean()
def mse_metric(solution, prediction):
'''Mean-square error.
Works even if the target matrix has more than one column'''
mse = np.sum((solution - prediction)**2, axis=1)
return np.mean(mse)
def _HERE(*args):
h = os.path.dirname(os.path.realpath(__file__))
return os.path.join(h, *args)
# =============================== MAIN ========================================
if __name__ == "__main__":
#### INPUT/OUTPUT: Get input and output directory names
prediction_file = argv[1]
solution_file = argv[2]
score_file = open(_HERE('scores.txt'), 'w')
# # Extract the dataset name from the file name
prediction_name = os.path.basename(prediction_file)
# Read the solution and prediction values into numpy arrays
solution = read_array(solution_file)
prediction = read_array(prediction_file)
# Compute the score prescribed by the metric file
accuracy_score = accuracy_metric(solution, prediction)
mse_score = mse_metric(solution, prediction)
print(
"======= (" + prediction_name + "): score(accuracy_metric)=%0.2f =======" % accuracy_score)
print(
"======= (" + prediction_name + "): score(mse_metric)=%0.2f =======" % mse_score)
# Write score corresponding to selected task and metric to the output file
score_file.write("accuracy_metric: %0.2f\n" % accuracy_score)
score_file.write("mse_metric: %0.2f\n" % mse_score)
score_file.close()
- Commit and push changes:
git add score.py
git commit -m "implement MSE metric"
git push origin a_MSE
Implement unit tests for MSE
The tester have to implement unit tests for the accuracy_metric and mse_metric functions in the score.py
program. The process involves creating a test class, setting up test data, and then writing test cases for each function. You'll ensure that the tests cover a variety of scenarios, such as correct and incorrect predictions, and edge cases like empty arrays.
Solution
- Install pytest:
pip install pytest
- Create a file
tests/test_metrics.py
:
import unittest
import numpy as np
import os, sys
sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
from score import accuracy_metric, mse_metric # Import your metric functions
class TestMetrics(unittest.TestCase):
def setUp(self):
# Set up test data
self.solution = np.array([[1, 0, 1], [0, 1, 0], [1, 1, 1]])
self.correct_prediction = np.array([[1, 0, 1], [0, 1, 0], [1, 1, 1]])
self.incorrect_prediction = np.array([[0, 1, 0], [1, 0, 1], [0, 0, 1]])
self.empty_array = np.array([])
def test_accuracy_metric(self):
# Test accuracy with correct predictions
self.assertEqual(accuracy_metric(self.solution, self.correct_prediction), 1.0)
# Test accuracy with incorrect predictions
self.assertEqual(accuracy_metric(self.solution, self.incorrect_prediction), 0.0)
# Test accuracy with empty arrays
self.assertEqual(accuracy_metric(self.empty_array, self.empty_array), 0.0)
def test_mse_metric(self):
# Test MSE with correct predictions
self.assertEqual(mse_metric(self.solution, self.correct_prediction), 0.0)
# Test MSE with incorrect predictions
self.assertEqual(mse_metric(self.solution, self.incorrect_prediction), 8/3)
# Test MSE with empty arrays
self.assertEqual(mse_metric(self.empty_array, self.empty_array), 0.0)
if __name__ == '__main__':
unittest.main()
- Run the tests:
pytest
- Commit and push changes:
git add tests/test_metrics.py
git commit -m "implement unit tests for metrics"
git push origin a_MSE
Fix MSE metric
The tests failed. The tester tells to the developer that the two metric functions can't handle empty arrays. Now, the developer need to fix this by adding checks to return a default value or raise an error when the input arrays are empty. The appropriate action depends on the expected behavior of your application.
Solution
def accuracy_metric(solution, prediction):
if len(solution) == 0 or len(prediction) == 0:
return 0
correct_samples = np.all(solution == prediction, axis=1)
return np.mean(correct_samples)
def mse_metric(solution, prediction):
'''Mean-square error.
Works even if the target matrix has more than one column'''
if len(solution) == 0 or len(prediction) == 0:
return 0
mse = np.sum((solution - prediction)**2, axis=1)
return np.mean(mse)
- Run the tests:
pytest
The tests now should pass.
- Commit and push changes:
git add score.py
git commit -m "fix metric functions to handle empty arrays"
git push origin a_MSE
Create a merge request
As the tests passed, the developer creates a merge request from a_MSE
to develop
.
- On Gitlab project page, Select Code > Merge requests.
- In the upper-right corner, select New merge request.
- Select a source and target branch, then select Compare branches and continue.
- Complete the fields on the New merge request page,
- Description: implement MSE metric and unit tests for the two functions.
- Assignee:
Project leader
- Reviewer:
Code reviewer
then select Create merge request.
Approve a merge request
The code reviewer does run all the tests again and ensures that the features MSE
and unittest
have been accurately implemented. If something goes wrong, the reviewer communicates these findings to the developer and tester for rectification. If everything is OK, click on Approve
.
a_MSE
into develop
Merge It is the responsibility of the project leader to finalize the integration of changes into the develop
. This involves merging the requests that have been created by the developer and subsequently approved by the reviewer by simply clicking Merge
button.