1
0
mirror of https://github.com/gsi-upm/senpy synced 2025-10-18 17:28:28 +00:00

Compare commits

...

8 Commits

Author SHA1 Message Date
J. Fernando Sánchez
c5a2cf23cb typo docs/readme 2019-09-02 15:58:10 +02:00
J. Fernando Sánchez
49a183aeb6 typo readme 2019-09-02 15:43:35 +02:00
J. Fernando Sánchez
3088d9474a compatibility notice 2019-09-02 15:39:18 +02:00
J. Fernando Sánchez
0f5bc514b7 add windows+mac tests in travis 2019-09-02 13:56:30 +02:00
J. Fernando Sánchez
7ae493b3f3 Minor fix setup and docs 2019-07-18 11:40:41 +02:00
J. Fernando Sánchez
435d107677 Add headers and minor fixes 2019-07-17 16:29:30 +02:00
J. Fernando Sánchez
c4321dc500 Update schema examples 2019-04-09 15:51:20 +02:00
J. Fernando Sánchez
3bd3c87af4 Add license to manifest 2019-04-04 19:21:58 +02:00
77 changed files with 3750 additions and 2699 deletions

View File

@@ -1,15 +1,43 @@
sudo: required
services:
- docker
language: python
env:
- PYV=3.4
- PYV=3.5
- PYV=3.6
- PYV=3.7
# - PYV=3.3 # Apt fails in this docker image
# run nosetests - Tests
script: make test-$PYV
matrix:
allow_failures:
# Windows is experimental in Travis.
# As of this writing, senpy installs but hangs on tests that use the flask test client (e.g. blueprints)
- os: windows
include:
- os: linux
language: python
python: 3.4
before_install:
- pip install --upgrade --force-reinstall pandas
- os: linux
language: python
python: 3.5
- os: linux
language: python
python: 3.6
- os: linux
language: python
python: 3.7
- os: osx
language: generic
addons:
homebrew:
# update: true
packages: python3
before_install:
- python3 -m pip install --upgrade virtualenv
- virtualenv -p python3 --system-site-packages "$HOME/venv"
- source "$HOME/venv/bin/activate"
- os: windows
language: bash
before_install:
- choco install -y python3
- python -m pip install --upgrade pip
env: PATH=/c/Python37:/c/Python37/Scripts:$PATH
# command to run tests
# 'python' points to Python 2.7 on macOS but points to Python 3.7 on Linux and Windows
# 'python3' is a 'command not found' error on Windows but 'py' works on Windows only
script:
- python3 setup.py test || python setup.py test

View File

@@ -4,8 +4,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [1.0.1]
### Added
* License headers
* Description for PyPI (setup.py)
### Changed
* The evaluation tab shows datasets inline, and a tooltip shows the number of instances
* The docs should be clearer now
## [1.0.0]
### Fixed
* Restored hash changing function in `main.js`

View File

@@ -2,9 +2,10 @@ include requirements.txt
include test-requirements.txt
include extra-requirements.txt
include README.rst
include LICENSE.txt
include senpy/VERSION
graft senpy/plugins
graft senpy/schemas
graft senpy/templates
graft senpy/static
graft img
graft img

View File

@@ -2,23 +2,21 @@
:width: 100%
:target: http://senpy.gsi.upm.es
.. image:: https://travis-ci.org/gsi-upm/senpy.svg?branch=master
:target: https://travis-ci.org/gsi-upm/senpy
.. image:: https://lab.gsi.upm.es/senpy/senpy/badges/master/pipeline.svg
:target: https://lab.gsi.upm.es/senpy/senpy/commits/master
.. image:: https://lab.gsi.upm.es/senpy/senpy/badges/master/coverage.svg
:target: https://lab.gsi.upm.es/senpy/senpy/commits/master
.. image:: https://readthedocs.org/projects/senpy/badge/?version=latest
:target: http://senpy.readthedocs.io/en/latest/
.. image:: https://badge.fury.io/py/senpy.svg
:target: https://badge.fury.io/py/senpy
.. image:: https://travis-ci.org/gsi-upm/senpy.svg
:target: https://github.com/gsi-upm/senpy/senpy/tree/master
.. image:: https://img.shields.io/pypi/l/requests.svg
:target: https://lab.gsi.upm.es/senpy/senpy/
:target: https://lab.gsi.upm.es/senpy/senpy/
Senpy lets you create sentiment analysis web services easily, fast and using a well known API.
As a bonus, senpy services use semantic vocabularies (e.g. `NIF <http://persistence.uni-leipzig.org/nlp2rdf/>`_, `Marl <http://www.gsi.dit.upm.es/ontologies/marl>`_, `Onyx <http://www.gsi.dit.upm.es/ontologies/onyx>`_) and formats (turtle, JSON-LD, xml-rdf).
As a bonus, Senpy services use semantic vocabularies (e.g. `NIF <http://persistence.uni-leipzig.org/nlp2rdf/>`_, `Marl <http://www.gsi.dit.upm.es/ontologies/marl>`_, `Onyx <http://www.gsi.dit.upm.es/ontologies/onyx>`_) and formats (turtle, JSON-LD, xml-rdf).
Have you ever wanted to turn your sentiment analysis algorithms into a service?
With senpy, now you can.
With Senpy, now you can.
It provides all the tools so you just have to worry about improving your algorithms:
`See it in action. <http://senpy.gsi.upm.es/>`_
@@ -43,20 +41,36 @@ Alternatively, you can use the development version:
cd senpy
pip install --user .
If you want to install senpy globally, use sudo instead of the ``--user`` flag.
If you want to install Senpy globally, use sudo instead of the ``--user`` flag.
Docker Image
************
Build the image or use the pre-built one: ``docker run -ti -p 5000:5000 gsiupm/senpy``.
To add custom plugins, add a volume and tell senpy where to find the plugins: ``docker run -ti -p 5000:5000 -v <PATH OF PLUGINS>:/plugins gsiupm/senpy -f /plugins``
To add custom plugins, add a volume and tell Senpy where to find the plugins: ``docker run -ti -p 5000:5000 -v <PATH OF PLUGINS>:/plugins gsiupm/senpy -f /plugins``
Compatibility
-------------
Senpy should run on any major operating system.
Its code is pure Python, and the only limitations are imposed by its dependencies (e.g., nltk, pandas).
Currently, the CI/CD pipeline tests the code on:
* GNU/Linux with Python versions 3.4, 3.5, 3.6 and 3.7
* MacOS and homebrew's python3
* Windows 10 and chocolatey's python3
The latest PyPI package is verified to install on Ubuntu, Debian and Arch Linux.
If you have trouble installing Senpy on your platform, see `Having problems?`_.
Developing
----------
Developing/debugging
********************
Running/debugging
*****************
This command will run the senpy container using the latest image available, mounting your current folder so you get your latest code:
.. code:: bash
@@ -119,7 +133,7 @@ or, alternatively:
This will create a server with any modules found in the current path.
For more options, see the `--help` page.
Alternatively, you can use the modules included in senpy to build your own application.
Alternatively, you can use the modules included in Senpy to build your own application.
Deploying on Heroku
-------------------
@@ -127,9 +141,6 @@ Use a free heroku instance to share your service with the world.
Just use the example Procfile in this repository, or build your own.
`DEMO on heroku <http://senpy.herokuapp.com>`_
For more information, check out the `documentation <http://senpy.readthedocs.org>`_.
------------------------------------------------------------------------------------
@@ -144,6 +155,17 @@ Instead, the maintainers will focus their efforts on keeping the codebase compat
We apologize for the inconvenience.
Having problems?
----------------
Please, file a new issue `on GitHub <https://github.com/gsi-upm/senpy/issues>`_ including enough details to reproduce the bug, including:
* Operating system
* Version of Senpy (or docker tag)
* Installed libraries
* Relevant logs
* A simple code example
Acknowledgement
---------------
This development has been partially funded by the European Union through the MixedEmotions Project (project number H2020 655632), as part of the `RIA ICT 15 Big data and Open Data Innovation and take-up` programme.

File diff suppressed because it is too large Load Diff

592
docs/Evaluation.ipynb Normal file
View File

@@ -0,0 +1,592 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Evaluating Services"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Sentiment analysis plugins can also be evaluated on a series of pre-defined datasets.\n",
"This can be done in three ways: through the Web UI (playground), through the web API and programmatically.\n",
"\n",
"Regardless of the way you perform the evaluation, you will need to specify a plugin (service) that you want to evaluate, and a series of datasets on which it should be evaluated.\n",
"\n",
"to evaluate a plugin on a dataset, senpy use the plugin to predict the sentiment in each entry in the dataset.\n",
"These predictions are compared with the expected values to produce several metrics, such as: accuracy, precision and f1-score.\n",
"\n",
"**note**: the evaluation process might take long for plugins that use external services, such as `sentiment140`.\n",
"\n",
"**note**: plugins are assumed to be pre-trained and invariant. i.e., the prediction for an entry should "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Web UI (Playground)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The playground should contain a tab for Evaluation, where you can select any plugin that can be evaluated, and the set of datasets that you want to test the plugin on.\n",
"\n",
"For example, the image below shows the results of the `sentiment-vader` plugin on the `vader` and `sts` datasets:\n",
"\n",
"\n",
"![](eval_table.png)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Web API"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The api exposes an endpoint (`/evaluate`), which accents the plugin and the set of datasets on which it should be evaluated."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The following code is not necessary, but it will display the results better:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here is a simple call using the requests library:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<style>.output_html .hll { background-color: #ffffcc }\n",
".output_html { background: #f8f8f8; }\n",
".output_html .c { color: #408080; font-style: italic } /* Comment */\n",
".output_html .err { border: 1px solid #FF0000 } /* Error */\n",
".output_html .k { color: #008000; font-weight: bold } /* Keyword */\n",
".output_html .o { color: #666666 } /* Operator */\n",
".output_html .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
".output_html .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
".output_html .cp { color: #BC7A00 } /* Comment.Preproc */\n",
".output_html .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
".output_html .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
".output_html .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
".output_html .gd { color: #A00000 } /* Generic.Deleted */\n",
".output_html .ge { font-style: italic } /* Generic.Emph */\n",
".output_html .gr { color: #FF0000 } /* Generic.Error */\n",
".output_html .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
".output_html .gi { color: #00A000 } /* Generic.Inserted */\n",
".output_html .go { color: #888888 } /* Generic.Output */\n",
".output_html .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
".output_html .gs { font-weight: bold } /* Generic.Strong */\n",
".output_html .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
".output_html .gt { color: #0044DD } /* Generic.Traceback */\n",
".output_html .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
".output_html .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
".output_html .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
".output_html .kp { color: #008000 } /* Keyword.Pseudo */\n",
".output_html .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
".output_html .kt { color: #B00040 } /* Keyword.Type */\n",
".output_html .m { color: #666666 } /* Literal.Number */\n",
".output_html .s { color: #BA2121 } /* Literal.String */\n",
".output_html .na { color: #7D9029 } /* Name.Attribute */\n",
".output_html .nb { color: #008000 } /* Name.Builtin */\n",
".output_html .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
".output_html .no { color: #880000 } /* Name.Constant */\n",
".output_html .nd { color: #AA22FF } /* Name.Decorator */\n",
".output_html .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
".output_html .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
".output_html .nf { color: #0000FF } /* Name.Function */\n",
".output_html .nl { color: #A0A000 } /* Name.Label */\n",
".output_html .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
".output_html .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
".output_html .nv { color: #19177C } /* Name.Variable */\n",
".output_html .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
".output_html .w { color: #bbbbbb } /* Text.Whitespace */\n",
".output_html .mb { color: #666666 } /* Literal.Number.Bin */\n",
".output_html .mf { color: #666666 } /* Literal.Number.Float */\n",
".output_html .mh { color: #666666 } /* Literal.Number.Hex */\n",
".output_html .mi { color: #666666 } /* Literal.Number.Integer */\n",
".output_html .mo { color: #666666 } /* Literal.Number.Oct */\n",
".output_html .sa { color: #BA2121 } /* Literal.String.Affix */\n",
".output_html .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
".output_html .sc { color: #BA2121 } /* Literal.String.Char */\n",
".output_html .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
".output_html .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
".output_html .s2 { color: #BA2121 } /* Literal.String.Double */\n",
".output_html .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
".output_html .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
".output_html .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
".output_html .sx { color: #008000 } /* Literal.String.Other */\n",
".output_html .sr { color: #BB6688 } /* Literal.String.Regex */\n",
".output_html .s1 { color: #BA2121 } /* Literal.String.Single */\n",
".output_html .ss { color: #19177C } /* Literal.String.Symbol */\n",
".output_html .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
".output_html .fm { color: #0000FF } /* Name.Function.Magic */\n",
".output_html .vc { color: #19177C } /* Name.Variable.Class */\n",
".output_html .vg { color: #19177C } /* Name.Variable.Global */\n",
".output_html .vi { color: #19177C } /* Name.Variable.Instance */\n",
".output_html .vm { color: #19177C } /* Name.Variable.Magic */\n",
".output_html .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;@context&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;http://senpy.gsi.upm.es/api/contexts/YXBpL2V2YWx1YXRlLz9hbGdvPXNlbnRpbWVudC12YWRlciZkYXRhc2V0PXZhZGVyJTJDc3RzJm91dGZvcm1hdD1qc29uLWxkIw%3D%3D&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;@type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;AggregatedEvaluation&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;senpy:evaluations&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
" <span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;@type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;Evaluation&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;evaluates&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;endpoint:plugins/sentiment-vader_0.1.1__vader&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;evaluatesOn&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;vader&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;metrics&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
" <span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;@type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;Accuracy&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;value&quot;</span><span class=\"p\">:</span> <span class=\"mf\">0.6907142857142857</span>\n",
" <span class=\"p\">},</span>\n",
" <span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;@type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;Precision_macro&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;value&quot;</span><span class=\"p\">:</span> <span class=\"mf\">0.34535714285714286</span>\n",
" <span class=\"p\">},</span>\n",
" <span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;@type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;Recall_macro&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;value&quot;</span><span class=\"p\">:</span> <span class=\"mf\">0.5</span>\n",
" <span class=\"p\">},</span>\n",
" <span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;@type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;F1_macro&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;value&quot;</span><span class=\"p\">:</span> <span class=\"mf\">0.40853400929446554</span>\n",
" <span class=\"p\">},</span>\n",
" <span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;@type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;F1_weighted&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;value&quot;</span><span class=\"p\">:</span> <span class=\"mf\">0.5643605528396403</span>\n",
" <span class=\"p\">},</span>\n",
" <span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;@type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;F1_micro&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;value&quot;</span><span class=\"p\">:</span> <span class=\"mf\">0.6907142857142857</span>\n",
" <span class=\"p\">},</span>\n",
" <span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;@type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;F1_macro&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;value&quot;</span><span class=\"p\">:</span> <span class=\"mf\">0.40853400929446554</span>\n",
" <span class=\"p\">}</span>\n",
" <span class=\"p\">]</span>\n",
" <span class=\"p\">},</span>\n",
" <span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;@type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;Evaluation&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;evaluates&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;endpoint:plugins/sentiment-vader_0.1.1__sts&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;evaluatesOn&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;sts&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;metrics&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
" <span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;@type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;Accuracy&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;value&quot;</span><span class=\"p\">:</span> <span class=\"mf\">0.3107177974434612</span>\n",
" <span class=\"p\">},</span>\n",
" <span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;@type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;Precision_macro&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;value&quot;</span><span class=\"p\">:</span> <span class=\"mf\">0.1553588987217306</span>\n",
" <span class=\"p\">},</span>\n",
" <span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;@type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;Recall_macro&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;value&quot;</span><span class=\"p\">:</span> <span class=\"mf\">0.5</span>\n",
" <span class=\"p\">},</span>\n",
" <span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;@type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;F1_macro&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;value&quot;</span><span class=\"p\">:</span> <span class=\"mf\">0.23705926481620407</span>\n",
" <span class=\"p\">},</span>\n",
" <span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;@type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;F1_weighted&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;value&quot;</span><span class=\"p\">:</span> <span class=\"mf\">0.14731706525451424</span>\n",
" <span class=\"p\">},</span>\n",
" <span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;@type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;F1_micro&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;value&quot;</span><span class=\"p\">:</span> <span class=\"mf\">0.3107177974434612</span>\n",
" <span class=\"p\">},</span>\n",
" <span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;@type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;F1_macro&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;value&quot;</span><span class=\"p\">:</span> <span class=\"mf\">0.23705926481620407</span>\n",
" <span class=\"p\">}</span>\n",
" <span class=\"p\">]</span>\n",
" <span class=\"p\">}</span>\n",
" <span class=\"p\">]</span>\n",
"<span class=\"p\">}</span>\n",
"</pre></div>\n"
],
"text/latex": [
"\\begin{Verbatim}[commandchars=\\\\\\{\\}]\n",
"\\PY{p}{\\PYZob{}}\n",
" \\PY{n+nt}{\\PYZdq{}@context\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}http://senpy.gsi.upm.es/api/contexts/YXBpL2V2YWx1YXRlLz9hbGdvPXNlbnRpbWVudC12YWRlciZkYXRhc2V0PXZhZGVyJTJDc3RzJm91dGZvcm1hdD1qc29uLWxkIw\\PYZpc{}3D\\PYZpc{}3D\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}@type\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}AggregatedEvaluation\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}senpy:evaluations\\PYZdq{}}\\PY{p}{:} \\PY{p}{[}\n",
" \\PY{p}{\\PYZob{}}\n",
" \\PY{n+nt}{\\PYZdq{}@type\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}Evaluation\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}evaluates\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}endpoint:plugins/sentiment\\PYZhy{}vader\\PYZus{}0.1.1\\PYZus{}\\PYZus{}vader\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}evaluatesOn\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}vader\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}metrics\\PYZdq{}}\\PY{p}{:} \\PY{p}{[}\n",
" \\PY{p}{\\PYZob{}}\n",
" \\PY{n+nt}{\\PYZdq{}@type\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}Accuracy\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}value\\PYZdq{}}\\PY{p}{:} \\PY{l+m+mf}{0.6907142857142857}\n",
" \\PY{p}{\\PYZcb{}}\\PY{p}{,}\n",
" \\PY{p}{\\PYZob{}}\n",
" \\PY{n+nt}{\\PYZdq{}@type\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}Precision\\PYZus{}macro\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}value\\PYZdq{}}\\PY{p}{:} \\PY{l+m+mf}{0.34535714285714286}\n",
" \\PY{p}{\\PYZcb{}}\\PY{p}{,}\n",
" \\PY{p}{\\PYZob{}}\n",
" \\PY{n+nt}{\\PYZdq{}@type\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}Recall\\PYZus{}macro\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}value\\PYZdq{}}\\PY{p}{:} \\PY{l+m+mf}{0.5}\n",
" \\PY{p}{\\PYZcb{}}\\PY{p}{,}\n",
" \\PY{p}{\\PYZob{}}\n",
" \\PY{n+nt}{\\PYZdq{}@type\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}F1\\PYZus{}macro\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}value\\PYZdq{}}\\PY{p}{:} \\PY{l+m+mf}{0.40853400929446554}\n",
" \\PY{p}{\\PYZcb{}}\\PY{p}{,}\n",
" \\PY{p}{\\PYZob{}}\n",
" \\PY{n+nt}{\\PYZdq{}@type\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}F1\\PYZus{}weighted\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}value\\PYZdq{}}\\PY{p}{:} \\PY{l+m+mf}{0.5643605528396403}\n",
" \\PY{p}{\\PYZcb{}}\\PY{p}{,}\n",
" \\PY{p}{\\PYZob{}}\n",
" \\PY{n+nt}{\\PYZdq{}@type\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}F1\\PYZus{}micro\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}value\\PYZdq{}}\\PY{p}{:} \\PY{l+m+mf}{0.6907142857142857}\n",
" \\PY{p}{\\PYZcb{}}\\PY{p}{,}\n",
" \\PY{p}{\\PYZob{}}\n",
" \\PY{n+nt}{\\PYZdq{}@type\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}F1\\PYZus{}macro\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}value\\PYZdq{}}\\PY{p}{:} \\PY{l+m+mf}{0.40853400929446554}\n",
" \\PY{p}{\\PYZcb{}}\n",
" \\PY{p}{]}\n",
" \\PY{p}{\\PYZcb{}}\\PY{p}{,}\n",
" \\PY{p}{\\PYZob{}}\n",
" \\PY{n+nt}{\\PYZdq{}@type\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}Evaluation\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}evaluates\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}endpoint:plugins/sentiment\\PYZhy{}vader\\PYZus{}0.1.1\\PYZus{}\\PYZus{}sts\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}evaluatesOn\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}sts\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}metrics\\PYZdq{}}\\PY{p}{:} \\PY{p}{[}\n",
" \\PY{p}{\\PYZob{}}\n",
" \\PY{n+nt}{\\PYZdq{}@type\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}Accuracy\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}value\\PYZdq{}}\\PY{p}{:} \\PY{l+m+mf}{0.3107177974434612}\n",
" \\PY{p}{\\PYZcb{}}\\PY{p}{,}\n",
" \\PY{p}{\\PYZob{}}\n",
" \\PY{n+nt}{\\PYZdq{}@type\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}Precision\\PYZus{}macro\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}value\\PYZdq{}}\\PY{p}{:} \\PY{l+m+mf}{0.1553588987217306}\n",
" \\PY{p}{\\PYZcb{}}\\PY{p}{,}\n",
" \\PY{p}{\\PYZob{}}\n",
" \\PY{n+nt}{\\PYZdq{}@type\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}Recall\\PYZus{}macro\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}value\\PYZdq{}}\\PY{p}{:} \\PY{l+m+mf}{0.5}\n",
" \\PY{p}{\\PYZcb{}}\\PY{p}{,}\n",
" \\PY{p}{\\PYZob{}}\n",
" \\PY{n+nt}{\\PYZdq{}@type\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}F1\\PYZus{}macro\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}value\\PYZdq{}}\\PY{p}{:} \\PY{l+m+mf}{0.23705926481620407}\n",
" \\PY{p}{\\PYZcb{}}\\PY{p}{,}\n",
" \\PY{p}{\\PYZob{}}\n",
" \\PY{n+nt}{\\PYZdq{}@type\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}F1\\PYZus{}weighted\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}value\\PYZdq{}}\\PY{p}{:} \\PY{l+m+mf}{0.14731706525451424}\n",
" \\PY{p}{\\PYZcb{}}\\PY{p}{,}\n",
" \\PY{p}{\\PYZob{}}\n",
" \\PY{n+nt}{\\PYZdq{}@type\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}F1\\PYZus{}micro\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}value\\PYZdq{}}\\PY{p}{:} \\PY{l+m+mf}{0.3107177974434612}\n",
" \\PY{p}{\\PYZcb{}}\\PY{p}{,}\n",
" \\PY{p}{\\PYZob{}}\n",
" \\PY{n+nt}{\\PYZdq{}@type\\PYZdq{}}\\PY{p}{:} \\PY{l+s+s2}{\\PYZdq{}F1\\PYZus{}macro\\PYZdq{}}\\PY{p}{,}\n",
" \\PY{n+nt}{\\PYZdq{}value\\PYZdq{}}\\PY{p}{:} \\PY{l+m+mf}{0.23705926481620407}\n",
" \\PY{p}{\\PYZcb{}}\n",
" \\PY{p}{]}\n",
" \\PY{p}{\\PYZcb{}}\n",
" \\PY{p}{]}\n",
"\\PY{p}{\\PYZcb{}}\n",
"\\end{Verbatim}\n"
],
"text/plain": [
"{\n",
" \"@context\": \"http://senpy.gsi.upm.es/api/contexts/YXBpL2V2YWx1YXRlLz9hbGdvPXNlbnRpbWVudC12YWRlciZkYXRhc2V0PXZhZGVyJTJDc3RzJm91dGZvcm1hdD1qc29uLWxkIw%3D%3D\",\n",
" \"@type\": \"AggregatedEvaluation\",\n",
" \"senpy:evaluations\": [\n",
" {\n",
" \"@type\": \"Evaluation\",\n",
" \"evaluates\": \"endpoint:plugins/sentiment-vader_0.1.1__vader\",\n",
" \"evaluatesOn\": \"vader\",\n",
" \"metrics\": [\n",
" {\n",
" \"@type\": \"Accuracy\",\n",
" \"value\": 0.6907142857142857\n",
" },\n",
" {\n",
" \"@type\": \"Precision_macro\",\n",
" \"value\": 0.34535714285714286\n",
" },\n",
" {\n",
" \"@type\": \"Recall_macro\",\n",
" \"value\": 0.5\n",
" },\n",
" {\n",
" \"@type\": \"F1_macro\",\n",
" \"value\": 0.40853400929446554\n",
" },\n",
" {\n",
" \"@type\": \"F1_weighted\",\n",
" \"value\": 0.5643605528396403\n",
" },\n",
" {\n",
" \"@type\": \"F1_micro\",\n",
" \"value\": 0.6907142857142857\n",
" },\n",
" {\n",
" \"@type\": \"F1_macro\",\n",
" \"value\": 0.40853400929446554\n",
" }\n",
" ]\n",
" },\n",
" {\n",
" \"@type\": \"Evaluation\",\n",
" \"evaluates\": \"endpoint:plugins/sentiment-vader_0.1.1__sts\",\n",
" \"evaluatesOn\": \"sts\",\n",
" \"metrics\": [\n",
" {\n",
" \"@type\": \"Accuracy\",\n",
" \"value\": 0.3107177974434612\n",
" },\n",
" {\n",
" \"@type\": \"Precision_macro\",\n",
" \"value\": 0.1553588987217306\n",
" },\n",
" {\n",
" \"@type\": \"Recall_macro\",\n",
" \"value\": 0.5\n",
" },\n",
" {\n",
" \"@type\": \"F1_macro\",\n",
" \"value\": 0.23705926481620407\n",
" },\n",
" {\n",
" \"@type\": \"F1_weighted\",\n",
" \"value\": 0.14731706525451424\n",
" },\n",
" {\n",
" \"@type\": \"F1_micro\",\n",
" \"value\": 0.3107177974434612\n",
" },\n",
" {\n",
" \"@type\": \"F1_macro\",\n",
" \"value\": 0.23705926481620407\n",
" }\n",
" ]\n",
" }\n",
" ]\n",
"}"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import requests\n",
"from IPython.display import Code\n",
"\n",
"endpoint = 'http://senpy.gsi.upm.es/api'\n",
"res = requests.get(f'{endpoint}/evaluate',\n",
" params={\"algo\": \"sentiment-vader\",\n",
" \"dataset\": \"vader,sts\",\n",
" 'outformat': 'json-ld'\n",
" })\n",
"Code(res.text, language='json')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Programmatically (expert)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A third option is to evaluate plugins manually without launching the server.\n",
"\n",
"This option is particularly interesting for advanced users that want faster iterations and evaluation results, and for automation.\n",
"\n",
"We would first need an instance of a plugin.\n",
"In this example we will use the Sentiment140 plugin that is included in every senpy installation:"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"from senpy.plugins.sentiment import sentiment140_plugin"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
"s140 = sentiment140_plugin.Sentiment140()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then, we need to know what datasets are available.\n",
"We can list all datasets and basic stats (e.g., number of instances and labels used) like this:"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"vader {'instances': 4200, 'labels': [1, -1]}\n",
"sts {'instances': 4200, 'labels': [1, -1]}\n",
"imdb_unsup {'instances': 50000, 'labels': [1, -1]}\n",
"imdb {'instances': 50000, 'labels': [1, -1]}\n",
"sst {'instances': 11855, 'labels': [1, -1]}\n",
"multidomain {'instances': 38548, 'labels': [1, -1]}\n",
"sentiment140 {'instances': 1600000, 'labels': [1, -1]}\n",
"semeval07 {'instances': 'None', 'labels': [1, -1]}\n",
"semeval14 {'instances': 7838, 'labels': [1, -1]}\n",
"pl04 {'instances': 4000, 'labels': [1, -1]}\n",
"pl05 {'instances': 10662, 'labels': [1, -1]}\n",
"semeval13 {'instances': 6259, 'labels': [1, -1]}\n"
]
}
],
"source": [
"from senpy.gsitk_compat import datasets\n",
"for k, d in datasets.items():\n",
" print(k, d['stats'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, we will evaluate our plugin in one of the smallest datasets, `sts`:"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/plain": [
"[{\n",
" \"@type\": \"Evaluation\",\n",
" \"evaluates\": \"endpoint:plugins/sentiment140_0.2\",\n",
" \"evaluatesOn\": \"sts\",\n",
" \"metrics\": [\n",
" {\n",
" \"@type\": \"Accuracy\",\n",
" \"value\": 0.872173058013766\n",
" },\n",
" {\n",
" \"@type\": \"Precision_macro\",\n",
" \"value\": 0.9035254323131467\n",
" },\n",
" {\n",
" \"@type\": \"Recall_macro\",\n",
" \"value\": 0.8021249029415483\n",
" },\n",
" {\n",
" \"@type\": \"F1_macro\",\n",
" \"value\": 0.8320673712021136\n",
" },\n",
" {\n",
" \"@type\": \"F1_weighted\",\n",
" \"value\": 0.8631351567604358\n",
" },\n",
" {\n",
" \"@type\": \"F1_micro\",\n",
" \"value\": 0.872173058013766\n",
" },\n",
" {\n",
" \"@type\": \"F1_macro\",\n",
" \"value\": 0.8320673712021136\n",
" }\n",
" ]\n",
" }]"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"s140.evaluate(['sts', ])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
},
"toc": {
"colors": {
"hover_highlight": "#DAA520",
"running_highlight": "#FF0000",
"selected_highlight": "#FFD700"
},
"moveMenuLeft": true,
"nav_menu": {
"height": "68px",
"width": "252px"
},
"navigate_menu": true,
"number_sections": true,
"sideBar": true,
"threshold": 4,
"toc_cell": false,
"toc_section_display": "block",
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 1
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,152 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Senpy in 1 minute\n",
"\n",
"This mini-tutorial only shows how to annotate with a service.\n",
"We will use the [demo server](http://senpy.gsi.upm.es), which runs some open source plugins for sentiment and emotion analysis."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Annotating with senpy is as simple as issuing an HTTP request to the API using your favourite tool.\n",
"This is just an example using curl:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{\r\n",
" \"@context\": \"http://senpy.gsi.upm.es/api/contexts/YXBpL3NlbnRpbWVudDE0MD8j\",\r\n",
" \"@type\": \"Results\",\r\n",
" \"entries\": [\r\n",
" {\r\n",
" \"@id\": \"prefix:\",\r\n",
" \"@type\": \"Entry\",\r\n",
" \"marl:hasOpinion\": [\r\n",
" {\r\n",
" \"@type\": \"Sentiment\",\r\n",
" \"marl:hasPolarity\": \"marl:Positive\",\r\n",
" \"prov:wasGeneratedBy\": \"prefix:Analysis_1554389334.6431913\"\r\n",
" }\r\n",
" ],\r\n",
" \"nif:isString\": \"Senpy is awesome\",\r\n",
" \"onyx:hasEmotionSet\": []\r\n",
" }\r\n",
" ]\r\n",
"}"
]
}
],
"source": [
"!curl \"http://senpy.gsi.upm.es/api/sentiment140\" --data-urlencode \"input=Senpy is awesome\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Congratulations**, you've used your first senpy service!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here is the equivalent using the `requests` library:"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{\n",
" \"@context\": \"http://senpy.gsi.upm.es/api/contexts/YXBpL3NlbnRpbWVudDE0MD9pbnB1dD1TZW5weStpcythd2Vzb21lIw%3D%3D\",\n",
" \"@type\": \"Results\",\n",
" \"entries\": [\n",
" {\n",
" \"@id\": \"prefix:\",\n",
" \"@type\": \"Entry\",\n",
" \"marl:hasOpinion\": [\n",
" {\n",
" \"@type\": \"Sentiment\",\n",
" \"marl:hasPolarity\": \"marl:Positive\",\n",
" \"prov:wasGeneratedBy\": \"prefix:Analysis_1554389335.9803226\"\n",
" }\n",
" ],\n",
" \"nif:isString\": \"Senpy is awesome\",\n",
" \"onyx:hasEmotionSet\": []\n",
" }\n",
" ]\n",
"}\n"
]
}
],
"source": [
"import requests\n",
"res = requests.get('http://senpy.gsi.upm.es/api/sentiment140',\n",
" params={\"input\": \"Senpy is awesome\",})\n",
"print(res.text)"
]
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
},
"toc": {
"colors": {
"hover_highlight": "#DAA520",
"running_highlight": "#FF0000",
"selected_highlight": "#FFD700"
},
"moveMenuLeft": true,
"nav_menu": {
"height": "68px",
"width": "252px"
},
"navigate_menu": true,
"number_sections": true,
"sideBar": true,
"threshold": 4,
"toc_cell": false,
"toc_section_display": "block",
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 1
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +0,0 @@
Advanced usage
--------------
.. toctree::
:maxdepth: 1
server-cli
conversion
commandline
development

View File

@@ -1,10 +0,0 @@
Command line
============
Although the main use of senpy is to publish services, the tool can also be used locally to analyze text in the command line.
This is a short video demonstration:
.. image:: https://asciinema.org/a/9uwef1ghkjk062cw2t4mhzpyk.png
:width: 100%
:target: https://asciinema.org/a/9uwef1ghkjk062cw2t4mhzpyk
:alt: CLI demo

View File

@@ -130,6 +130,7 @@ html_theme_options = {
'github_user': 'gsi-upm',
'github_repo': 'senpy',
'github_banner': True,
'sidebar_collapse': True,
}
@@ -292,11 +293,10 @@ texinfo_documents = [
#texinfo_no_detailmenu = False
nbsphinx_prolog = """
.. note:: This page has been auto-generated from a Jupyter notebook using nbsphinx_.
.. note:: This is an `auto-generated <https://nbsphinx.readthedocs.io>`_ static view of a Jupyter notebook.
The original source is available at: https://github.com/gsi-upm/senpy/tree/master/docs//{{ env.doc2path(env.docname, base=None) }}
To run the code examples in your computer, you may download the original notebook from the repository: https://github.com/gsi-upm/senpy/tree/master/docs/{{ env.doc2path(env.docname, base=None) }}
.. _nbsphinx: https://nbsphinx.readthedocs.io/
----
"""

View File

@@ -1,93 +1,152 @@
Conversion
----------
Automatic Model Conversion
--------------------------
Senpy includes experimental support for emotion/sentiment conversion plugins.
Senpy includes support for emotion and sentiment conversion.
When a user requests a specific model, senpy will choose a strategy to convert the model that the service usually outputs and the model requested by the user.
Out of the box, senpy can convert from the `emotionml:pad` (pleasure-arousal-dominance) dimensional model to `emoml:big6` (Ekman's big-6) categories, and vice versa.
This specific conversion uses a series of dimensional centroids (`emotionml:pad`) for each emotion category (`emotionml:big6`).
A dimensional value is converted to a category by looking for the nearest centroid.
The centroids are calculated according to this article:
.. code-block:: text
Kim, S. M., Valitutti, A., & Calvo, R. A. (2010, June).
Evaluation of unsupervised emotion models to textual affect recognition.
In Proceedings of the NAACL HLT 2010 Workshop on Computational Approaches to Analysis and Generation of Emotion in Text (pp. 62-70).
Association for Computational Linguistics.
It is possible to add new conversion strategies by `Developing a conversion plugin`_.
Use
===
Consider the original query: http://127.0.0.1:5000/api/?i=hello&algo=emotion-random
Consider the following query to an emotion service: http://senpy.gsi.upm.es/api/emotion-anew?i=good
The requested plugin (emotion-random) returns emotions using Ekman's model (or big6 in EmotionML):
The requested plugin (emotion-random) returns emotions using the VAD space (FSRE dimensions in EmotionML):
.. code:: json
... rest of the document ...
{
"@type": "emotionSet",
"onyx:hasEmotion": {
"@type": "emotion",
"onyx:hasEmotionCategory": "emoml:big6anger"
},
"prov:wasGeneratedBy": "plugins/emotion-random_0.1"
}
[
{
"@type": "EmotionSet",
"onyx:hasEmotion": [
{
"@type": "Emotion",
"emoml:pad-dimensions_arousal": 5.43,
"emoml:pad-dimensions_dominance": 6.41,
"emoml:pad-dimensions_pleasure": 7.47,
"prov:wasGeneratedBy": "prefix:Analysis_1562744784.8789825"
}
],
"prov:wasGeneratedBy": "prefix:Analysis_1562744784.8789825"
}
]
To get these emotions in VAD space (FSRE dimensions in EmotionML), we'd do this:
To get the equivalent of these emotions in Ekman's categories (i.e., Ekman's Big 6 in EmotionML), we'd do this:
http://127.0.0.1:5000/api/?i=hello&algo=emotion-random&emotionModel=emoml:fsre-dimensions
http://senpy.gsi.upm.es/api/emotion-anew?i=good&emotion-model=emoml:big6
This call, provided there is a valid conversion plugin from Ekman's to VAD, would return something like this:
.. code:: json
... rest of the document ...
[
{
"@type": "EmotionSet",
"onyx:hasEmotion": [
{
"@type": "emotionSet",
"onyx:hasEmotion": {
"@type": "emotion",
"onyx:hasEmotionCategory": "emoml:big6anger"
},
"prov:wasGeneratedBy": "plugins/emotion-random.1"
}, {
"@type": "emotionSet",
"onyx:hasEmotion": {
"@type": "emotion",
"A": 7.22,
"D": 6.28,
"V": 8.6
},
"prov:wasGeneratedBy": "plugins/Ekman2VAD_0.1"
"@type": "Emotion",
"onyx:algorithmConfidence": 4.4979,
"onyx:hasEmotionCategory": "emoml:big6happiness"
}
],
"prov:wasDerivedFrom": {
"@id": "Emotions0",
"@type": "EmotionSet",
"onyx:hasEmotion": [
{
"@id": "Emotion0",
"@type": "Emotion",
"emoml:pad-dimensions_arousal": 5.43,
"emoml:pad-dimensions_dominance": 6.41,
"emoml:pad-dimensions_pleasure": 7.47,
"prov:wasGeneratedBy": "prefix:Analysis_1562745220.1553965"
}
],
"prov:wasGeneratedBy": "prefix:Analysis_1562745220.1553965"
},
"prov:wasGeneratedBy": "prefix:Analysis_1562745220.1570725"
}
]
That is called a *full* response, as it simply adds the converted emotion alongside.
It is also possible to get the original emotion nested within the new converted emotion, using the `conversion=nested` parameter:
http://senpy.gsi.upm.es/api/emotion-anew?i=good&emotion-model=emoml:big6&conversion=nested
.. code:: json
[
{
"@type": "EmotionSet",
"onyx:hasEmotion": [
{
"@type": "Emotion",
"onyx:algorithmConfidence": 4.4979,
"onyx:hasEmotionCategory": "emoml:big6happiness"
}
],
"prov:wasDerivedFrom": {
"@id": "Emotions0",
"@type": "EmotionSet",
"onyx:hasEmotion": [
{
"@id": "Emotion0",
"@type": "Emotion",
"emoml:pad-dimensions_arousal": 5.43,
"emoml:pad-dimensions_dominance": 6.41,
"emoml:pad-dimensions_pleasure": 7.47,
"prov:wasGeneratedBy": "prefix:Analysis_1562744962.896306"
}
],
"prov:wasGeneratedBy": "prefix:Analysis_1562744962.896306"
},
"prov:wasGeneratedBy": "prefix:Analysis_1562744962.8978968"
}
]
... rest of the document ...
{
"@type": "emotionSet",
"onyx:hasEmotion": {
"@type": "emotion",
"onyx:hasEmotionCategory": "emoml:big6anger"
},
"prov:wasGeneratedBy": "plugins/emotion-random.1"
"onyx:wasDerivedFrom": {
"@type": "emotionSet",
"onyx:hasEmotion": {
"@type": "emotion",
"A": 7.22,
"D": 6.28,
"V": 8.6
},
"prov:wasGeneratedBy": "plugins/Ekman2VAD_0.1"
}
}
Lastly, `conversion=filtered` would only return the converted emotions.
.. code:: json
[
{
"@type": "EmotionSet",
"onyx:hasEmotion": [
{
"@type": "Emotion",
"onyx:algorithmConfidence": 4.4979,
"onyx:hasEmotionCategory": "emoml:big6happiness"
}
],
"prov:wasGeneratedBy": "prefix:Analysis_1562744925.7322266"
}
]
Developing a conversion plugin
================================
==============================
Conversion plugins are discovered by the server just like any other plugin.
The difference is the slightly different API, and the need to specify the `source` and `target` of the conversion.
@@ -106,7 +165,6 @@ For instance, an emotion conversion plugin needs the following:
.. code:: python
@@ -114,3 +172,6 @@ For instance, an emotion conversion plugin needs the following:
def convert(self, emotionSet, fromModel, toModel, params):
pass
More implementation details are shown in the `centroids plugin <https://github.com/gsi-upm/senpy/blob/master/senpy/plugins/postprocessing/emotion/centroids.py>`_.

View File

@@ -2,7 +2,7 @@ Demo
----
There is a demo available on http://senpy.gsi.upm.es/, where you can test a live instance of Senpy, with several open source plugins.
You can use the playground (a web interface) or make HTTP requests to the service API.
You can use the playground (a web interface) or the HTTP API.
.. image:: playground-0.20.png
:target: http://senpy.gsi.upm.es

View File

@@ -2,11 +2,7 @@ Developing new services
-----------------------
Developing web services can be hard.
To illustrate it, the figure below summarizes the typical features in a text analysis service.
.. image:: senpy-framework.png
:width: 60%
:align: center
A text analysis service must implement all the typical features, such as: extraction of parameters, validation, format conversion, visualization...
Senpy implements all the common blocks, so developers can focus on what really matters: great analysis algorithms that solve real problems.
Among other things, Senpy takes care of these tasks:
@@ -23,5 +19,7 @@ Sharing your sentiment analysis with the world has never been easier!
.. toctree::
:maxdepth: 1
server-cli
plugins-quickstart
plugins-faq
plugins-faq
plugins-definition

BIN
docs/eval_table.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

View File

@@ -26,20 +26,7 @@ Representation
,,,,,,,,,,,,,,
.. literalinclude:: examples/results/example-sentiment.json
:emphasize-lines: 5-10,25-33
:language: json-ld
Suggestion Mining
.................
Description
,,,,,,,,,,,
The suggestions schema represented below shows the suggestions detected in the text. Within it, we can find the NIF fields highlighted that corresponds to the text of the detected suggestion.
Representation
,,,,,,,,,,,,,,
.. literalinclude:: examples/results/example-suggestion.json
:emphasize-lines: 5-8,22-27
:emphasize-lines: 5-11,20-30
:language: json-ld
Emotion Analysis
@@ -53,28 +40,6 @@ Representation
.. literalinclude:: examples/results/example-emotion.json
:language: json-ld
:emphasize-lines: 5-8,25-37
:emphasize-lines: 5-11,22-36
Named Entity Recognition
........................
Description
,,,,,,,,,,,
The Named Entity Recognition is represented as follows. In this particular case, it can be seen within the entities array the entities recognised. For the example input, Microsoft and Windows Phone are the ones detected.
Representation
,,,,,,,,,,,,,,
.. literalinclude:: examples/results/example-ner.json
:emphasize-lines: 5-8,19-34
:language: json-ld
Complete example
................
Description
,,,,,,,,,,,
This example covers all of the above cases, integrating all the annotations in the same document.
Representation
,,,,,,,,,,,,,,
.. literalinclude:: examples/results/example-complete.json
:language: json-ld

View File

@@ -17,10 +17,6 @@
"nif:Context"
],
"nif:isString": "Dear Microsoft, put your Windows Phone on your newest #open technology program. You'll be awesome. #opensource",
"entities": [
],
"suggestions": [
],
"sentiments": [
],
"emotions": [

View File

@@ -17,10 +17,6 @@
"nif:Context"
],
"nif:isString": "Dear Microsoft, put your Windows Phone on your newest #open technology program. You'll be awesome. #opensource",
"entities": [
],
"suggestions": [
],
"sentiments": [
{
"@id": "http://micro.blog/status1#char=80,97",
@@ -32,7 +28,7 @@
"prov:wasGeneratedBy": "_:SAnalysis1_Activity"
}
],
"emotionSets": [
"emotions": [
]
}
]

View File

@@ -5,31 +5,102 @@ Welcome to Senpy's documentation!
:target: http://senpy.readthedocs.io/en/latest/
.. image:: https://badge.fury.io/py/senpy.svg
:target: https://badge.fury.io/py/senpy
.. image:: https://lab.gsi.upm.es/senpy/senpy/badges/master/build.svg
:target: https://lab.gsi.upm.es/senpy/senpy/commits/master
.. image:: https://lab.gsi.upm.es/senpy/senpy/badges/master/coverage.svg
:target: https://lab.gsi.upm.es/senpy/senpy/commits/master
.. image:: https://travis-ci.org/gsi-upm/senpy.svg
:target: https://github.com/gsi-upm/senpy/senpy/tree/master
.. image:: https://img.shields.io/pypi/l/requests.svg
:target: https://lab.gsi.upm.es/senpy/senpy/
Senpy is a framework to build sentiment and emotion analysis services.
It provides functionalities for:
Senpy is a framework for sentiment and emotion analysis services.
Senpy services are interchangeable and easy to use because they share a common semantic :doc:`apischema`.
- developing sentiment and emotion classifier and exposing them as an HTTP service
- requesting sentiment and emotion analysis from different providers (i.e. Vader, Sentimet140, ...) using the same interface (:doc:`apischema`). In this way, applications do not depend on the API offered for these services.
- combining services that use different sentiment model (e.g. polarity between [-1, 1] or [0,1] or emotion models (e.g. Ekkman or VAD)
- evaluating sentiment algorithms with well known datasets
If you interested in consuming Senpy services, read :doc:`Quickstart`.
Using senpy services is as simple as sending an HTTP request with your favourite tool or library.
Let's analyze the sentiment of the text "Senpy is awesome".
We can call the `Sentiment140 <http://www.sentiment140.com/>`_ service with an HTTP request using curl:
.. code:: shell
:emphasize-lines: 14,18
$ curl "http://senpy.gsi.upm.es/api/sentiment140" \
--data-urlencode "input=Senpy is awesome"
{
"@context": "http://senpy.gsi.upm.es/api/contexts/YXBpL3NlbnRpbWVudDE0MD8j",
"@type": "Results",
"entries": [
{
"@id": "prefix:",
"@type": "Entry",
"marl:hasOpinion": [
{
"@type": "Sentiment",
"marl:hasPolarity": "marl:Positive",
"prov:wasGeneratedBy": "prefix:Analysis_1554389334.6431913"
}
],
"nif:isString": "Senpy is awesome",
"onyx:hasEmotionSet": []
}
]
}
Congratulations, youve used your first senpy service!
You can observe the result: the polarity is positive (marl:Positive). The reason of this prefix is that Senpy follows a linked data approach.
You can analyze the same sentence using a different sentiment service (e.g. Vader) and requesting a different format (e.g. turtle):
.. code:: shell
$ curl "http://senpy.gsi.upm.es/api/sentiment-vader" \
--data-urlencode "input=Senpy is awesome" \
--data-urlencode "outformat=turtle"
@prefix : <http://www.gsi.upm.es/onto/senpy/ns#> .
@prefix endpoint: <http://senpy.gsi.upm.es/api/> .
@prefix marl: <http://www.gsi.dit.upm.es/ontologies/marl/ns#> .
@prefix nif: <http://persistence.uni-leipzig.org/nlp2rdf/ontologies/nif-core#> .
@prefix prefix: <http://senpy.invalid/> .
@prefix prov: <http://www.w3.org/ns/prov#> .
@prefix senpy: <http://www.gsi.upm.es/onto/senpy/ns#> .
prefix: a senpy:Entry ;
nif:isString "Senpy is awesome" ;
marl:hasOpinion [ a senpy:Sentiment ;
marl:hasPolarity "marl:Positive" ;
marl:polarityValue 6.72e-01 ;
prov:wasGeneratedBy prefix:Analysis_1562668175.9808676 ] .
[] a senpy:Results ;
prov:used prefix: .
As you see, Vader returns also the polarity value (0.67) in addition to the category (positive).
If you are interested in consuming Senpy services, read :doc:`Quickstart`.
To get familiar with the concepts behind Senpy, and what it can offer for service developers, check out :doc:`development`.
:doc:`apischema` contains information about the semantic models and vocabularies used by Senpy.
.. toctree::
:caption: Learn more about senpy:
:maxdepth: 2
:hidden:
senpy
demo
Quickstart.ipynb
installation
conversion
Evaluation.ipynb
apischema
advanced
development
publications
projects

View File

@@ -1,10 +1,10 @@
Installation
------------
The stable version can be used in two ways: as a system/user library through pip, or as a docker image.
The stable version can be used in two ways: as a system/user library through pip, or from a docker image.
The docker image is the recommended way because it is self-contained and isolated from the system, which means:
Using docker is recommended because the image is self-contained, reproducible and isolated from the system, which means:
* Downloading and using it is just one command
* It can be downloaded and run with just one simple command
* All dependencies are included
* It is OS-independent (MacOS, Windows, GNU/Linux)
* Several versions may coexist in the same machine without additional virtual environments
@@ -17,40 +17,39 @@ Through PIP
.. code:: bash
pip install senpy
# Or with --user if you get permission errors:
pip install --user senpy
Alternatively, you can use the development version:
.. code:: bash
..
Alternatively, you can use the development version:
git clone git@github.com:gsi-upm/senpy
cd senpy
pip install --user .
.. code:: bash
git clone git@github.com:gsi-upm/senpy
cd senpy
pip install --user .
Each version is automatically tested on GNU/Linux, macOS and Windows 10.
If you have trouble with the installation, please file an `issue on GitHub <https://github.com/gsi-upm/senpy/issues>`_.
If you want to install senpy globally, use sudo instead of the ``--user`` flag.
Docker Image
************
The base image of senpy comes with some builtin plugins that you can use:
The base image of senpy comes with some built-in plugins that you can use:
.. code:: bash
docker run -ti -p 5000:5000 gsiupm/senpy --host 0.0.0.0
To add your custom plugins, you can use a docker volume:
To use your custom plugins, you can add volume to the container:
.. code:: bash
docker run -ti -p 5000:5000 -v <PATH OF PLUGINS>:/plugins gsiupm/senpy --host 0.0.0.0 --plugins -f /plugins
There is a Senpy image for **python 2**, too:
.. code:: bash
docker run -ti -p 5000:5000 gsiupm/senpy:python2.7 --host 0.0.0.0
Alias

View File

@@ -9,20 +9,21 @@ Lastly, it is also possible to add new plugins programmatically.
.. contents:: :local:
What is a plugin?
=================
..
What is a plugin?
=================
A plugin is a program that, given a text, will add annotations to it.
In practice, a plugin consists of at least two files:
A plugin is a program that, given a text, will add annotations to it.
In practice, a plugin consists of at least two files:
- Definition file: a `.senpy` file that describes the plugin (e.g. what input parameters it accepts, what emotion model it uses).
- Python module: the actual code that will add annotations to each input.
- Definition file: a `.senpy` file that describes the plugin (e.g. what input parameters it accepts, what emotion model it uses).
- Python module: the actual code that will add annotations to each input.
This separation allows us to deploy plugins that use the same code but employ different parameters.
For instance, one could use the same classifier and processing in several plugins, but train with different datasets.
This scenario is particularly useful for evaluation purposes.
This separation allows us to deploy plugins that use the same code but employ different parameters.
For instance, one could use the same classifier and processing in several plugins, but train with different datasets.
This scenario is particularly useful for evaluation purposes.
The only limitation is that the name of each plugin needs to be unique.
The only limitation is that the name of each plugin needs to be unique.
Definition files
================
@@ -109,5 +110,3 @@ Now, in a file named ``helloworld.py``:
sentiment['marl:hasPolarity'] = 'marl:Negative'
entry.sentiments.append(sentiment)
yield entry
The complete code of the example plugin is available `here <https://lab.gsi.upm.es/senpy/plugin-prueba>`__.

View File

@@ -8,7 +8,7 @@ F.A.Q.
What are annotations?
#####################
They are objects just like entries.
Senpy ships with several default annotations, including: ``Sentiment``, ``Emotion``, ``EmotionSet``...jk bb
Senpy ships with several default annotations, including ``Sentiment`` and ``Emotion``.
What's a plugin made of?
@@ -23,7 +23,7 @@ In practice, this is what a plugin looks like, tests included:
.. literalinclude:: ../example-plugins/rand_plugin.py
:emphasize-lines: 5-11
:emphasize-lines: 21-28
:language: python

View File

@@ -37,7 +37,8 @@ The framework consists of two main modules: Senpy core, which is the building bl
What is a plugin?
#################
A plugin is a python object that can process entries. Given an entry, it will modify it, add annotations to it, or generate new entries.
A plugin is a python object that can process entries.
Given an entry, it will modify it, add annotations to it, or generate new entries.
What is an entry?

49
docs/projects.rst Normal file
View File

@@ -0,0 +1,49 @@
Projects using Senpy
--------------------
Are you using Senpy in your work?, we would love to hear from you!
Here is a list of on-going and past projects that have benefited from senpy:
MixedEmotions
,,,,,,,,,,,,,
`MixedEmotions <https://mixedemotions-project.eu/>`_ develops innovative multilingual multi-modal Big Data analytics applications.
The analytics relies on a common toolbox for multi-modal sentiment and emotion analysis.
The NLP parts of the toolbox are based on senpy and its API.
The toolbox is featured in this publication:
.. code-block:: text
Buitelaar, P., Wood, I. D., Arcan, M., McCrae, J. P., Abele, A., Robin, C., … Tummarello, G. (2018).
MixedEmotions: An Open-Source Toolbox for Multi-Modal Emotion Analysis.
IEEE Transactions on Multimedia.
EuroSentiment
,,,,,,,,,,,,,
The aim of the EUROSENTIMENT project was to create a pool for multilingual language resources and services for Sentiment Analysis.
The EuroSentiment project was the main motivation behind the development of Senpy, and some early versions were used:
.. code-block:: text
Sánchez-Rada, J. F., Vulcu, G., Iglesias, C. A., & Buitelaar, P. (2014).
EUROSENTIMENT: Linked Data Sentiment Analysis.
Proceedings of the ISWC 2014 Posters & Demonstrations Track
13th International Semantic Web Conference (ISWC 2014) (Vol. 1272, pp. 145148).
SoMeDi
,,,,,,
`SoMeDi <https://itea3.org/project/somedi.html>`_ is an ITEA3 project to research machine learning and artificial intelligence techniques that can be used to turn digital interaction data into Digital Interaction Intelligence and approaches that can be used to effectively enter and act in social media, and to automate this process.
SoMeDi exploits senpy's interoperability of services in their customizable data enrichment and NLP workflows.
TRIVALENT
,,,,,,,,,
`TRIVALENT <https://trivalent-project.eu/>`_ is an EU funded project which aims to a better understanding of root causes of the phenomenon of violent radicalisation in Europe in order to develop appropriate countermeasures, ranging from early detection methodologies to techniques of counter-narrative.
In addition to sentiment and emotion analysis services, trivalent provides other types of senpy services such as radicalism and writing style analysis.

View File

@@ -2,7 +2,7 @@ Publications
============
If you use Senpy in your research, please cite `Senpy: A Pragmatic Linked Sentiment Analysis Framework <http://gsi.dit.upm.es/index.php/es/investigacion/publicaciones?view=publication&task=show&id=417>`__ (`BibTex <http://gsi.dit.upm.es/index.php/es/investigacion/publicaciones?controller=publications&task=export&format=bibtex&id=417>`__):
And if you use Senpy in your research, please cite `Senpy: A Pragmatic Linked Sentiment Analysis Framework <http://gsi.dit.upm.es/index.php/es/investigacion/publicaciones?view=publication&task=show&id=417>`__ (`BibTex <http://gsi.dit.upm.es/index.php/es/investigacion/publicaciones?controller=publications&task=export&format=bibtex&id=417>`__):
.. code-block:: text
@@ -12,7 +12,6 @@ If you use Senpy in your research, please cite `Senpy: A Pragmatic Linked Sentim
2016 IEEE International Conference on (pp. 735-742). IEEE.
Senpy uses Onyx for emotion representation, first introduced in:
.. code-block:: text
@@ -28,19 +27,10 @@ Senpy uses Marl for sentiment representation, which was presented in:
Westerski, A., Iglesias Fernandez, C. A., & Tapia Rico, F. (2011).
Linked opinions: Describing sentiments on the structured web of data.
Senpy has been used extensively in the toolbox of the MixedEmotions project:
.. code-block:: text
Buitelaar, P., Wood, I. D., Arcan, M., McCrae, J. P., Abele, A., Robin, C., … Tummarello, G. (2018).
MixedEmotions: An Open-Source Toolbox for Multi-Modal Emotion Analysis.
IEEE Transactions on Multimedia.
The representation models, formats and challenges are partially covered in a chapter of the book Sentiment Analysis in Social Networks:
.. code-block:: text
Iglesias, C. A., Sánchez-Rada, J. F., Vulcu, G., & Buitelaar, P. (2017).
Linked Data Models for Sentiment and Emotion Analysis in Social Networks.
In Sentiment Analysis in Social Networks (pp. 49-69).
In Sentiment Analysis in Social Networks (pp. 49-69).

View File

@@ -1,5 +1,8 @@
Server
======
Command line tool
=================
Basic usage
-----------
The senpy server is launched via the `senpy` command:
@@ -70,3 +73,14 @@ For instance, to accept connections on port 6000 on any interface:
senpy --host 0.0.0.0 --port 6000
For more options, see the `--help` page.
Sentiment analysis in the command line
--------------------------------------
Although the main use of senpy is to publish services, the tool can also be used locally to analyze text in the command line.
This is a short video demonstration:
.. image:: https://asciinema.org/a/9uwef1ghkjk062cw2t4mhzpyk.png
:width: 100%
:target: https://asciinema.org/a/9uwef1ghkjk062cw2t4mhzpyk
:alt: CLI demo

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from senpy import AnalysisPlugin
import multiprocessing

View File

@@ -1,5 +1,21 @@
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
emoticons = {
'pos': [':)', ':]', '=)', ':D'],

View File

@@ -1,5 +1,20 @@
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from senpy import easy_test, models, plugins

View File

@@ -1,5 +1,20 @@
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from senpy import easy_test, SentimentBox

View File

@@ -1,5 +1,21 @@
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from senpy import easy_test, SentimentBox

View File

@@ -1,5 +1,21 @@
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from senpy import easy_test, models, plugins

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from senpy import AnalysisPlugin, easy

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from senpy import AnalysisPlugin, easy

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import random
from senpy.plugins import EmotionPlugin

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import noop
from senpy.plugins import SentimentPlugin

View File

@@ -1,5 +1,21 @@
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from senpy import easy_test, models, plugins

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import random
from senpy import SentimentPlugin, Sentiment, Entry

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
'''
Create a dummy dataset.
Messages with a happy emoticon are labelled positive

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import train_test_split

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from senpy import SentimentBox, easy_test
from mypipeline import pipeline

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from senpy.plugins import AnalysisPlugin
from time import sleep

View File

@@ -1,7 +1,7 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright 2014 J. Fernando Sánchez Rada - Grupo de Sistemas Inteligentes
# DIT, UPM
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""
Sentiment analysis server in Python
"""

View File

@@ -1,7 +1,6 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright 2014 J. Fernando Sánchez Rada - Grupo de Sistemas Inteligentes
# DIT, UPM
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from future.utils import iteritems
from .models import Error, Results, Entry, from_string
import logging

View File

@@ -1,19 +1,20 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright 2014 J. Fernando Sánchez Rada - Grupo de Sistemas Inteligentes
# DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# http://www.apache.org/licenses/LICENSE-2.0
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# Unless required by applicable law or agreed to in writing, software
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""
Blueprints for Senpy
"""
@@ -24,7 +25,7 @@ from . import api
from .version import __version__
from functools import wraps
from .gsitk_compat import GSITK_AVAILABLE
from .gsitk_compat import GSITK_AVAILABLE, datasets
import logging
import json
@@ -272,8 +273,6 @@ def plugin(plugin):
@api_blueprint.route('/datasets/', methods=['POST', 'GET'])
@basic_api
def datasets():
sp = current_app.senpy
datasets = sp.datasets
def get_datasets():
dic = Datasets(datasets=list(datasets.values()))
return dic

View File

@@ -1,3 +1,18 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from __future__ import print_function
import sys

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import requests
import logging
from . import models

View File

@@ -1,3 +1,18 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""
Main class for Senpy.
It orchestrates plugin (de)activation and analysis.
@@ -274,36 +289,16 @@ class Senpy(object):
return response
def _get_datasets(self, request):
if not self.datasets:
raise Error(
status=404,
message=("No datasets found."
" Please verify DatasetManager"))
datasets_name = request.parameters.get('dataset', None).split(',')
for dataset in datasets_name:
if dataset not in self.datasets:
if dataset not in gsitk_compat.datasets:
logger.debug(("The dataset '{}' is not valid\n"
"Valid datasets: {}").format(
dataset, self.datasets.keys()))
dataset, gsitk_compat.datasets.keys()))
raise Error(
status=404,
message="The dataset '{}' is not valid".format(dataset))
dm = gsitk_compat.DatasetManager()
datasets = dm.prepare_datasets(datasets_name)
return datasets
@property
def datasets(self):
self._dataset_list = {}
dm = gsitk_compat.DatasetManager()
for item in dm.get_datasets():
for key in item:
if key in self._dataset_list:
continue
properties = item[key]
properties['@id'] = key
self._dataset_list[key] = properties
return self._dataset_list
return datasets_name
def evaluate(self, params):
logger.debug("evaluating request: {}".format(params))

View File

@@ -1,4 +1,21 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
import os
from pkg_resources import parse_version, get_distribution, DistributionNotFound
@@ -17,15 +34,34 @@ try:
gsitk_distro = get_distribution("gsitk")
GSITK_VERSION = parse_version(gsitk_distro.version)
if not os.environ.get('DATA_PATH'):
os.environ['DATA_PATH'] = os.environ.get('SENPY_DATA', 'senpy_data')
from gsitk.datasets.datasets import DatasetManager
from gsitk.evaluation.evaluation import Evaluation as Eval # noqa: F401
from gsitk.evaluation.evaluation import EvalPipeline # noqa: F401
from sklearn.pipeline import Pipeline
modules = locals()
GSITK_AVAILABLE = True
datasets = {}
manager = DatasetManager()
for item in manager.get_datasets():
for key in item:
if key in datasets:
continue
properties = item[key]
properties['@id'] = key
datasets[key] = properties
def prepare(ds, *args, **kwargs):
return manager.prepare_datasets(ds, *args, **kwargs)
except (DistributionNotFound, ImportError) as err:
logger.debug('Error importing GSITK: {}'.format(err))
logger.warning(IMPORTMSG)
GSITK_AVAILABLE = False
GSITK_VERSION = ()
DatasetManager = Eval = Pipeline = raise_exception
DatasetManager = Eval = Pipeline = prepare = raise_exception
datasets = {}

View File

@@ -1,3 +1,18 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
'''
Meta-programming for the models.
'''

View File

@@ -1,3 +1,18 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
'''
Senpy Models.

View File

@@ -1,5 +1,21 @@
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from future import standard_library
standard_library.install_aliases()
@@ -45,7 +61,7 @@ class PluginMeta(models.BaseMeta):
plugin_type.add(name)
alias = attrs.get('name', name).lower()
attrs['_plugin_type'] = plugin_type
logger.debug('Adding new plugin class', name, bases, attrs, plugin_type)
logger.debug('Adding new plugin class: %s %s %s %s', name, bases, attrs, plugin_type)
attrs['name'] = alias
if 'description' not in attrs:
doc = attrs.get('__doc__', None)
@@ -94,7 +110,7 @@ class Plugin(with_metaclass(PluginMeta, models.Plugin)):
Provides a canonical name for plugins and serves as base for other
kinds of plugins.
"""
logger.debug("Initialising {}".format(info))
logger.debug("Initialising %s", info)
super(Plugin, self).__init__(**kwargs)
if info:
self.update(info)
@@ -164,8 +180,7 @@ class Plugin(with_metaclass(PluginMeta, models.Plugin)):
def process_entries(self, entries, activity):
for entry in entries:
self.log.debug('Processing entry with plugin {}: {}'.format(
self, entry))
self.log.debug('Processing entry with plugin %s: %s', self, entry)
results = self.process_entry(entry, activity)
if inspect.isgenerator(results):
for result in results:
@@ -347,6 +362,9 @@ class Evaluable(Plugin):
def evaluate_func(self, X, activity=None):
raise Exception('Implement the evaluate_func function')
def evaluate(self, *args, **kwargs):
return evaluate([self], *args, **kwargs)
class SentimentPlugin(Analyser, Evaluable, models.SentimentPlugin):
'''
@@ -831,6 +849,9 @@ def evaluate(plugins, datasets, **kwargs):
if not hasattr(plug, 'as_pipe'):
raise models.Error('Plugin {} cannot be evaluated'.format(plug.name))
if not isinstance(datasets, dict):
datasets = gsitk_compat.prepare(datasets, download=True)
tuples = list(product(plugins, datasets))
missing = []
for (p, d) in tuples:
@@ -844,12 +865,12 @@ def evaluate(plugins, datasets, **kwargs):
new_ev = evaluations_to_JSONLD(results, **kwargs)
for ev in new_ev:
dataset = ev.evaluatesOn
model = ev.evaluates.rstrip('__' + dataset)
model = ev.evaluates
cached_evs[(model, dataset)] = ev
evaluations = []
print(tuples, 'Cached evs', cached_evs)
logger.debug('%s. Cached evs: %s', tuples, cached_evs)
for (p, d) in tuples:
print('Adding', d, p)
logger.debug('Adding %s, %s', d, p)
evaluations.append(cached_evs[(p.id, d)])
return evaluations
@@ -868,7 +889,7 @@ def evaluations_to_JSONLD(results, flatten=False):
if row.get('CV', True):
evaluation['@type'] = ['StaticCV', 'Evaluation']
evaluation.evaluatesOn = row['Dataset']
evaluation.evaluates = row['Model']
evaluation.evaluates = row['Model'].rstrip('__' + row['Dataset'])
i = 0
if flatten:
metric = models.Metric()

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from senpy.plugins import Transformation
from senpy.models import Entry
from nltk.tokenize.punkt import PunktSentenceTokenizer

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from senpy.plugins import EmotionConversionPlugin
from senpy.models import EmotionSet, Emotion, Error
@@ -85,7 +101,13 @@ class CentroidConversion(EmotionConversionPlugin):
def distance(centroid):
return sum(distance_k(centroid, original, k) for k in dimensions)
emotion = min(centroids, key=lambda x: distance(centroids[x]))
distances = {k: distance(centroids[k]) for k in centroids}
logger.debug('Converting %s', original)
logger.debug('Centroids: %s', centroids)
logger.debug('Distances: %s', distances)
emotion = min(distances, key=lambda x: distances[x])
result = Emotion(onyx__hasEmotionCategory=emotion)
result.onyx__algorithmConfidence = distance(centroids[emotion])

View File

@@ -9,30 +9,30 @@ centroids:
anger:
A: 6.95
D: 5.1
V: 2.7
P: 2.7
disgust:
A: 5.3
D: 8.05
V: 2.7
P: 2.7
fear:
A: 6.5
D: 3.6
V: 3.2
P: 3.2
happiness:
A: 7.22
D: 6.28
V: 8.6
P: 8.6
sadness:
A: 5.21
D: 2.82
V: 2.21
P: 2.21
centroids_direction:
- emoml:big6
- emoml:pad
- emoml:pad-dimensions
aliases: # These are aliases for any key in the centroid, to avoid repeating a long name several times
A: emoml:pad-dimensions:arousal
V: emoml:pad-dimensions:valence
D: emoml:pad-dimensions:dominance
P: emoml:pad-dimensions_pleasure
A: emoml:pad-dimensions_arousal
D: emoml:pad-dimensions_dominance
anger: emoml:big6anger
disgust: emoml:big6disgust
fear: emoml:big6fear

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from senpy import PostProcessing, easy_test

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import requests
import json

View File

@@ -174,10 +174,18 @@ function add_plugin_pipeline(){
function draw_datasets(){
html = "";
repeated_html = "<input class=\"checks-datasets\" type=\"checkbox\" value=\"";
for (dataset in datasets){
html += repeated_html+datasets[dataset]["@id"]+"\">"+datasets[dataset]["@id"];
html += "<br>"
ds = datasets[dataset]
// html += repeated_html+datasets[dataset]["@id"]+"\">"+datasets[dataset]["@id"];
html += `
<span class="d-inline-block" tabindex="0" data-toggle="tooltip" title="Instances: ${ds["stats"]["instances"]}">
<div class="form-check form-check-inline">
<input class="form-check-input checks-datasets" type="checkbox" value="${ds["@id"]}">
<label class="form-check-label" for="defaultCheck1">${ds["@id"]}</label>
</div>
</span>
`
}
document.getElementById("datasets").innerHTML = html;
}

View File

@@ -233,28 +233,43 @@ In Data Science and Advanced Analytics (DSAA),
<div class="tab-pane" role="tabpanel" aria-labelledby="nav-evaluate" id="evaluate">
<div class="card my-2">
<div class="card-body">
<p>Automatically evaluate the classification performance of your plugin in several public datasets, and compare it with other plugins.</p>
<p>The datasets will be automatically downloaded if they are not already available locally. Depending on the size of the dataset and the speed of the plugin, the evaluation may take a long time.</p>
<form id="form" class="container" onsubmit="" accept-charset="utf-8">
<div>
<p>Automatically evaluate the classification performance of your plugin in several public datasets, and compare it with other plugins.</p>
<p>The datasets will be automatically downloaded if they are not already available locally. Depending on the size of the dataset and the speed of the plugin, the evaluation may take a long time.</p>
<label>Select the plugin:</label>
<select id="plugins-eval" name="plugins-eval" class=plugin onchange="draw_extra_parameters()">
</select>
</div>
<div>
<label>Select the datasets:</label>
<div id="datasets" name="datasets" >
</select>
<div class="card my-2">
<div class="card-header">
<h5>
Select the plugin.
</h5>
</div>
<div id="plugin_selection" class="card-body">
<select id="plugins-eval" name="plugins-eval" class=plugin onchange="draw_extra_parameters()">
</select>
</div>
<button id="doevaluate" class="btn btn-lg btn-primary" onclick="evaluate_JSON()">Evaluate Plugin</button>
<!--<button id="visualise" name="type" type="button">Visualise!</button>-->
</div>
<div class="card my-2">
<div class="card-header">
<h5>
Select the dataset.
</h5>
</div>
<div id="dataset_selection" class="card-body">
<div id="datasets" name="datasets" >
</div>
</div>
</div>
<!--<button id="visualise" name="type" type="button">Visualise!</button>-->
<button id="doevaluate" class="btn btn-lg btn-primary" onclick="evaluate_JSON()">Evaluate Plugin</button>
</form>
</div>
</div>
<div class="card my-2">
<div id="loading-results" class="loading"></div>
<span id="input_request_eval"></span>
<div id="input_request_eval"></div>
<div id="evaluate-div">
<ul class="nav nav-pills" role="tablist">
@@ -273,23 +288,25 @@ In Data Science and Advanced Analytics (DSAA),
</div>
</div>
<div class="tab-pane" role="tabpanel" aria-labelledby="" id="evaluate-table">
<table id="eval_table" class="table table-condensed">
<thead>
<tr>
<th>Plugin</th>
<th>Dataset</th>
<th>Accuracy</th>
<th>Precision_macro</th>
<th>Recall_macro</th>
<th>F1_macro</th>
<th>F1_weighted</th>
<th>F1_micro</th>
<th>F1</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<div>
<table id="eval_table" class="table table-condensed">
<thead>
<tr>
<th>Plugin</th>
<th>Dataset</th>
<th>Accuracy</th>
<th>Precision_macro</th>
<th>Recall_macro</th>
<th>F1_macro</th>
<th>F1_weighted</th>
<th>F1_micro</th>
<th>F1</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</div>

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from past.builtins import basestring
import os

View File

@@ -1,3 +1,18 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from . import models, __version__
from collections import MutableMapping
import pprint

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import os
import logging
@@ -13,7 +29,7 @@ def read_version(versionfile=DEFAULT_FILE):
return f.read().strip()
except IOError: # pragma: no cover
logger.error('Running an unknown version of senpy. Be careful!.')
return '0.0'
return 'devel'
__version__ = read_version()

View File

@@ -13,7 +13,7 @@ max-line-length = 100
[bdist_wheel]
universal=1
[tool:pytest]
addopts = --cov=senpy --cov-report term-missing
addopts = -v --cov=senpy --cov-report term-missing
filterwarnings =
ignore:the matrix subclass:PendingDeprecationWarning
[coverage:report]

View File

@@ -1,17 +1,44 @@
from setuptools import setup
'''
Copyright 2014 GSI DIT UPM
with open('senpy/VERSION') as f:
__version__ = f.read().strip()
assert __version__
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
'''
from setuptools import setup
from os import path
import io
try:
with io.open('senpy/VERSION') as f:
__version__ = f.read().strip()
assert __version__
except IOError: # pragma: no cover
print('Installing a development version of senpy. Proceed with caution!')
__version__ = 'devel'
def parse_requirements(filename):
""" load requirements from a pip requirements file """
with open(filename, 'r') as f:
with io.open(filename, 'r') as f:
lineiter = list(line.strip() for line in f)
return [line for line in lineiter if line and not line.startswith("#")]
this_directory = path.abspath(path.dirname(__file__))
with io.open(path.join(this_directory, 'README.rst'), encoding='utf-8') as f:
long_description = f.read()
install_reqs = parse_requirements("requirements.txt")
test_reqs = parse_requirements("test-requirements.txt")
extra_reqs = parse_requirements("extra-requirements.txt")
@@ -25,6 +52,8 @@ setup(
description=('A sentiment analysis server implementation. '
'Designed to be extensible, so new algorithms '
'and sources can be used.'),
long_description=long_description,
long_description_content_type='text/x-rst',
author='J. Fernando Sanchez',
author_email='balkian@gmail.com',
url='https://github.com/gsi-upm/senpy', # use the URL to the github repo

View File

@@ -1,3 +1,4 @@
mock
pytest-cov
pytest
pandas

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
logger = logging.getLogger(__name__)

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import os
import logging

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
from functools import partial

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from unittest import TestCase
from senpy.testing import patch_requests

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from __future__ import print_function
import os
from copy import deepcopy

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
import jsonschema

View File

@@ -1,5 +1,21 @@
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import os
import pickle

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from __future__ import print_function
import json

View File

@@ -1,5 +1,21 @@
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from future.standard_library import install_aliases
install_aliases()

View File

@@ -1,3 +1,19 @@
#
# Copyright 2014 Grupo de Sistemas Inteligentes (GSI) DIT, UPM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from unittest import TestCase
import requests