mirror of
https://github.com/gsi-upm/senpy
synced 2024-11-22 16:12:29 +00:00
Converted Ekman2VAD to centroids
* Changed the way modules are imported -> we can now use dotted notation (e.g. senpy.plugins.conversion.centroids) * Refactored ekman2vad's plugin -> generic centroids * Added some basic tests
This commit is contained in:
parent
453b9f3257
commit
d8b59d06a4
6
Makefile
6
Makefile
@ -41,12 +41,12 @@ build-%: version Dockerfile-%
|
|||||||
quick_test: $(addprefix test-,$(PYMAIN))
|
quick_test: $(addprefix test-,$(PYMAIN))
|
||||||
|
|
||||||
dev-%:
|
dev-%:
|
||||||
@docker start $(NAME)-dev || (\
|
@docker start $(NAME)-dev$* || (\
|
||||||
$(MAKE) build-$*; \
|
$(MAKE) build-$*; \
|
||||||
docker run -d -w /usr/src/app/ -v $$PWD:/usr/src/app --entrypoint=/bin/bash -p 5000:5000 -ti --name $(NAME)-dev '$(IMAGEWTAG)-python$*'; \
|
docker run -d -w /usr/src/app/ -v $$PWD:/usr/src/app --entrypoint=/bin/bash -ti --name $(NAME)-dev$* '$(IMAGEWTAG)-python$*'; \
|
||||||
)\
|
)\
|
||||||
|
|
||||||
docker exec -ti $(NAME)-dev bash
|
docker exec -ti $(NAME)-dev$* bash
|
||||||
|
|
||||||
dev: dev-$(PYMAIN)
|
dev: dev-$(PYMAIN)
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ import copy
|
|||||||
import fnmatch
|
import fnmatch
|
||||||
import inspect
|
import inspect
|
||||||
import sys
|
import sys
|
||||||
import imp
|
import importlib
|
||||||
import logging
|
import logging
|
||||||
import traceback
|
import traceback
|
||||||
import yaml
|
import yaml
|
||||||
@ -181,7 +181,7 @@ class Senpy(object):
|
|||||||
newentries = []
|
newentries = []
|
||||||
for i in resp.entries:
|
for i in resp.entries:
|
||||||
if output == "full":
|
if output == "full":
|
||||||
newemotions = copy.copy(i.emotions)
|
newemotions = copy.deepcopy(i.emotions)
|
||||||
else:
|
else:
|
||||||
newemotions = []
|
newemotions = []
|
||||||
for j in i.emotions:
|
for j in i.emotions:
|
||||||
@ -303,6 +303,13 @@ class Senpy(object):
|
|||||||
logger.info('Installing requirements: ' + str(requirements))
|
logger.info('Installing requirements: ' + str(requirements))
|
||||||
pip.main(pip_args)
|
pip.main(pip_args)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _load_module(cls, name, root):
|
||||||
|
sys.path.append(root)
|
||||||
|
tmp = importlib.import_module(name)
|
||||||
|
sys.path.remove(root)
|
||||||
|
return tmp
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _load_plugin_from_info(cls, info, root):
|
def _load_plugin_from_info(cls, info, root):
|
||||||
if not cls.validate_info(info):
|
if not cls.validate_info(info):
|
||||||
@ -310,11 +317,10 @@ class Senpy(object):
|
|||||||
return None, None
|
return None, None
|
||||||
module = info["module"]
|
module = info["module"]
|
||||||
name = info["name"]
|
name = info["name"]
|
||||||
sys.path.append(root)
|
|
||||||
(fp, pathname, desc) = imp.find_module(module, [root, ])
|
|
||||||
cls._install_deps(info)
|
cls._install_deps(info)
|
||||||
tmp = imp.load_module(module, fp, pathname, desc)
|
tmp = cls._load_module(module, root)
|
||||||
sys.path.remove(root)
|
|
||||||
candidate = None
|
candidate = None
|
||||||
for _, obj in inspect.getmembers(tmp):
|
for _, obj in inspect.getmembers(tmp):
|
||||||
if inspect.isclass(obj) and inspect.getmodule(obj) == tmp:
|
if inspect.isclass(obj) and inspect.getmodule(obj) == tmp:
|
||||||
|
@ -7,7 +7,7 @@ import pickle
|
|||||||
import logging
|
import logging
|
||||||
import tempfile
|
import tempfile
|
||||||
import copy
|
import copy
|
||||||
from . import models
|
from .. import models
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
0
senpy/plugins/conversion/__init__.py
Normal file
0
senpy/plugins/conversion/__init__.py
Normal file
52
senpy/plugins/conversion/centroids.py
Normal file
52
senpy/plugins/conversion/centroids.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
from senpy.plugins import EmotionConversionPlugin
|
||||||
|
from senpy.models import EmotionSet, Emotion, Error
|
||||||
|
|
||||||
|
import logging
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class CentroidConversion(EmotionConversionPlugin):
|
||||||
|
|
||||||
|
def _forward_conversion(self, original):
|
||||||
|
"""Sum the VAD value of all categories found."""
|
||||||
|
res = Emotion()
|
||||||
|
for e in original.onyx__hasEmotion:
|
||||||
|
category = e.onyx__hasEmotionCategory
|
||||||
|
if category in self.centroids:
|
||||||
|
for dim, value in self.centroids[category].iteritems():
|
||||||
|
try:
|
||||||
|
res[dim] += value
|
||||||
|
except Exception:
|
||||||
|
res[dim] = value
|
||||||
|
return res
|
||||||
|
|
||||||
|
def _backwards_conversion(self, original):
|
||||||
|
"""Find the closest category"""
|
||||||
|
dimensions = list(self.centroids.values())[0]
|
||||||
|
|
||||||
|
def distance(e1, e2):
|
||||||
|
return sum((e1[k] - e2.get(self.aliases[k], 0)) for k in dimensions)
|
||||||
|
|
||||||
|
emotion = ''
|
||||||
|
mindistance = 10000000000000000000000.0
|
||||||
|
for state in self.centroids:
|
||||||
|
d = distance(self.centroids[state], original)
|
||||||
|
if d < mindistance:
|
||||||
|
mindistance = d
|
||||||
|
emotion = state
|
||||||
|
result = Emotion(onyx__hasEmotionCategory=emotion)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def convert(self, emotionSet, fromModel, toModel, params):
|
||||||
|
|
||||||
|
cf, ct = self.centroids_direction
|
||||||
|
logger.debug('{}\n{}\n{}\n{}'.format(emotionSet, fromModel, toModel, params))
|
||||||
|
e = EmotionSet()
|
||||||
|
if fromModel == cf:
|
||||||
|
e.onyx__hasEmotion.append(self._forward_conversion(emotionSet))
|
||||||
|
elif fromModel == ct:
|
||||||
|
for i in emotionSet.onyx__hasEmotion:
|
||||||
|
e.onyx__hasEmotion.append(self._backwards_conversion(i))
|
||||||
|
else:
|
||||||
|
raise Error('EMOTION MODEL NOT KNOWN')
|
||||||
|
yield e
|
@ -1,58 +0,0 @@
|
|||||||
from senpy.plugins import EmotionConversionPlugin
|
|
||||||
from senpy.models import EmotionSet, Emotion, Error
|
|
||||||
|
|
||||||
import logging
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
import math
|
|
||||||
|
|
||||||
|
|
||||||
class WNA2VAD(EmotionConversionPlugin):
|
|
||||||
|
|
||||||
def _ekman_to_vad(self, ekmanSet):
|
|
||||||
"""Sum the VAD value of all categories found."""
|
|
||||||
valence = 0
|
|
||||||
arousal = 0
|
|
||||||
dominance = 0
|
|
||||||
for e in ekmanSet.onyx__hasEmotion:
|
|
||||||
category = e.onyx__hasEmotionCategory
|
|
||||||
centroid = self.centroids[category]
|
|
||||||
valence += centroid['V']
|
|
||||||
arousal += centroid['A']
|
|
||||||
dominance += centroid['D']
|
|
||||||
e = Emotion({'emoml:valence': valence,
|
|
||||||
'emoml:arousal': arousal,
|
|
||||||
'emoml:potency': dominance})
|
|
||||||
return e
|
|
||||||
|
|
||||||
def _vad_to_ekman(self, VADEmotion):
|
|
||||||
"""Find the closest category"""
|
|
||||||
V = VADEmotion['emoml:valence']
|
|
||||||
A = VADEmotion['emoml:arousal']
|
|
||||||
D = VADEmotion['emoml:potency']
|
|
||||||
emotion = ''
|
|
||||||
value = 10000000000000000000000.0
|
|
||||||
for state in self.centroids:
|
|
||||||
valence = V - self.centroids[state]['V']
|
|
||||||
arousal = A - self.centroids[state]['A']
|
|
||||||
dominance = D - self.centroids[state]['D']
|
|
||||||
new_value = math.sqrt((valence**2) +
|
|
||||||
(arousal**2) +
|
|
||||||
(dominance**2))
|
|
||||||
if new_value < value:
|
|
||||||
value = new_value
|
|
||||||
emotion = state
|
|
||||||
result = Emotion(onyx__hasEmotionCategory=emotion)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def convert(self, emotionSet, fromModel, toModel, params):
|
|
||||||
logger.debug('{}\n{}\n{}\n{}'.format(emotionSet, fromModel, toModel, params))
|
|
||||||
e = EmotionSet()
|
|
||||||
if fromModel == 'emoml:big6':
|
|
||||||
e.onyx__hasEmotion.append(self._ekman_to_vad(emotionSet))
|
|
||||||
elif fromModel == 'emoml:fsre-dimensions':
|
|
||||||
for i in emotionSet.onyx__hasEmotion:
|
|
||||||
e.onyx__hasEmotion.append(self._vad_to_ekman(i))
|
|
||||||
else:
|
|
||||||
raise Error('EMOTION MODEL NOT KNOWN')
|
|
||||||
yield e
|
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: Ekman2VAD
|
name: Ekman2VAD
|
||||||
module: ekman2vad
|
module: senpy.plugins.conversion.centroids
|
||||||
description: Plugin to convert emotion sets from Ekman to VAD
|
description: Plugin to convert emotion sets from Ekman to VAD
|
||||||
version: 0.1
|
version: 0.1
|
||||||
onyx:doesConversion:
|
onyx:doesConversion:
|
||||||
@ -29,6 +29,9 @@ centroids:
|
|||||||
A: 5.21
|
A: 5.21
|
||||||
D: 2.82
|
D: 2.82
|
||||||
V: 2.21
|
V: 2.21
|
||||||
|
centroids_direction:
|
||||||
|
- emoml:big6
|
||||||
|
- emoml:fsre-dimensions
|
||||||
aliases:
|
aliases:
|
||||||
A: emoml:arousal
|
A: emoml:arousal
|
||||||
V: emoml:valence
|
V: emoml:valence
|
||||||
|
Loading…
Reference in New Issue
Block a user