1
0
mirror of https://github.com/gsi-upm/senpy synced 2024-11-21 15:52:28 +00:00

Merge branch '36-estimate-vad'

This commit is contained in:
J. Fernando Sánchez 2017-06-12 20:10:21 +02:00
commit c9bc485535
8 changed files with 110 additions and 24 deletions

View File

@ -84,7 +84,15 @@ deploy:
only: only:
- master - master
clean_docker : push-github:
stage: deploy
script:
- make -e push-github
only:
- master
- triggers
clean :
stage: clean stage: clean
script: script:
- make -e clean - make -e clean

View File

@ -12,6 +12,7 @@ DEVPORT=5000
TARNAME=$(NAME)-$(VERSION).tar.gz TARNAME=$(NAME)-$(VERSION).tar.gz
action="test-${PYMAIN}" action="test-${PYMAIN}"
GITHUB_REPO=git@github.com:gsi-upm/senpy.git
KUBE_CA_PEM_FILE="" KUBE_CA_PEM_FILE=""
KUBE_URL="" KUBE_URL=""

View File

@ -32,36 +32,58 @@ class CentroidConversion(EmotionConversionPlugin):
nv1[aliases.get(k2, k2)] = v2 nv1[aliases.get(k2, k2)] = v2
ncentroids[aliases.get(k1, k1)] = nv1 ncentroids[aliases.get(k1, k1)] = nv1
info['centroids'] = ncentroids info['centroids'] = ncentroids
super(CentroidConversion, self).__init__(info) super(CentroidConversion, self).__init__(info)
self.dimensions = set()
for c in self.centroids.values():
self.dimensions.update(c.keys())
self.neutralPoints = self.get("neutralPoints", dict())
if not self.neutralPoints:
for i in self.dimensions:
self.neutralPoints[i] = self.get("neutralValue", 0)
def _forward_conversion(self, original): def _forward_conversion(self, original):
"""Sum the VAD value of all categories found.""" """Sum the VAD value of all categories found weighted by intensity.
Intensities are scaled by onyx:maxIntensityValue if it is present, else maxIntensityValue
is assumed to be one. Emotion entries that do not have onxy:hasEmotionIntensity specified
are assumed to have maxIntensityValue. Emotion entries that do not have
onyx:hasEmotionCategory specified are ignored."""
res = Emotion() res = Emotion()
maxIntensity = float(original.get("onyx:maxIntensityValue", 1))
for e in original.onyx__hasEmotion: for e in original.onyx__hasEmotion:
category = e.onyx__hasEmotionCategory category = e.get("onyx:hasEmotionCategory", None)
if category in self.centroids: if not category:
for dim, value in self.centroids[category].items(): continue
try: intensity = e.get("onyx:hasEmotionIntensity", maxIntensity) / maxIntensity
res[dim] += value if not intensity:
except Exception: continue
res[dim] = value centroid = self.centroids.get(category, None)
if centroid:
for dim, value in centroid.items():
neutral = self.neutralPoints[dim]
if dim not in res:
res[dim] = 0
res[dim] += (value - neutral) * intensity + neutral
return res return res
def _backwards_conversion(self, original): def _backwards_conversion(self, original):
"""Find the closest category""" """Find the closest category"""
dimensions = list(self.centroids.values())[0] centroids = self.centroids
neutralPoints = self.neutralPoints
dimensions = self.dimensions
def distance(e1, e2): def distance_k(centroid, original, k):
return sum((e1[k] - e2.get(k, 0)) for k in dimensions) # k component of the distance between the value and a given centroid
return (centroid.get(k, neutralPoints[k]) - original.get(k, neutralPoints[k]))**2
def distance(centroid):
return sum(distance_k(centroid, original, k) for k in dimensions)
emotion = min(centroids, key=lambda x: distance(centroids[x]))
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) result = Emotion(onyx__hasEmotionCategory=emotion)
result.onyx__algorithmConfidence = distance(centroids[emotion])
return result return result
def convert(self, emotionSet, fromModel, toModel, params): def convert(self, emotionSet, fromModel, toModel, params):

View File

@ -1,6 +1,6 @@
--- ---
name: Ekman2FSRE name: Ekman2FSRE
module: senpy.plugins.conversion.centroids module: senpy.plugins.conversion.emotion.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
# No need to specify onyx:doesConversion because centroids.py adds it automatically from centroids_direction # No need to specify onyx:doesConversion because centroids.py adds it automatically from centroids_direction

View File

@ -1,9 +1,14 @@
--- ---
name: Ekman2PAD name: Ekman2PAD
module: senpy.plugins.conversion.centroids module: senpy.plugins.conversion.emotion.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
# No need to specify onyx:doesConversion because centroids.py adds it automatically from centroids_direction # No need to specify onyx:doesConversion because centroids.py adds it automatically from centroids_direction
origin:
# Point in VAD space with no emotion (aka Neutral)
A: 5.0
D: 5.0
V: 5.0
centroids: centroids:
anger: anger:
A: 6.95 A: 6.95
@ -36,4 +41,4 @@ aliases: # These are aliases for any key in the centroid, to avoid repeating a l
disgust: emoml:big6disgust disgust: emoml:big6disgust
fear: emoml:big6fear fear: emoml:big6fear
happiness: emoml:big6happiness happiness: emoml:big6happiness
sadness: emoml:big6sadness sadness: emoml:big6sadness

View File

@ -11,7 +11,7 @@ def read_version(versionfile=DEFAULT_FILE):
try: try:
with open(versionfile) as f: with open(versionfile) as f:
return f.read().strip() return f.read().strip()
except IOError: except IOError: # pragma: no cover
logger.error('Running an unknown version of senpy. Be careful!.') logger.error('Running an unknown version of senpy. Be careful!.')
return '0.0' return '0.0'

View File

@ -6,8 +6,9 @@ import shutil
import tempfile import tempfile
from unittest import TestCase from unittest import TestCase
from senpy.models import Results, Entry from senpy.models import Results, Entry, EmotionSet, Emotion
from senpy.plugins import SentimentPlugin, ShelfMixin from senpy.plugins import SentimentPlugin, ShelfMixin
from senpy.plugins.conversion.emotion.centroids import CentroidConversion
class ShelfDummyPlugin(SentimentPlugin, ShelfMixin): class ShelfDummyPlugin(SentimentPlugin, ShelfMixin):
@ -152,3 +153,52 @@ class PluginsTest(TestCase):
} }
}) })
assert 'example' in a.extra_params assert 'example' in a.extra_params
def test_conversion_centroids(self):
info = {
"name": "CentroidTest",
"description": "Centroid test",
"version": 0,
"centroids": {
"c1": {"V1": 0.5,
"V2": 0.5},
"c2": {"V1": -0.5,
"V2": 0.5},
"c3": {"V1": -0.5,
"V2": -0.5},
"c4": {"V1": 0.5,
"V2": -0.5}},
"aliases": {
"V1": "X-dimension",
"V2": "Y-dimension"
},
"centroids_direction": ["emoml:big6", "emoml:fsre-dimensions"]
}
c = CentroidConversion(info)
es1 = EmotionSet()
e1 = Emotion()
e1.onyx__hasEmotionCategory = "c1"
es1.onyx__hasEmotion.append(e1)
res = c._forward_conversion(es1)
assert res["X-dimension"] == 0.5
assert res["Y-dimension"] == 0.5
e2 = Emotion()
e2.onyx__hasEmotionCategory = "c2"
es1.onyx__hasEmotion.append(e2)
res = c._forward_conversion(es1)
assert res["X-dimension"] == 0
assert res["Y-dimension"] == 1
e = Emotion()
e["X-dimension"] = -0.2
e["Y-dimension"] = -0.3
res = c._backwards_conversion(e)
assert res["onyx:hasEmotionCategory"] == "c3"
e = Emotion()
e["X-dimension"] = -0.2
e["Y-dimension"] = 0.3
res = c._backwards_conversion(e)
assert res["onyx:hasEmotionCategory"] == "c2"