拿 ml5 来练习 如何附加自己的分类在别人的情绪之上 (五)

介绍

首先介绍什麽是如何附加自己的分类在别人的情绪之上
对别人已经训练好的情绪 model,我们对这个 model 的某一次输入及输出,打上一个标签,
但因为我们不可能帮所有的输入及输出打上标签,我们可以透过 ml5 的 KNNClassifier
就可以很简单地,自动地将他的情绪及其他造成他这样情绪的文字,打上一个最相近的标签。

第一阶段备料

接着备料,
将上一章的 sketch_sentiment.js,改写成如下所示。

let sentiment;

let statusEl;
let inputBox;
let submitBtn;
let sentimentResult;

let addshow;
let labelBox;
let buttonAddLabel;
let buttonShowLabel;
let predictResult;

let saveload;
let buttonSetData;
let buttonGetData;

function setup() {
    // initialize sentiment
    sentiment = ml5.sentiment('movieReviews', modelReady);

    noCanvas();


    statusEl = createP('loading model...');

    inputBox = createInput();
    inputBox.attribute('size', '75');

    submitBtn = createButton('submit');
    submitBtn.mousePressed(getSentiment);

    sentimentResult = createP('sentiment score:');


    addshow = createP();

    labelBox = createInput();
    labelBox.attribute('size', '15');
    labelBox.parent(addshow);

    buttonAddLabel = createButton('add label');
    buttonAddLabel.mousePressed(addExample);
    buttonAddLabel.parent(addshow);

    buttonShowLabel = createButton('show label');
    buttonShowLabel.mousePressed(classify);
    buttonShowLabel.parent(addshow);
    buttonShowLabel.hide();

    predictResult = createP('addExample count:');
    predictResult.parent(addshow);


    saveload = createP();

    buttonSetData = createButton('Save Dataset');
    buttonSetData.mousePressed(saveMyKNN);
    buttonSetData.parent(saveload);

    buttonGetData = createButton('Load Dataset');
    buttonGetData.mousePressed(loadMyKNN);
    buttonGetData.parent(saveload);
}


function modelReady() {
    // model is ready
    statusEl.html('model loaded!');
}


let text;
let prediction;
function getSentiment() {
    // get the values from the input
    text = inputBox.value();

    // make the prediction
    prediction = sentiment.predict(text);
    statusEl.html('get new sentiment score!');

    // display sentiment result on html page
    sentimentResult.html('sentiment score: ' + prediction.score);
}


const knnClassifier = ml5.KNNClassifier();

let count = 0;
function addExample() {
    const inputLabel = labelBox.value();

    if (inputLabel) {
        knnClassifier.addExample(getTensor(), inputLabel);

        predictResult.html('addExample count: ' + ++count);
        prediction = null;
        statusEl.html('addExample OK');

        labelBox.value('');
    }
}
function getTensor() {
    if (!prediction) {
        getSentiment();
    }

    const _text = text.padEnd(256).substr(0, 256);

    return _text.split('').map(p => [prediction.score, p.charCodeAt(0) / 100]);
}

function classify() {
    // Get the total number of labels from knnClassifier
    if (knnClassifier.getNumLabels() == 0) {
        statusEl.html('no example in any label.');
        return;
    }

    // Use knnClassifier to classify which label do these features belong to
    knnClassifier.classify(getTensor(), gotResults);
}
function gotResults(err, result) {
    if (err) {
        console.log(err);
    }
    console.log(result);

    if (result.confidencesByLabel) {
        predictResult.html(JSON.stringify(result.confidencesByLabel));
        prediction = null;
        statusEl.html('classify OK');
    }
}


// Save dataset as myKNNDataset.json
function saveMyKNN() {
    knnClassifier.save('myKNNDataset');
}

// Load dataset to the classifier
function loadMyKNN() {
    knnClassifier.load('./myKNNDataset.json', updateCounts);
}
function updateCounts() {
    predictResult.html('labels number: ' + knnClassifier.getNumLabels());
    console.log(knnClassifier.getCount());
    console.log(knnClassifier.getCountByLabel());
    labelBox.hide();
    buttonAddLabel.hide();
    buttonShowLabel.show();
}

第一阶段执行

备料完成後,就可启动 Live Server,
在 VS Code 里的 sentiment.html 程序码按右键,在显示的内容选单里,点选 Open with Live Server
就可显示如下画面。
https://ithelp.ithome.com.tw/upload/images/20201102/20132156lZOMHqfL3G.png

第二阶段备料

  1. 在第一个输入框内输入 A,按下右边的 submit 按钮,会得到如下画面。
    https://ithelp.ithome.com.tw/upload/images/20201102/20132156vXxDQYsokn.png
  2. 在第二个输入框内输入 快乐,按下右边的 add label 按钮,表示对输入的文字及输出的情绪,打上一个标签,结果如下。
    https://ithelp.ithome.com.tw/upload/images/20201102/201321568TsNZvV2sg.png
  3. 接下来再回到第一个输入框内输入 B,按下右边的 submit 按钮,然後在第二个输入框内输入 紧张,按下右边的 add label 按钮,会发现 addExample count 的数字会变成2
  4. 接下来再回到第一个输入框内输入 C,按下右边的 submit 按钮,然後在第二个输入框内输入 生气,按下右边的 add label 按钮,会发现 addExample count 的数字会变成3
  5. 接下来再回到第一个输入框内输入 D,按下右边的 submit 按钮,然後在第二个输入框内输入 忧伤,按下右边的 add label 按钮,会发现 addExample count 的数字会变成4
  6. 接下来再回到第一个输入框内输入 E,按下右边的 submit 按钮,然後在第二个输入框内输入 厌恶,按下右边的 add label 按钮,会发现 addExample count 的数字会变成5,出现数字5之後,按下下方的 Save Dataset 按钮,会下载一个档案,名叫 myKNNDataset.json,将以已下载的档案移到 hello-ml5 目录下,如下图所示。
    https://ithelp.ithome.com.tw/upload/images/20201102/20132156D3s6AigmlU.png
  7. 移好之後,按下 Load Dataset 按钮,会出现 labels number: 5 讯息,若在 hello-ml5 目录下没有 档案 myKNNDataset.json 或没有载入成功,则不会出现这样的讯息。

第二阶段执行

备料完成後,就可重新载入此网页,按下 Load Dataset 按钮,画面就会如下所示。
https://ithelp.ithome.com.tw/upload/images/20201102/20132156pdXEuSUMpI.png

测试

在输入框内输入 love,记得先按下右边的 submit 按钮,再按下 show label 按钮,结果如下图所示。
https://ithelp.ithome.com.tw/upload/images/20201102/20132156doyIYlg7PB.png

所以,已被纪录之别人的情绪,对 love 这个字而言,会介於我所分类的【快乐、紧张、厌恶】这些标签之间。

此外,如果觉得哪个分类很奇怪,可以将 sketch_sentiment.js 里的程序码,

    labelBox.hide();
    buttonAddLabel.hide();

注解掉,重新载入网页,并重新载入 myKNNDataset.json 之後,就可以对某个已取得情绪分数之有问题的文字,加入自己所认知的标签,
对相同的文字加入相同的标签越多次,则此标签对此文字的权重越高,这是 KNN 的特性,权重变更之後,就可以再按下 show label 按钮,确认结果是否正确,
确认後,按下 Save Dataset 按钮,下载新的 myKNNDataset.json 取代放在 hello-ml5 里旧的 myKNNDataset.json,这样重新载入 sentiment.html 时才可以使用新的权重。

参考资料

https://www.youtube.com/watch?v=KTNqXwkLuM4
https://www.youtube.com/watch?v=Mwo5_bUVhlA
https://www.youtube.com/watch?v=JWsKay58Z2g


<<:  鼠年全马铁人挑战 WEEK 37:封包测试工具 - Charles (二)

>>:  IP资料单元(Datagram)或封包(Packet)?

[Day17] 第十七章-Skill的反向定义关系

前言 今天因为电脑?不在身边 我们今天就把 skill的反向设定完就好了吧 图片会在之後补上喔! 实...

Day 22 「戏如人生」以真实案例分析 Clean Architecture 的分层原则

相信大家或多或少都有去公家机关办事的经验。去公家机关办事时,如果等待时间拖太久,肯定觉得很烦吧?好不...

CMoney菁英软件工程师战斗营_Week 7

Hi again 本周大部分时间都是在准备游戏专题 在专题中也会需要上周所提及的图片切个制作动画 由...

从零开始学3D游戏开发:零件介面 Part.1 开始

这是 Roblox 从零开始系列,使用者介面章节的第五个单元,你将要学会如何开始在零件的表面上去设计...