blob: 0cb9f63270b784330220fb6ce1080adf4f60e553 [file] [log] [blame]
Marc Kupietz83305222016-04-28 09:57:22 +02001<!DOCTYPE html>
2<html>
3 <head>
4 <title>DeReKo-Word-Vector-Distances: <%= $word %></title>
Marc Kupietz80bd7b92017-07-04 16:25:54 +02005 <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
6 <script src="http://code.jquery.com/jquery-latest.min.js"></script>
Marc Kupietz4abcd682017-11-28 20:51:08 +01007 <script src = "https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
8 <script src = "https://cdn.datatables.net/fixedcolumns/3.2.3/js/dataTables.fixedColumns.min.js"></script>
9 <link rel="stylesheet" href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css">
Marc Kupietz80bd7b92017-07-04 16:25:54 +020010 <script
Marc Kupietz4abcd682017-11-28 20:51:08 +010011src="http://code.jquery.com/ui/1.12.1/jquery-ui.min.js"
12integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU="
13crossorigin="anonymous"></script>
Marc Kupietz80bd7b92017-07-04 16:25:54 +020014 <script>
Marc Kupietz4abcd682017-11-28 20:51:08 +010015 $('#firstable').hide();
16 $(document).ready(function() {
17 $("#xxxtabs").tabs( {
18 "show": function(event, ui) {
19 var oTable = $('div.dataTables_scrollBody>table.display', ui.panel).dataTable();
20 if ( oTable.length > 0 ) {
21 oTable.fnAdjustColumnSizing();
22 }
23 }
24 } );
Marc Kupietz694610d2017-11-25 18:30:03 +010025
Marc Kupietz4abcd682017-11-28 20:51:08 +010026 $(".selector").tabs({ active: 1 });
Marc Kupietz0af83e32017-11-27 09:31:37 +010027
Marc Kupietz4abcd682017-11-28 20:51:08 +010028 $('#firsttable').DataTable({
29 "sScrollY": "780px",
30 "bScrollCollapse": true,
31 "bPaginate": false,
32 "bJQueryUI": true,
33 "dom": '<"top">rt<"bottom"flp><"clear">',
34 "aoColumnDefs": [
35 { "sWidth": "10%", "aTargets": [ -1 ] }
36 ]
37 } );
Marc Kupietz0af83e32017-11-27 09:31:37 +010038
39 $('#secondtable').DataTable({
Marc Kupietz4abcd682017-11-28 20:51:08 +010040 "sScrollY": "800px",
41 "bScrollCollapse": true,
42 "bPaginate": false,
43 "bJQueryUI": true,
44 "dom": '<"top">rt<"bottom"flp><"clear">',
45 "aoColumnDefs": [
46 { "sWidth": "10%", "aTargets": [ -1 ] }
47 ]
48 } );
49 });
Marc Kupietz0af83e32017-11-27 09:31:37 +010050
Marc Kupietz4abcd682017-11-28 20:51:08 +010051 $( function() {
52 $( "#iterations" ).spinner({
53 spin: function( event, ui ) {
54 if ( ui.value < 1000 ) {
55 $( this ).spinner( "value", 1000 );
56 return false;
57 } else if ( ui.value > 10000 ) {
58 $( this ).spinner( "value", 10000 );
59 return false;
60 }
61 }
62 });
63 } );
Marc Kupietz3305b0a2017-11-27 10:46:20 +010064
Marc Kupietz4abcd682017-11-28 20:51:08 +010065 $( function() {
66 $( "#neighbours" ).spinner({
67 spin: function( event, ui ) {
68 if ( ui.value < 0 ) {
69 $( this ).spinner( "value", 0 );
70 return false;
71 } else if ( ui.value > 200 ) {
72 $( this ).spinner( "value", 200 );
73 return false;
74 }
75 }
76 });
77 } );
78
79 $( function() {
80 $( "#cutoff" ).spinner({
81 spin: function( event, ui ) {
82 if ( ui.value < 100000 ) {
83 $( this ).spinner( "value", 100000 );
84 return false;
85 } else if ( ui.value > 2000000 ) {
86 $( this ).spinner( "value", 2000000 );
87 return false;
88 }
89 }
90 });
91 } );
92
93 $( function() {
94 $( "#tabs" ).tabs();
95 } );
96
97 $( function() {
98 $( ".controlgroup-vertical" ).controlgroup({
99 "direction": "vertical"
100 });
101 } );
102
103 $(function() {
104 $( document ).tooltip({
105 content: function() {
106 return $(this).attr('title');
107 }}
108 )
Marc Kupietz83305222016-04-28 09:57:22 +0200109 })
Marc Kupietz694610d2017-11-25 18:30:03 +0100110
Marc Kupietz83305222016-04-28 09:57:22 +0200111 </script>
112 <script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
Marc Kupietz554aff52017-11-09 14:42:09 +0100113 <script src="/derekovecs/js/tsne.js"></script>
114 <script src="/derekovecs/js/som.js"></script>
115 <script src="/derekovecs/js/labeler.js"></script>
Marc Kupietz83305222016-04-28 09:57:22 +0200116 <style>
117 body, input {
118 font-family: Arial, sans-serif;
119 font-size: 11pt;
120 }
Marc Kupietz30ca4342017-11-22 21:21:20 +0100121
122 .mono {
123 font-family: "DejaVu Sans Mono", Inconsolata, SourceCodePro, Courier;
124 }
125
Marc Kupietz83305222016-04-28 09:57:22 +0200126 .ui-tooltip-content {
127 font-size: 9pt;
128 color: #222222;
129 }
130
131 svg > .ui-tooltip-content {
132 font-size: 8pt;
133 color: #222222;
134 }
135
136 a.merged {
137 color: green;
138 fill: green;
139 }
140
141 #first a {
142 text-decoration: none;
143 }
144
145 a.marked, #first a.marked {
146 text-decoration: underline;
147 }
Marc Kupietzf4b49392016-04-28 10:49:56 +0200148
Marc Kupietz83305222016-04-28 09:57:22 +0200149 a.target {
150 color: red;
151 fill: red;
152 }
Marc Kupietz694610d2017-11-25 18:30:03 +0100153
Marc Kupietz4abcd682017-11-28 20:51:08 +0100154 table.display {
155 width: 40% important!;
156 margin: 1; /* <- works for me this way ****/
157 }
158 table.dataTable thead th, table.dataTable thead td, table.dataTable tbody td {
159 padding: 2px 2px;
160 // border-bottom: 1px solid #111;
161 }
Marc Kupietz83305222016-04-28 09:57:22 +0200162 #collocators {
163 margin-bottom: 15px;
164 }
165
Marc Kupietz4abcd682017-11-28 20:51:08 +0100166 #topwrapper {
Marc Kupietz83305222016-04-28 09:57:22 +0200167 width: 100%;
168 // border: 1px solid red;
169 overflow: hidden; /* will contain if #first is longer than #second */
170 }
Marc Kupietz4abcd682017-11-28 20:51:08 +0100171
172 #wrapper {
173 width: 1200px;
174 // border: 1px solid red;
175 overflow: hidden; /* will contain if #first is longer than #second */
176 }
177
178 #options {
179 float: right;
180 margin: 20px;
181 max-width: 280px;
182 overflow: hidden; /* if you don't want #second to wrap below #first */
183 }
184
Marc Kupietz83305222016-04-28 09:57:22 +0200185 #first {
186 margin-right: 20px;
187 float: left;
Marc Kupietz4abcd682017-11-28 20:51:08 +0100188 overflow: hidden; /* if you don't want #second to wrap below #first */
Marc Kupietz83305222016-04-28 09:57:22 +0200189 // border: 1px solid green;
190 }
Marc Kupietz4abcd682017-11-28 20:51:08 +0100191 #tabs {
192 margin-right: 20px;
193 overflow: hidden; /* if you don't want #second to wrap below #first */
194 }
195
196 #embed {
197 max-width: 802px;
198 border: 1px solid #333;
199 }
200
Marc Kupietz83305222016-04-28 09:57:22 +0200201 #second {
Marc Kupietz4abcd682017-11-28 20:51:08 +0100202// border: 1px solid #333;
Marc Kupietz83305222016-04-28 09:57:22 +0200203 overflow: hidden; /* if you don't want #second to wrap below #first */
204 }
205 #som2 svg {
206 border: 1px solid #333;
207 }
208
209 #cost {
210 font-size: 8pt;
211 color: #222222;
212 margin-top: 4px;
213 margin-bottom: 12px;
214 }
215
216 #sominfo1, #sominfo {
217 font-size: 8pt;
218 color: #222222;
219 margin-top: 0px;
220 }
221
222 #somcolor1, #somcolor2, #somcolor3 {
223 display: inline-block;
224 height: 10px;
225 width: 10px;
226 }
227
228 #third {
229 border: 1px solid #333;
230 }
231
232 </style>
233 <script>
234
235 var opt = {epsilon: <%= $epsilon %>, perplexity: <%= $perplexity %>},
236 mapWidth = 800, // width map
237 mapHeight = 800,
238 jitterRadius = 7;
239
240 var T = new tsnejs.tSNE(opt); // create a tSNE instance
241
242 var Y;
243
244 var data;
245 var labeler;
246
247 function applyJitter() {
Marc Kupietz4abcd682017-11-28 20:51:08 +0100248 svg.selectAll('.tsnet')
249 .data(labels)
250 .transition()
251 .duration(50)
252 .attr("transform", function(d, i) {
253 T.Y[i][0] = (d.x - mapWidth/2 - tx)/ss/20;
254 T.Y[i][1] = (d.y - mapHeight/2 - ty)/ss/20;
255 return "translate(" +
256 (d.x) + "," +
257 (d.y) + ")";
258 });
Marc Kupietz83305222016-04-28 09:57:22 +0200259 }
260
261 function updateEmbedding() {
Marc Kupietz4abcd682017-11-28 20:51:08 +0100262 var Y = T.getSolution();
263 svg.selectAll('.tsnet')
264 .data(data.words)
265 .attr("transform", function(d, i) {
266 return "translate(" +
267 ((Y[i][0]*20*ss + tx) + mapWidth/2) + "," +
268 ((Y[i][1]*20*ss + ty) + mapHeight/2) + ")"; });
Marc Kupietz83305222016-04-28 09:57:22 +0200269 }
270
271 var svg;
272 var labels = [];
273 var anchor_array = [];
274 var text;
275
276 function drawEmbedding() {
Marc Kupietz4abcd682017-11-28 20:51:08 +0100277 $("#embed").empty();
278 var div = d3.select("#embed");
279
280 // get min and max in each column of Y
281 var Y = T.Y;
282
283 svg = div.append("svg") // svg is global
284 .attr("width", mapWidth)
285 .attr("height", mapHeight);
286
287 var g = svg.selectAll(".b")
288 .data(data.words)
289 .enter().append("g")
290 .attr("class", "tsnet");
291
292 g.append("a")
293 .attr("xlink:href", function(word) {
294 return (data.urlprefix+word);})
295 .attr("class", function(d, i) {
296 var res="";
297 if(data.marked[i]) {
298 res="marked ";
299 }
300 if(data.target.indexOf(" "+d+" ") >= 0) {
301 return res+"target";
302 } else if(data.ranks[i] < data.mergedEnd) {
303 return res+"merged";
304 } else {
305 return res;
306 }
307 })
308 .attr("title", function(d, i) {
309 if(data.mergedEnd > 0) {
310 if(data.ranks[i] >= data.mergedEnd) {
311 return "rank: "+i +" "+"freq. rank: "+(data.ranks[i]).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
312 } else {
313 return "rank: "+i +" "+"freq. rank: "+data.ranks[i].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + " (merged vocab)";
314 }
315 } else {
316 return "rank: "+i +" "+"freq. rank: "+data.ranks[i].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
317 }
318 })
319 .append("text")
320 .attr("text-anchor", "top")
321 .attr("font-size", 12)
322 .text(function(d) { return d; });
323
324 var zoomListener = d3.behavior.zoom()
325 .scaleExtent([0.1, 10])
326 .center([0,0])
327 .on("zoom", zoomHandler);
328 zoomListener(svg);
Marc Kupietz83305222016-04-28 09:57:22 +0200329 }
330
331 var tx=0, ty=0;
332 var ss=1;
333 var iter_id=-1;
334
335 function zoomHandler() {
Marc Kupietz4abcd682017-11-28 20:51:08 +0100336 tx = d3.event.translate[0];
337 ty = d3.event.translate[1];
338 ss = d3.event.scale;
339 updateEmbedding();
Marc Kupietz83305222016-04-28 09:57:22 +0200340 }
341
342 var stepnum = 0;
343
344 function stopStep() {
Marc Kupietz4abcd682017-11-28 20:51:08 +0100345 clearInterval(iter_id);
346 text = svg.selectAll("text");
347
348 // jitter function needs different data and co-ordinate representation
349 labels = d3.range(data.words.length).map(function(i) {
350 var x = (T.Y[i][0]*20*ss + tx) + mapWidth/2;
351 var y = (T.Y[i][1]*20*ss + ty) + mapHeight/2;
352 anchor_array.push({x: x, y: y, r: jitterRadius});
353 return {
354 x: x,
355 y: y,
356 name: data.words[i]
357 };
358 });
359
360 // get the actual label bounding boxes for the jitter function
361 var index = 0;
362 text.each(function() {
363 labels[index].width = this.getBBox().width;
364 labels[index].height = this.getBBox().height;
365 index += 1;
366 });
Marc Kupietz83305222016-04-28 09:57:22 +0200367
Marc Kupietz4abcd682017-11-28 20:51:08 +0100368
369 // setTimeout(updateEmbedding, 1);
370 // setTimeout(
371 labeler = d3.labeler()
372 .label(labels)
373 .anchor(anchor_array)
374 .width(mapWidth)
375 .height(mapHeight)
376 .update(applyJitter);
377 // .start(1000);
Marc Kupietz83305222016-04-28 09:57:22 +0200378
Marc Kupietz4abcd682017-11-28 20:51:08 +0100379 iter_id = setInterval(jitterStep, 1);
Marc Kupietz83305222016-04-28 09:57:22 +0200380 }
381
382 var jitter_i=0;
383
384 function jitterStep() {
Marc Kupietz4abcd682017-11-28 20:51:08 +0100385 if(jitter_i++ > 100) {
386 clearInterval(iter_id);
387 } else {
388 labeler.start2(10);
389 applyJitter();
390 }
Marc Kupietz83305222016-04-28 09:57:22 +0200391 }
392
393 var last_cost=1000;
394
395 function step() {
Marc Kupietz4abcd682017-11-28 20:51:08 +0100396 var i = T.iter;
397
398 if(i > <%= $no_iterations %>) {
399 stopStep();
400 } else {
401 var cost = Math.round(T.step() * 100000) / 100000; // do a few steps
402 $("#cost").html("tsne iteration " + i + ", cost: " + cost.toFixed(5));
403 if(i % 250 == 0 && cost >= last_cost) {
404 stopStep();
405 } else {
406 last_cost = cost;
407 updateEmbedding();
408 }
409 }
Marc Kupietz83305222016-04-28 09:57:22 +0200410 }
411
412 function showMap(j) {
Marc Kupietz4abcd682017-11-28 20:51:08 +0100413 data=j;
414 T.iter=0;
415 T.initDataRaw(data.vecs); // init embedding
416 drawEmbedding(); // draw initial embedding
417
418 if(iter_id >= 0) {
419 clearInterval(iter_id);
420 }
421 //T.debugGrad();
422 iter_id = setInterval(step, 1);
423 if(<%= $show_som %>) {
424 makeSOM(j, <%= $no_iterations %>);
425 }
Marc Kupietz83305222016-04-28 09:57:22 +0200426 }
Marc Kupietz39179ab2017-07-04 16:28:06 +0200427 var queryword;
428
429 function onload() {
Marc Kupietz4abcd682017-11-28 20:51:08 +0100430 queryword = document.getElementById('word');
Marc Kupietz39179ab2017-07-04 16:28:06 +0200431 }
432
433 function queryKorAP() {
434 window.open('http://korap.ids-mannheim.de/kalamar/?q='+queryword.value, 'KorAP');
435 }
Marc Kupietz4dc270c2017-11-24 10:17:12 +0100436
437 function queryKorAPCII(query) {
438 window.open('http://korap.ids-mannheim.de/kalamar/?ql=cosmas2&q='+query, 'KorAP');
439 }
Marc Kupietz83305222016-04-28 09:57:22 +0200440 </script>
441 </head>
Marc Kupietz39179ab2017-07-04 16:28:06 +0200442 <body onload="onload()">
Marc Kupietz4abcd682017-11-28 20:51:08 +0100443 <div id="topwrapper">
444 <div id="options" class="widget">
445 <form>
446 <input id="word" type="text" name="word" size="20" placeholder="Word(s) to be searched" value="<%= $word %>"
447 title="When looking for multiple words use spaces as separators to search around the average vector and | as separator to get the neighbours for each word."/>
448 <input type="submit" value="SEARCH">
449 <fieldset>
450 <legend>Settings</legend>
451 <div class="controlgroup-vertical">
452 <label for="cutoff">cut-off</label>
453 <input id="cutoff" type="text" name="cutoff" size="10" value="<%= $cutoff %>" title="Only consider the most frequent x word forms.">
454 <label for="dedupe">dedupe</label>
455 <input id="dedupe" type="checkbox" name="dedupe" value="1" <%= ($dedupe ? "checked" : "") %> title="radically filter out any near-duplicates">
456 % if($mergedEnd > 0) {
457 <label for="sbf">backw.</label>
458 <input id="sbf" type="checkbox" name="sbf" value="1" <%= ($searchBaseVocabFirst ? "checked" : "") %> title="If checkecked base vocabulary will be searched first. Otherwise merged vocabulray will be searched first.">
459 % }
460 <label for="neighbours">max. neighbours:</label>
461 <input id="neighbours" size="4" name="n" value="<%= $no_nbs %>">
462 <label for="iterations">max. iterations</label>
463 <input id="iterations" name="N" size="4" value="<%= $no_iterations %>">
464 <label for="dosom">SOM</label>
465 <input id="dosom" type="checkbox" name="som" value="1" <%= ($show_som ? "checked" : "") %>>
466 % if($collocators) {
467 <label for="sortby">window/sort</label>
468 <select id="sortby" name="sort">
469 <option value="0" <%= ($sort!=1 && $sort!=2? "selected":"") %>>auto focus</option>
470 <option value="1" <%= ($sort==1? "selected":"") %>>any single position</option>
471 <option value="2" <%= ($sort==2? "selected":"") %>>whole window</option>
472 </select>
473 % }
474 <span> </span><input type="button" value="→ KorAP" onclick="queryKorAP();" title="query word with KorAP"/>
475 <br>
476 </div>
477 </fieldset>
478 </form>
Marc Kupietz0af83e32017-11-27 09:31:37 +0100479 </div>
Marc Kupietz4abcd682017-11-28 20:51:08 +0100480 <div id="tabs">
481 <ul>
482 <li><a href="#tabs-1">Semantics</a></li>
483 <li><a href="#tabs-2">Syntagmatic (collocators)</a></li>
484 </ul>
485 <div id="tabs-1">
486 % if($lists && (@$lists) > 0 && (@$lists)[0]) {
487 <div id="wrapper">
488 <div id="first" style="width:220px">
489 <table class="display compact nowrap" id="firsttable">
490 <thead>
491 <tr>
492 <th align="right">#</th><th align="right">cos</th><th align="left">paradigmatic</th>
493 </tr>
494 </thead>
495 <tbody>
496 % my $j=0; my @words; my @vecs; my @ranks; my @marked;
497 % for my $list (@$lists) {
498 % my $i=0; while($list) {
499 % my $item = (@$list)[$i];
500 % my $c = ($collocators? (@$collocators)[$i] : 0);
501 % last if(!$c && !$item);
502 <tr>
503 <td align="right">
504 <%= ++$i %>.
505 </td>
506 % if($item) {
507 % if(!grep{$_ eq $item->{word}} @words) {
508 % push @vecs, $item->{vector};
509 % push @words, $item->{word};
510 % push @ranks, $item->{rank};
511 % push @marked, ($marked->{$item->{word}}? 1 : 0);
512 % }
513 <td align="right">
514 <%= sprintf("%.3f", $item->{dist}) %>
515 </td>
516 <td>
517 % my $class = ($marked->{$item->{word}}? "marked " : "");
518 % my $r = $item->{rank};
519 % if($r < $mergedEnd) {
520 % $class .= "merged";
521 % $r .= " (merged vocab)";
522 % } elsif($mergedEnd!=0 && $r > $mergedEnd) {
523 % $r -= $mergedEnd;
524 % }
525 <a class="<%= $class =%>"
526 title="freq. rank: <%= $r =%>"
527 href="<%= url_with->query([word => $item->{word}]) =%>">
528 <%= $item->{word} =%>
529 </a>
530 </td>
531 % } else {
532 <td colspan="2"/>
533 % }
534 </tr>
535 % last if($i >= 100);
536 % }
537 % }
538 </tbody>
539 </table>
540 </div>
541 <script>
542 % use Mojo::ByteStream 'b';
543 % my $urlprefix = url_with->query([word=>'']);
544 $(window).load(function() {
545 showMap(<%= b(Mojo::JSON::to_json({target => " $word ", mergedEnd=> $mergedEnd, words => \@words, vecs => \@vecs, ranks => \@ranks, marked => \@marked, urlprefix => $urlprefix})); %>);
546 });
547 </script>
548 % } else {
549 <div id="wrapper">
550 <p>
551 ERROR: "<%= $word %>" not found in vocabluary.
552 </p>
553 </div>
554 % }
555 <div id="second">
556 <div id="embed">
557 </div>
558 <div id="cost">
559 </div>
560 % if($show_som) {
561 <div id="som2">
562 </div>
563 <div id="sominfo1"><span id="somcolor1"> </span> <span id="somword1"> </span> <span id="somcolor2"> </span> <span id="somword2"> </span> <span id="somcolor3"> </span></div>
564 <div id="sominfo">SOM iteration <span id="iterations">0</span></div>
565 % }
566 </div>
567 </div>
568 </div>
569 <div id="tabs-2">
570 <div id="second" style="width:500px">
571 <table class="display compact nowrap" id="secondtable">
572 <thead>
573 <tr>
574 % if($collocators) {
575 <th>#</th>
576 <th align="right" title="The window around the target word that is considered for summation.">w'</th>
577 <th align="right" title="Raw (max.) activation of the collocator in the output layers.">a</th>
578 <th title="Σp(c<sub><small>@</small></sub>) – Sum of the probability approximations that the combination of the target word and the collocator at the relative position @ come from the training corpus. Single approximations can be distorted because of sub-sampling frequent words and the sum cannot itself be interpreted as probability." align="right">Σp</th>
579 <th align="right">Σp/|w|</th>
580 <th title="c" align="left">collocator</th>
581 % }
582 </tr>
583 </thead>
584 <tbody>
585 % for(my $i=0; $i < 100; $i++) {
586 % my $c = ($collocators? (@$collocators)[$i] : 0);
587 <tr>
588 <td align="right">
589 <%= $i %>
590 </td>
591 % if($c) {
592 <td align="right">
593 <span class="mono"><%= bitvec2window( $c->{pos} ) %></span>
594 </td>
595 <td align="right">
596 <%= sprintf("%.3f", $c->{dist}) %>
597 </td>
598 <td align="right">
599 <%= sprintf("%.3e", $c->{norm}) %>
600 </td>
601 <td align="right">
602 <%= sprintf("%.3e", $c->{sum}) %>
603 </td>
604 <td align="left">
605 <a onclick="<%= sprintf("queryKorAPCII('%s /w5 %s')", $c->{word}, $word) =%>"
606 title="freq. rank: <%= $c->{rank} =%>">
607 <%= $c->{word} %>
608 </a>
609 </td>
610 % } else {
611 <td colspan="5"/>
612 % }
613 </tr>
614 % }
615 </tbody>
616 </table>
617 </div> <!-- - tab2 -->
618 </div> <!-- tabs -->
619 </div> <!-- topwrapper -->
620 <div style="clear: both;"></div>
Marc Kupietz0af83e32017-11-27 09:31:37 +0100621 </div>
Marc Kupietz4abcd682017-11-28 20:51:08 +0100622 % if($training_args) {
623 <p>
624 Word vector model trained with <a href="https://code.google.com/p/word2vec/">word2vec</a> using the following parameters: <pre><%= $training_args %></pre>
625 </p>
Marc Kupietz83305222016-04-28 09:57:22 +0200626 % }
Marc Kupietz4abcd682017-11-28 20:51:08 +0100627 </body>
Marc Kupietz83305222016-04-28 09:57:22 +0200628</html>