mirror of
https://github.com/gsi-upm/senpy
synced 2024-11-22 08:12:27 +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))
|
||||
|
||||
dev-%:
|
||||
@docker start $(NAME)-dev || (\
|
||||
@docker start $(NAME)-dev$* || (\
|
||||
$(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)
|
||||
|
||||
|
@ -17,7 +17,7 @@ import copy
|
||||
import fnmatch
|
||||
import inspect
|
||||
import sys
|
||||
import imp
|
||||
import importlib
|
||||
import logging
|
||||
import traceback
|
||||
import yaml
|
||||
@ -181,7 +181,7 @@ class Senpy(object):
|
||||
newentries = []
|
||||
for i in resp.entries:
|
||||
if output == "full":
|
||||
newemotions = copy.copy(i.emotions)
|
||||
newemotions = copy.deepcopy(i.emotions)
|
||||
else:
|
||||
newemotions = []
|
||||
for j in i.emotions:
|
||||
@ -303,6 +303,13 @@ class Senpy(object):
|
||||
logger.info('Installing requirements: ' + str(requirements))
|
||||
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
|
||||
def _load_plugin_from_info(cls, info, root):
|
||||
if not cls.validate_info(info):
|
||||
@ -310,11 +317,10 @@ class Senpy(object):
|
||||
return None, None
|
||||
module = info["module"]
|
||||
name = info["name"]
|
||||
sys.path.append(root)
|
||||
(fp, pathname, desc) = imp.find_module(module, [root, ])
|
||||
|
||||
cls._install_deps(info)
|
||||
tmp = imp.load_module(module, fp, pathname, desc)
|
||||
sys.path.remove(root)
|
||||
tmp = cls._load_module(module, root)
|
||||
|
||||
candidate = None
|
||||
for _, obj in inspect.getmembers(tmp):
|
||||
if inspect.isclass(obj) and inspect.getmodule(obj) == tmp:
|
||||
|
@ -7,7 +7,7 @@ import pickle
|
||||
import logging
|
||||
import tempfile
|
||||
import copy
|
||||
from . import models
|
||||
from .. import models
|
||||
|
||||
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
|
||||
module: ekman2vad
|
||||
module: senpy.plugins.conversion.centroids
|
||||
description: Plugin to convert emotion sets from Ekman to VAD
|
||||
version: 0.1
|
||||
onyx:doesConversion:
|
||||
@ -29,6 +29,9 @@ centroids:
|
||||
A: 5.21
|
||||
D: 2.82
|
||||
V: 2.21
|
||||
centroids_direction:
|
||||
- emoml:big6
|
||||
- emoml:fsre-dimensions
|
||||
aliases:
|
||||
A: emoml:arousal
|
||||
V: emoml:valence
|
||||
|
Loading…
Reference in New Issue
Block a user