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:
commit
c9bc485535
@ -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
|
||||||
|
1
Makefile
1
Makefile
@ -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=""
|
||||||
|
0
senpy/plugins/conversion/emotion/__init__.py
Normal file
0
senpy/plugins/conversion/emotion/__init__.py
Normal 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):
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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'
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
Loading…
Reference in New Issue
Block a user