1
0
mirror of https://github.com/gsi-upm/senpy synced 2025-08-23 18:12:20 +00:00

Add headers and minor fixes

This commit is contained in:
J. Fernando Sánchez
2019-07-17 16:29:30 +02:00
parent c4321dc500
commit 435d107677
69 changed files with 3638 additions and 2592 deletions

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,
}

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

@@ -19,6 +19,7 @@ Sharing your sentiment analysis with the world has never been easier!
.. toctree::
:maxdepth: 1
server-cli
plugins-quickstart
plugins-faq
plugins-definition

BIN
docs/eval_table.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

View File

@@ -12,24 +12,97 @@ Welcome to Senpy's documentation!
.. 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

@@ -17,18 +17,20 @@ 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
If you want to install senpy globally, use sudo instead of the ``--user`` flag.
git clone git@github.com:gsi-upm/senpy
cd senpy
pip install --user .
Docker Image
************

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

@@ -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