Complete Correlation Matrix Memories (CCMM) Implementation
d:todo
1. paragraph
1. description

2. paragraph
1. test of all properties that are described in Teuvo's paper

3. paragraph
1. abstract class which can also be used in order to implement the incomplete correlation matrix memory

4. paragraph
1. mutable version where values can be added and removed

5. paragraph
1. back end agnostic repository system

6. paragraph
1. repository distribution system

7. paragraph
1. Move this and related articles to a new project.

#!/usr/bin/env python3
"""This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.

Based on the paper "Correlation Matrix Memories" by TEUVO KOHONEN.
"""
__author__ = 'Mārtiņš Avots'
from testingArtifacts import floatTuple
import unittest
class CompleteCorrelationMatrixMemory():
def __init__(self, keyValuePairs):
for key in keyValuePairs:
self.columns = len(key)
self.rows = len(keyValuePairs[key])
break
self.matrix = [[0. for i in range(self.columns)] for j in range(self.rows)]
keyValuePairs = self.convertKeyValuePairs(keyValuePairs)
for iRow in range(self.rows):
for iColumn in range(self.columns):
for key in keyValuePairs:
c = self.c(key) # Deviation from TEUVO's paper
value = keyValuePairs[key]
self.matrix[iRow][iColumn] += c * key[iColumn] * value[iRow]
def convertKeyValuePairs(self, keyValuePairs):
rVal = dict()
for key in keyValuePairs:
value = keyValuePairs[key]
key = tuple(floatTuple(key))
value = floatTuple(value)
rVal[key] = value
return rVal
def c(self, vector):
rBase = 0.
for i in vector:
rBase += i ** 2
return 1. / rBase
def recall(self, key):
key = floatTuple(key)
value = [0.]*self.rows
for iRow in range(len(value)):
for iColumn in range(len(key)):
value[iRow]
self.matrix[iRow][iColumn]
key[iColumn]
value[iRow] += self.matrix[iRow][iColumn] * key[iColumn]
return floatTuple(value)
if __name__ == "__main__":
from orthogonalKeyTests import OrthogonalKeyTests
from randomKeyTests import RandomKeyTests
from classificationTests import ClassificationTests
unittest.main()

#!/usr/bin/env python3
"""This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
"""
__author__ = 'Mārtiņš Avots'
from random import uniform, choice
def floatTuple(vector):
rVal = []
for e in vector:
rVal.append(float(e))
return rVal
def difference(a, b):
rVal = 0.
for i in range(len(a)):
rVal += abs(a[i] - b[i])
return rVal
def randomVector(length):
rVal = []
for i in range(length):
rVal.append(
uniform(-1000, 1000) # TODO Random chosen magic constants
)
return rVal
def randomZeroOneVector(length):
rVal = []
for i in range(length):
rVal.append(choice([0,1]))
return rVal
def randomZeroOnePositiveAndNegativeVector(length):
rVal = []
for i in range(length):
rVal.append(choice([-1,0,1]))
return rVal
def printImage(matrix, length):
rows=int(len(matrix) / length)
for row in range(rows):
rowStr = ""
for i in range(length):
rowStr += " " + str(round(matrix[row * length + i], 2))
print(rowStr)
print("")
images3x3 = {
"cross" : (1,0,1, 0,1,0, 1,0,1), # cross
"vertical" : (0,1,0, 0,1,0, 0,1,0), # vertical
"horizontal" : (0,0,0, 1,1,1, 0,0,0), # horizontal
"zero" : (1,1,1, 1,0,1, 1,1,1), # zero
"one" : (0,0,1, 0,1,1, 0,0,1), # one
"v" : (1,0,1, 1,0,1, 0,1,0), # v
"seven" : (1,1,1, 0,1,0, 1,0,0), # seven
"t" : (1,1,1, 0,1,0, 0,1,0), # t
"h" : (1,0,1, 1,1,1, 1,0,1) # h
}

#!/usr/bin/env python3
"""This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.

Based on the paper "Correlation Matrix Memories" by TEUVO KOHONEN.
"""
__author__ = 'Mārtiņš Avots'
import unittest
from completeCorrelationMatrixMemories import CompleteCorrelationMatrixMemory
from testingArtifacts import randomVector, randomZeroOneVector, difference, images3x3, randomZeroOnePositiveAndNegativeVector
from random import uniform, sample
class RandomKeyTests(unittest.TestCase):
def testRandomKeys(self): # TODO This test fails randomly.
self.__randomKeysTest(9, 9, lambda:randomVector(9))
def testRandomZeroOneKeys(self): # TODO This test fails randomly.
self.__randomKeysTest(9, 9, lambda:randomZeroOnePositiveAndNegativeVector(9))
def __randomKeysTest(self, keySize, valueCount, randomKeyGenerator):
values = sample(list(images3x3.values()), valueCount)
mapping = {}
for i in range(valueCount):
tmpRandomVector = tuple(randomKeyGenerator())
while tmpRandomVector in mapping:
tmpRandomxVector = tuple(randomKeyGenerator())
mapping[tmpRandomVector] = values[i]
testSubject = CompleteCorrelationMatrixMemory(mapping)
overallDifference = 0.
for key in mapping:
overallDifference += difference(testSubject.recall(key), mapping[key])
meanDifference = overallDifference / (9 * 9)
print("testRandomKeys: meanDifference = " + str(meanDifference)) # TODO make logs instead of console prints
# Randomly generated vectors are assumed to be not orthogonal.
# TODO check orthogonality during test and change assertions accordingly
self.assertTrue(meanDifference < .6)
self.assertTrue(meanDifference > .4)

#!/usr/bin/env python3
"""This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.

Based on the paper "Correlation Matrix Memories" by TEUVO KOHONEN.
"""
__author__ = 'Mārtiņš Avots'
from completeCorrelationMatrixMemories import CompleteCorrelationMatrixMemory
from unittest import TestCase, expectedFailure
from testingArtifacts import floatTuple, difference, images3x3
class ClassificationTests(TestCase):
# TODO high resolution image tests
def testClassificationOf2Images(self):
self.__testOrthogonalKeys({
images3x3["cross"] : (0,),
images3x3["zero"] : (2,),
})
def testClassificationOf2OtherImages(self):
self.__testOrthogonalKeys({
images3x3["cross"] : (0,),
images3x3["zero"] : (2,),
})
@expectedFailure
def testClassificationOf9Images(self):
"""It is not expected to work, as the keys are most propably not orthogonal"""
self.__testOrthogonalKeys({
images3x3["cross"] : (0,),
images3x3["vertical"] : (1,),
images3x3["horizontal"] : (2,),
images3x3["zero"] : (3,),
images3x3["one"] : (4,)
})
def __testOrthogonalKeys(self, mapping):
testSubject = CompleteCorrelationMatrixMemory(mapping)
for key in mapping:
self.assertEqual(mapping[key][0], self.__nearestNumber(mapping.values(), testSubject.recall(key)[0]))
def __nearestNumber(self, candidates, number):
"""Candidate is an tuple with 1 element."""
diff = 1000000000 # TODO magic number
candidate = None
for i in candidates:
currentDiff = abs(i[0] - number)
if currentDiff < diff:
diff = currentDiff
candidate = i[0]
return candidate

d:todo
1. paragraph
1. Implementation