|
|
<html> |
|
|
|
|
|
<head> |
|
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8" /> |
|
|
<title>OpenSLU Visual Analysis</title> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|
|
<link href="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/css/bootstrap.min.css" rel="stylesheet"> |
|
|
<script src="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/js/bootstrap.bundle.min.js"></script> |
|
|
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script> |
|
|
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.1/dist/echarts.min.js"></script> |
|
|
<style type="text/css"> |
|
|
span.rcorners2 { |
|
|
background-color: #e6e6e6; |
|
|
color: #000; |
|
|
} |
|
|
</style> |
|
|
<link rel="icon" href="{{url_for('static',filename='favicon.ico')}}" type ="image/x-icon"> |
|
|
</head> |
|
|
|
|
|
<body> |
|
|
<div class="row" style="width: 100%;margin: 2px;"> |
|
|
<div class="col-md-12 col-sm-12" style="display: flex; flex-direction: column; align-items: center;"> |
|
|
|
|
|
<div class="row" style="width: 100%; margin: 20px 0px 30px 0px; justify-content: center;"> |
|
|
<div class="col-md-4"> |
|
|
<div class="card" |
|
|
style="width: 100%;display: flex;align-content: center;flex-direction: column;flex-wrap: nowrap;justify-content: center;align-items: center;"> |
|
|
<div style="margin-bottom: 0px; margin-top: 20px;text-align: center;"> |
|
|
<b>Error Intent Label Distribution</b> |
|
|
</div> |
|
|
<div id="intent-pie" style="width: 100%;height:300px;"></div> |
|
|
</div> |
|
|
|
|
|
</div> |
|
|
<div class="col-md-4"> |
|
|
<div class="card" |
|
|
style="width: 100%;display: flex;align-content: center;flex-direction: column;flex-wrap: nowrap;justify-content: center;align-items: center;"> |
|
|
<div style="margin-bottom: 0px; margin-top: 20px;text-align: center;"> |
|
|
<b>Error Slot Label Distribution</b> |
|
|
</div> |
|
|
<div id="slot-pie" style="width: 100%;height:300px;"></div> |
|
|
</div> |
|
|
</div> |
|
|
<div class="col-md-4"> |
|
|
<div class="card" |
|
|
style="width: 90%;display: flex;align-content: center;flex-direction: column;flex-wrap: nowrap;justify-content: center;align-items: center;"> |
|
|
<div class="card-body" style="width: 100%;"> |
|
|
<div id="card-title" style="text-align: center;"></div> |
|
|
<div id="gauge_chart" style="width: 100%; height:200px;"></div> |
|
|
<p class="card-text" style="margin-top: -80px;" id="card-statistics"> |
|
|
</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
<div class="row" style="width: 100%; margin: 20px 0px 30px 0px; justify-content: center;"> |
|
|
|
|
|
|
|
|
|
|
|
<script type="text/javascript"> |
|
|
{% autoescape false %} |
|
|
var slot_dict = {{ slot_dict }} |
|
|
var slot_dict_list = {{ slot_dict_list }} |
|
|
var intent_dict = {{ intent_dict }} |
|
|
var intent_dict_list = {{ intent_dict_list }} |
|
|
|
|
|
{% endautoescape %} |
|
|
function drawPieChart(docId, data, type) { |
|
|
var chartDom = document.getElementById(docId); |
|
|
var data_keys = [] |
|
|
for (var i = 0; i < data.length; i++) { |
|
|
data_keys.push(data[i]["name"]) |
|
|
} |
|
|
var myChart = echarts.init(chartDom); |
|
|
|
|
|
var option = { |
|
|
tooltip: { |
|
|
trigger: 'item' |
|
|
}, |
|
|
visualMap: { |
|
|
show: false, |
|
|
|
|
|
|
|
|
splitNumber: 10, |
|
|
inRange: { |
|
|
color: ["#a50026", "#d73027", "#f46d43", "#fdae61", "#fee090", "#ffffbf", "#e0f3f8", "#abd9e9", "#74add1", "#4575b4", "#313695"] |
|
|
|
|
|
}, |
|
|
pieces: [ |
|
|
{ gt: data[1]["value"], lte: data[0]["value"] }, |
|
|
{ gt: data[2]["value"], lte: data[1]["value"] }, |
|
|
{ gt: data[3]["value"], lte: data[2]["value"] }, |
|
|
{ gt: data[4]["value"], lte: data[3]["value"] }, |
|
|
{ gt: data[5]["value"], lte: data[4]["value"] }, |
|
|
{ gt: data[6]["value"], lte: data[5]["value"] }, |
|
|
{ gt: data[7]["value"], lte: data[6]["value"] }, |
|
|
{ gt: data[8]["value"], lte: data[7]["value"] }, |
|
|
{ gt: data[9]["value"], lte: data[8]["value"] }, |
|
|
{ lte: data[9]["value"] } |
|
|
] |
|
|
}, |
|
|
series: [ |
|
|
{ |
|
|
type: 'pie', |
|
|
radius: ['50%', '70%'], |
|
|
avoidLabelOverlap: false, |
|
|
itemStyle: { |
|
|
|
|
|
borderRadius: 10, |
|
|
borderColor: '#fff', |
|
|
borderWidth: 2 |
|
|
}, |
|
|
label: { |
|
|
show: false, |
|
|
position: 'center' |
|
|
}, |
|
|
emphasis: { |
|
|
label: { |
|
|
show: true, |
|
|
fontSize: 20, |
|
|
fontWeight: 'bold' |
|
|
} |
|
|
}, |
|
|
labelLine: { |
|
|
show: false |
|
|
}, |
|
|
data: data |
|
|
} |
|
|
] |
|
|
}; |
|
|
|
|
|
option && myChart.setOption(option); |
|
|
myChart.on('click', function (params) { |
|
|
if (type == "slot") { |
|
|
var detailChart = drawGaugeChart("gauge_chart", slot_dict, params.name, "slot") |
|
|
} else { |
|
|
var detailChart = drawGaugeChart("gauge_chart", intent_dict, params.name, "intent") |
|
|
} |
|
|
|
|
|
}); |
|
|
} |
|
|
function drawBarChart(docId, data, type) { |
|
|
var chartDom = document.getElementById(docId); |
|
|
var data_dicts = {} |
|
|
var data_keys = [] |
|
|
var bars = [] |
|
|
for (var i = 0; i < data.length; i++) { |
|
|
data_dicts[data[i]["name"]] = data[i]["value"] |
|
|
data_keys.push(data[i]["name"]) |
|
|
bars.push({ type: 'bar' }) |
|
|
} |
|
|
var myChart = echarts.init(chartDom); |
|
|
|
|
|
option = { |
|
|
legend: {}, |
|
|
tooltip: {}, |
|
|
dataset: { |
|
|
dimensions: data_keys, |
|
|
source: [data_dicts] |
|
|
}, |
|
|
xAxis: { type: 'category' }, |
|
|
yAxis: {}, |
|
|
|
|
|
|
|
|
series: bars |
|
|
}; |
|
|
option && myChart.setOption(option); |
|
|
myChart.on('click', function (params) { |
|
|
if (type == "slot") { |
|
|
var detailChart = drawGaugeChart("gauge_chart", slot_dict, params.name, "slot") |
|
|
} else { |
|
|
var detailChart = drawGaugeChart("gauge_chart", intent_dict, params.name, "intent") |
|
|
} |
|
|
|
|
|
}); |
|
|
} |
|
|
function greatBarChart(docId, data, type) { |
|
|
var chartDom = document.getElementById(docId); |
|
|
var myChart = echarts.init(chartDom); |
|
|
myChart.hideLoading(); |
|
|
var data_lists = [] |
|
|
var data_keys = [] |
|
|
var bars = [] |
|
|
var colors = [ |
|
|
'#dd6b66', |
|
|
'#759aa0', |
|
|
'#e69d87', |
|
|
'#8dc1a9', |
|
|
'#ea7e53', |
|
|
'#eedd78', |
|
|
'#73a373', |
|
|
'#73b9bc', |
|
|
'#7289ab', |
|
|
'#91ca8c', |
|
|
'#f49f42' |
|
|
] |
|
|
for (var i = 0; i < data.length; i++) { |
|
|
data_lists.push({ "value": data[i]["value"], "itemStyle": { color: colors[i % colors.length] } }) |
|
|
data_keys.push(data[i]["name"]) |
|
|
bars.push({ type: 'bar' }) |
|
|
} |
|
|
console.log(data_lists) |
|
|
option = { |
|
|
tooltip: { |
|
|
trigger: 'axis', |
|
|
axisPointer: { |
|
|
type: 'shadow', |
|
|
label: { |
|
|
show: true |
|
|
} |
|
|
} |
|
|
}, |
|
|
toolbox: { |
|
|
show: true, |
|
|
feature: { |
|
|
dataZoom: { yAxisIndex: 'none', title: 'Area Zoom' }, |
|
|
|
|
|
dataView: { show: true, readOnly: false, title: 'Raw Data' }, |
|
|
magicType: { show: true, type: ['line', 'bar'], title: { line: 'Switch to Line Chart', bar: 'Switch to Bar Chart' } }, |
|
|
restore: { show: true, title: 'Restore Image' }, |
|
|
saveAsImage: { show: true, title: 'Save as Image' } |
|
|
} |
|
|
}, |
|
|
calculable: true, |
|
|
legend: { |
|
|
data: ['Budget 2011'], |
|
|
itemGap: 5 |
|
|
}, |
|
|
grid: { |
|
|
top: 50, |
|
|
bottom: 50, |
|
|
left: 10, |
|
|
right: 30, |
|
|
containLabel: true |
|
|
}, |
|
|
xAxis: { type: 'category', data: data_keys, show: false }, |
|
|
yAxis: {}, |
|
|
dataZoom: [ |
|
|
{ |
|
|
show: true, |
|
|
start: 0, |
|
|
end: 100 |
|
|
}, |
|
|
{ |
|
|
type: 'inside', |
|
|
start: 0, |
|
|
end: 100 |
|
|
}, |
|
|
{ |
|
|
show: true, |
|
|
yAxisIndex: 0, |
|
|
filterMode: 'empty', |
|
|
width: 20, |
|
|
|
|
|
height: '60%', |
|
|
showDataShadow: false, |
|
|
|
|
|
} |
|
|
], |
|
|
series: [{ data: data_lists, type: 'bar' }] |
|
|
}; |
|
|
option && myChart.setOption(option); |
|
|
myChart.on('click', function (params) { |
|
|
if (type == "slot") { |
|
|
var detailChart = drawGaugeChart("gauge_chart", slot_dict, params.name, "slot") |
|
|
} else { |
|
|
var detailChart = drawGaugeChart("gauge_chart", intent_dict, params.name, "intent") |
|
|
} |
|
|
|
|
|
}); |
|
|
} |
|
|
var xchart = greatBarChart("intent-pie", intent_dict_list, "intent") |
|
|
var ychart = greatBarChart("slot-pie", slot_dict_list, "slot") |
|
|
function drawGaugeChart(docId, x_dict, x_name, type) { |
|
|
var chartDom = document.getElementById(docId); |
|
|
var data = x_dict[x_name] |
|
|
var total = data[0][1] |
|
|
var error = data[1][1] |
|
|
var option = { |
|
|
series: [{ |
|
|
type: 'gauge', |
|
|
startAngle: 170, |
|
|
endAngle: 10, |
|
|
min: 0, |
|
|
max: 100, |
|
|
pointer: { show: false }, |
|
|
splitLine: { |
|
|
show: false, |
|
|
distance: 0, |
|
|
length: 10 |
|
|
}, |
|
|
axisTick: { show: false }, |
|
|
axisLabel: { |
|
|
show: false, |
|
|
distance: 50 |
|
|
}, |
|
|
detail: { |
|
|
show: false, |
|
|
width: 50, |
|
|
height: 14, |
|
|
fontSize: 14, |
|
|
color: 'inherit', |
|
|
borderColor: 'inherit', |
|
|
borderRadius: 20, |
|
|
borderWidth: 1, |
|
|
formatter: '{value}%' |
|
|
}, |
|
|
itemStyle: { |
|
|
color: 'rgb(128,183,214)', |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}, |
|
|
progress: { |
|
|
show: true, |
|
|
roundCap: true, |
|
|
width: 18 |
|
|
}, |
|
|
axisLine: { |
|
|
roundCap: true, |
|
|
lineStyle: { width: 18 } |
|
|
}, |
|
|
data: [100.0 * error / total] |
|
|
}] |
|
|
}; |
|
|
var myChart = echarts.init(chartDom); |
|
|
option && myChart.setOption(option); |
|
|
var element = document.getElementById("card-statistics"); |
|
|
var html_txt = `` |
|
|
html_txt += '<div style="margin: 0px 10px 10px 10px;"><b>' + Math.round(100.0 * error / total * 10) / 10 + '%</b> of <b>' + x_name + '</b> labels are predicted incorrectly. They are predicted as: </div>'; |
|
|
for (var i = 2; i < data.length; i++) { |
|
|
ratio = Math.round(100.0 * data[i][1] / error * 10) / 10 |
|
|
html_txt += `<div style="margin: 0px 10px 0px 10px;"> |
|
|
<div style="width:15%; height:12px; background-color:rgb(234, 235, 235);border-radius: 6px; display: inline-block;"> |
|
|
<div style="width:` |
|
|
+ (ratio) + `%; height:12px; background-color:rgb(128,183,214);border-radius: 6px; display: inline-block;"></div> |
|
|
</div> |
|
|
<div style="width: 63%;margin-left: 12px;display: inline-block;">` |
|
|
+ data[i][0] + |
|
|
`</div> |
|
|
<div style="width:15%; display: inline-block;text-align: right;">` |
|
|
+ ratio + |
|
|
`%</div></div>`; |
|
|
} |
|
|
element.innerHTML = html_txt; |
|
|
var title = document.getElementById("card-title"); |
|
|
title.innerHTML = "<b>Error ratio for " + type + " '" + x_name + "'</b>" |
|
|
} |
|
|
var detailChart = drawGaugeChart("gauge_chart", slot_dict, slot_dict_list[0].name, "slot") |
|
|
</script> |
|
|
</div> |
|
|
</div> |
|
|
<div class="col-md-12 col-sm-12" style="margin: -30px 10px 10px 10px; padding: 0px 40px 0px 40px;"> |
|
|
<div style="font-size: larger;margin-bottom: 10px;"><b>Instance Analysis</b> |
|
|
<hr /> |
|
|
</div> |
|
|
{% for example in examples %} |
|
|
<b>Intent:</b> |
|
|
{% for e in example["intent"] %} |
|
|
{% if e["intent"] == e["pred_intent"] %} |
|
|
|
|
|
<button type="button" class="btn btn-white"> |
|
|
<span class="badge text-dark btn-light">{{e["pred_intent"]}}</span> |
|
|
</button> |
|
|
{% else %} |
|
|
<button type="button" class="btn btn-light" data-bs-trigger="hover" data-bs-toggle="popover" |
|
|
data-bs-placement="left" data-bs-content=" |
|
|
<b>Golden Intent: </b> |
|
|
<span class='badge text-dark btn-light' style='background-color: #e6e6e6;'> |
|
|
{{e['intent']}} |
|
|
</span>"> |
|
|
<span class="badge" |
|
|
style="background-color: rgb(246,123,74);color: rgb(255, 255, 255);">{{e["pred_intent"]}}</span> |
|
|
</button> |
|
|
{% endif %} |
|
|
{% endfor %} |
|
|
|
|
|
<br /> |
|
|
<b>Slot:</b> |
|
|
{% for e in example["slot"] %} |
|
|
{% if e["slot"] == e["pred_slot"] %} |
|
|
|
|
|
<button type="button" class="btn btn-white"> |
|
|
{{e["text"]}} <span class="badge text-dark" style="background-color: rgb(255, 255, 255); |
|
|
color: rgb(62 62 62); |
|
|
box-shadow: 2px 2px 7px 1px rgba(210, 210, 210, 0.42);">{{e["pred_slot"]}}</span> |
|
|
</button> |
|
|
{% else %} |
|
|
<button type="button" class="btn btn-light" data-bs-trigger="hover" data-bs-toggle="popover" |
|
|
data-bs-placement="left" data-bs-content=" |
|
|
<b>Golden Slot: </b> |
|
|
<span class='rcorners2 badge text-dark btn-light'> |
|
|
{{e['slot']}} |
|
|
</span>"> |
|
|
{{e["text"]}} <span class="badge" style="background-color: rgb(246,123,74); |
|
|
color: rgb(255, 255, 255); |
|
|
">{{e["pred_slot"]}}</span> |
|
|
</button> |
|
|
{% endif %} |
|
|
{% endfor %} |
|
|
<hr /><br /> |
|
|
{% endfor %} |
|
|
<div class="row"> |
|
|
<div class="col"><button type="button" class="btn btn-outline-light text-dark" |
|
|
style="box-shadow: 2px 2px 7px 1px rgba(210, 210, 210, 0.42);" onclick="jump('/?page={{page - 1}}')">← Last |
|
|
Page</button></div> |
|
|
<div class="col" style="justify-content: center;display: flex;align-content: center;align-items: center;"> |
|
|
<div class="row" style="width: 230px;"> |
|
|
<div class="col" style="display: flex; align-items: center;">Page Index:</div> |
|
|
<div class="col"> |
|
|
<div class="input-group"> |
|
|
<input type="text" class="form-control" id="inputs" value="{{page}}"> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
</div> |
|
|
<script> |
|
|
var inputDom = document.getElementById('inputs'); |
|
|
inputDom.onblur = function () { |
|
|
var n = Number(inputDom.value); |
|
|
if (!isNaN(n)){ |
|
|
window.location.href = '/?page=' + inputDom.value; |
|
|
} |
|
|
|
|
|
}; |
|
|
function jump(url){ window.location.href=url;} |
|
|
</script> |
|
|
<div class="col" style="display: flex; justify-content: flex-end; padding-right: 40px;"><button |
|
|
type="button" class="btn btn-outline-light text-dark" |
|
|
style="box-shadow: 2px 2px 7px 1px rgba(210, 210, 210, 0.42);" onclick="jump('/?page={{page + 1}}')">Next |
|
|
Page →</button></div> |
|
|
</div> |
|
|
|
|
|
|
|
|
</div> |
|
|
</div> |
|
|
|
|
|
</body> |
|
|
<script> |
|
|
var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]')) |
|
|
var popoverList = popoverTriggerList.map(function (popoverTriggerEl) { |
|
|
return new bootstrap.Popover(popoverTriggerEl, { |
|
|
"html": true, |
|
|
"placement": "bottom" |
|
|
}) |
|
|
}); |
|
|
</script> |
|
|
|
|
|
</html> |