使用ML.NET实现猜动画片台词

前面几篇主要内容出自微软官方,经我特意修改的案例的文章:

使用ML.NET实现情感分析[新手篇]

使用ML.NET预测纽约出租车费

.NET Core玩转机器学习

使用ML.NET实现情感分析[新手篇]后补

相信看过后大家对ML.NET有了一定的了解了,由于目前还是0.1的版本,也没有更多官方示例放出来,大家普遍觉得提供的特性还不够强大,所以处在观望状态也是能理解的。

本文结合Azure提供的语音识别服务,向大家展示另一种ML.NET有趣的玩法——猜动画片台词。

这个场景特别容易想像,是一种你说我猜的游戏,我会事先用ML.NET对若干动画片的台词进行分类学习,然后使用麦克风,让使用者随便说一句动画片的台词(当然得是数据集中已存在的,没有的不要搞事情呀!),然后来预测出自哪一部。跟随我动手做做看。

准备工作



这次需要使用Azure的认知服务中一项API——Speaker Recognition,目前还处于免费试用阶段,打开https://azure.microsoft.com/zh-cn/try/cognitive-services/?api=speaker-recognition,能看到如下页面:

点击获取API密钥,用自己的Azure账号登录,然后就能看到自己的密钥了,类似如下图:

创建项目



这一次请注意,我们要创建一个.NET Framework 4.6.1或以上版本的控制台应用程序,通过NuGet分别引用三个类库:Microsoft.ML,JiebaNet.Analyser,Microsoft.CognitiveServices.Speech。

然后把编译平台修改成x64,而不是Any CPU。(这一点非常重要)

代码分解



在Main函数部分,我们只需要关心几个主要步骤,先切词,然后训练模型,最后在一个循环中等待使用者说话,用模型进行预测。

static void Main(string[] args)
{
    Segment(_dataPath, _dataTrainPath);
    var model = Train();
    Evaluate(model);
    ConsoleKeyInfo x;
    do
    {
        var speech = Recognize();
        speech.Wait();
        Predict(model, speech.Result);
        Console.WriteLine("\nRecognition done. Your Choice (0: Stop Any key to continue): ");
        x = Console.ReadKey(true);
    } while (x.Key != ConsoleKey.D0);
}

初始化的变量主要就是训练数据,Azure语音识别密钥等。注意YourServiceRegion的值是“westus”,而不是网址。

const string SubscriptionKey = "你的密钥";
const string YourServiceRegion = "westus";
const string _dataPath = @".\data\dubs.txt";
const string _dataTrainPath = @".\data\dubs_result.txt";

定义数据结构和预测结构和我之前的文章一样,没有什么特别之处。

public class DubbingData
{
    [Column(ordinal: "0")]
    public string DubbingText;
    [Column(ordinal: "1", name: "Label")]
    public string Label;
}

public class DubbingPrediction
{
    [ColumnName("PredictedLabel")]
    public string PredictedLabel;
}

切记部分注意对分隔符的过滤。

public static void Segment(string source, string result)
{
    var segmenter = new JiebaSegmenter();
    using (var reader = new StreamReader(source))
    {
        using (var writer = new StreamWriter(result))
        {
            while (true)
            {
                var line = reader.ReadLine();
                if (string.IsNullOrWhiteSpace(line))
                    break;
                var parts = line.Split(new[] { ‘\t‘ }, StringSplitOptions.RemoveEmptyEntries);
                if (parts.Length != 2) continue;
                var segments = segmenter.Cut(parts[0]);
                writer.WriteLine("{0}\t{1}", string.Join(" ", segments), parts[1]);
            }
        }
    }
}

训练部分依然使用熟悉的多分类训练器StochasticDualCoordinateAscentClassifier。TextFeaturizer用于对文本内容向量化处理。

public static PredictionModel<DubbingData, DubbingPrediction> Train()
{
    var pipeline = new LearningPipeline();
    pipeline.Add(new TextLoader<DubbingData>(_dataTrainPath, useHeader: false, separator: "tab"));
    pipeline.Add(new TextFeaturizer("Features", "DubbingText"));
    pipeline.Add(new Dictionarizer("Label"));
    pipeline.Add(new StochasticDualCoordinateAscentClassifier());
    pipeline.Add(new PredictedLabelColumnOriginalValueConverter() { PredictedLabelColumn = "PredictedLabel" });
    var model = pipeline.Train<DubbingData, DubbingPrediction>();
    return model;
}

验证部分这次重点是看损失程度分数。

public static void Evaluate(PredictionModel<DubbingData, DubbingPrediction> model)
{
    var testData = new TextLoader<DubbingData>(_dataTrainPath, useHeader: false, separator: "tab");
    var evaluator = new ClassificationEvaluator();
    var metrics = evaluator.Evaluate(model, testData);
    Console.WriteLine();
    Console.WriteLine("PredictionModel quality metrics evaluation");
    Console.WriteLine("------------------------------------------");
    //Console.WriteLine($"TopKAccuracy: {metrics.TopKAccuracy:P2}");
    Console.WriteLine($"LogLoss: {metrics.LogLoss:P2}");
}

预测部分没有什么大变化,就是对中文交互进行了友好展示。

public static void Predict(PredictionModel<DubbingData, DubbingPrediction> model, string sentence)
{
    IEnumerable<DubbingData> sentences = new[]
    {
        new DubbingData
        {
            DubbingText = sentence
        }
    };

    var segmenter = new JiebaSegmenter();
    foreach (var item in sentences)
    {
        item.DubbingText = string.Join(" ", segmenter.Cut(item.DubbingText));
    }

    IEnumerable<DubbingPrediction> predictions = model.Predict(sentences);
    Console.WriteLine();
    Console.WriteLine("Category Predictions");
    Console.WriteLine("---------------------");

    var sentencesAndPredictions = sentences.Zip(predictions, (sentiment, prediction) => (sentiment, prediction));
    foreach (var item in sentencesAndPredictions)
    {
        Console.WriteLine($"台词: {item.sentiment.DubbingText.Replace(" ", string.Empty)} | 来自动画片: {item.prediction.PredictedLabel}");
    }
    Console.WriteLine();
}

Azure语音识别的调用如下。

static async Task<string> Recognize()
{
    var factory = SpeechFactory.FromSubscription(SubscriptionKey, YourServiceRegion);
    var lang = "zh-cn";

    using (var recognizer = factory.CreateSpeechRecognizer(lang))
    {
        Console.WriteLine("Say something...");

        var result = await recognizer.RecognizeAsync().ConfigureAwait(false);

        if (result.RecognitionStatus != RecognitionStatus.Recognized)
        {
            Console.WriteLine($"There was an error. Status:{result.RecognitionStatus.ToString()}, Reason:{result.RecognitionFailureReason}");
            return null;
        }
        else
        {
            Console.WriteLine($"We recognized: {result.RecognizedText}");
            return result.RecognizedText;
        }
    }
}

运行过程如下:

虽然这看上去有点幼稚,不过一样让你开心一笑了,不是么?请期待更多有趣的案例。

本文使用的数据集:下载

完整的代码如下:

using System;
using Microsoft.ML.Models;
using Microsoft.ML.Runtime;
using Microsoft.ML.Runtime.Api;
using Microsoft.ML.Trainers;
using Microsoft.ML.Transforms;
using System.Collections.Generic;
using System.Linq;
using Microsoft.ML;
using JiebaNet.Segmenter;
using System.IO;
using Microsoft.CognitiveServices.Speech;
using System.Threading.Tasks;

namespace DubbingRecognition
{
    class Program
    {
        public class DubbingData
        {
            [Column(ordinal: "0")]
            public string DubbingText;
            [Column(ordinal: "1", name: "Label")]
            public string Label;
        }

        public class DubbingPrediction
        {
            [ColumnName("PredictedLabel")]
            public string PredictedLabel;
        }

        const string SubscriptionKey = "你的密钥";
        const string YourServiceRegion = "westus";
        const string _dataPath = @".\data\dubs.txt";
        const string _dataTrainPath = @".\data\dubs_result.txt";

        static void Main(string[] args)
        {
            Segment(_dataPath, _dataTrainPath);
            var model = Train();
            Evaluate(model);
            ConsoleKeyInfo x;
            do
            {
                var speech = Recognize();
                speech.Wait();
                Predict(model, speech.Result);
                Console.WriteLine("\nRecognition done. Your Choice (0: Stop Any key to continue): ");
                x = Console.ReadKey(true);
            } while (x.Key != ConsoleKey.D0);
        }

        public static void Segment(string source, string result)
        {
            var segmenter = new JiebaSegmenter();
            using (var reader = new StreamReader(source))
            {
                using (var writer = new StreamWriter(result))
                {
                    while (true)
                    {
                        var line = reader.ReadLine();
                        if (string.IsNullOrWhiteSpace(line))
                            break;
                        var parts = line.Split(new[] { ‘\t‘ }, StringSplitOptions.RemoveEmptyEntries);
                        if (parts.Length != 2) continue;
                        var segments = segmenter.Cut(parts[0]);
                        writer.WriteLine("{0}\t{1}", string.Join(" ", segments), parts[1]);
                    }
                }
            }
        }

        public static PredictionModel<DubbingData, DubbingPrediction> Train()
        {
            var pipeline = new LearningPipeline();
            pipeline.Add(new TextLoader<DubbingData>(_dataTrainPath, useHeader: false, separator: "tab"));

            //pipeline.Add(new ColumnConcatenator("Features", "DubbingText"));

            pipeline.Add(new TextFeaturizer("Features", "DubbingText"));
            //pipeline.Add(new TextFeaturizer("Label", "Category"));
            pipeline.Add(new Dictionarizer("Label"));
            pipeline.Add(new StochasticDualCoordinateAscentClassifier());
            pipeline.Add(new PredictedLabelColumnOriginalValueConverter() { PredictedLabelColumn = "PredictedLabel" });
            var model = pipeline.Train<DubbingData, DubbingPrediction>();
            return model;
        }

        public static void Evaluate(PredictionModel<DubbingData, DubbingPrediction> model)
        {
            var testData = new TextLoader<DubbingData>(_dataTrainPath, useHeader: false, separator: "tab");
            var evaluator = new ClassificationEvaluator();
            var metrics = evaluator.Evaluate(model, testData);
            Console.WriteLine();
            Console.WriteLine("PredictionModel quality metrics evaluation");
            Console.WriteLine("------------------------------------------");
            //Console.WriteLine($"TopKAccuracy: {metrics.TopKAccuracy:P2}");
            Console.WriteLine($"LogLoss: {metrics.LogLoss:P2}");
        }

        public static void Predict(PredictionModel<DubbingData, DubbingPrediction> model, string sentence)
        {
            IEnumerable<DubbingData> sentences = new[]
            {
                new DubbingData
                {
                    DubbingText = sentence
                }
            };

            var segmenter = new JiebaSegmenter();
            foreach (var item in sentences)
            {
                item.DubbingText = string.Join(" ", segmenter.Cut(item.DubbingText));
            }

            IEnumerable<DubbingPrediction> predictions = model.Predict(sentences);
            Console.WriteLine();
            Console.WriteLine("Category Predictions");
            Console.WriteLine("---------------------");

            var sentencesAndPredictions = sentences.Zip(predictions, (sentiment, prediction) => (sentiment, prediction));
            foreach (var item in sentencesAndPredictions)
            {
                Console.WriteLine($"台词: {item.sentiment.DubbingText.Replace(" ", string.Empty)} | 来自动画片: {item.prediction.PredictedLabel}");
            }
            Console.WriteLine();
        }
        static async Task<string> Recognize()
        {
            var factory = SpeechFactory.FromSubscription(SubscriptionKey, YourServiceRegion);
            var lang = "zh-cn";

            using (var recognizer = factory.CreateSpeechRecognizer(lang))
            {
                Console.WriteLine("Say something...");

                var result = await recognizer.RecognizeAsync().ConfigureAwait(false);

                if (result.RecognitionStatus != RecognitionStatus.Recognized)
                {
                    Console.WriteLine($"There was an error. Status:{result.RecognitionStatus.ToString()}, Reason:{result.RecognitionFailureReason}");
                    return null;
                }
                else
                {
                    Console.WriteLine($"We recognized: {result.RecognizedText}");
                    return result.RecognizedText;
                }
            }
        }
    }
}

原文地址:https://www.cnblogs.com/BeanHsiang/p/9052751.html

时间: 2024-08-11 12:25:33

使用ML.NET实现猜动画片台词的相关文章

湖南6名厅级党员领导干部严重违纪被开除党籍

而那道白光更是冲刺向前利剑一挥一道璀璨的蓝光剑气横扫了出去无数白光飞起措不及防下傲世派出的七名刺客已经有四个被我干掉而剩下的傲世嗜血则在拼命的加血根本就不敢上毕竟我的攻击力他们看在眼里肯定也知道厉害 嚓嚓连续两剑伤害跳起当然是母的凌雪撅嘴嗯为什么啊冰茶眨了眨美丽的大眼睛很不解的看着我 当然单纯的灵儿不会想到自己的作用只是甜甜笑着与我并肩在前面嗯接下来要学龙语者的四转技能了大家快退后不要再近战了地狱火嘿嘿一笑很期待而我则继续无视身在烈焰战马上光凭神龙斩的吸血就足够能够补充生命值了大祭司罗宁微微一惊

3年前中央的重大动作 今年有了新变化

大风骤起站在最前面的我冷笑着看着敌人的冲阵剑锋向前一指喝道给我杀地面开始震颤起来许多小小的碎石仿佛不受到重力控制一样的飞了起来甚至我也感觉到身体很轻仿佛就要被吸飞起来而那条灰色的巨龙则已经横行于高空之中猛然肆虐而来 但是凌雪可不能就这样白白挂掉而且我也宁愿用自己的一次挂掉来印证一下这是否真的就无法以操作来虐掉而且这里也只有我才有机会弄死这个了秦韵虽然身在上面但是她一个小牧师没有什么攻击力要杀的话难道用惩戒那估计得打到驴年马月去了对方的玩家所剩无几也就那几个高手了小蝴蝶这个星月祭祀已经被淡淡稻花香

iOS 11 : CORE ML—浅析

苹果在 iOS 5 里引入了 NSLinguisticTagger 来分析自然语言.iOS 8 出了 Metal,提供了对设备 GPU 的底层访问.去年,苹果在 Accelerate 框架添加了 Basic Neural Network Subroutines (BNNS),使开发者可以构建用于推理(不是训练)的神经网络. 今年,苹果给了我们 Core ML 和 Vision,让iOS开发者在人工智能上面更上一步台阶. Core ML 让我们更容易在 App 中使用训练过的模型. Vision

AI,DM,ML,PR的区别与联系

数据挖掘和机器学习的区别和联系,周志华有一篇很好的论述<机器学习与数据挖掘>可以帮助大家理解.数据挖掘受到很多学科领域的影响,其中数据库.机器学习.统计学无疑影响最大.简言之,对数据挖掘而言,数据库提供数据管理技术,机器学习和统计学提供数据分析技术.由于统计学往往醉心于理论的优美而忽视实际的效用,因此,统计学界提供的很多技术通常都要在机器学习界进一步研究,变成有效的机器学习算法之后才能再进入数据挖掘领域.从这个意义上说,统计学主要是通过机器学习来对数据挖掘发挥影响,而机器学习和数据库则是数据挖

门业阅闷猜勇纬的俺箍撩犊yuvw

IEEE Spectrum 杂志发布了一年一度的编程语言排行榜,这也是他们发布的第四届编程语言 Top 榜. 据介绍,IEEE Spectrum 的排序是来自 10 个重要线上数据源的综合,例如 Stack Overflow.Twitter.Reddit.IEEE Xplore.GitHub.CareerBuilder 等,对 48 种语言进行排行. 与其他排行榜不同的是,IEEE Spectrum 可以让读者自己选择参数组合时的权重,得到不同的排序结果.考虑到典型的 Spectrum 读者需求

20170913自制猜数字游戏

/* 猜数字:系统随机生成一个四位数,请根据下列判断猜出来 A:数值正确,位置正确 B:数值正确,位置不正确 C:数值不正确 */ #include<stdio.h> #include<time.h> #include<stdlib.h> #pragma warning (disable:4996) #define pUCharHead unsigned char * //以数组形式返回n个无重复的随机数,范围可指定[min,max] pUCharHead GenNoR

Mercedes-Benz NEC BGA 315MHZ 433MHZ 434MHZ GLK GLA GLC ML W204 W207 W212 W221 W222 S300 S350 S400 S500 S550 S600 C180 C200 C260 C300 ES350 GLK300 GLA200 E260L C200 B200 S320L Mercedes-Benz KEY PC

AUTO ECU CHIPS  STOCK ESL Motor  ELV Motor  Steering Lock Wheel Motor for Mercedes-Benz ESL/ELV Motor Steering Lock Wheel Motor for Mercedes-Benz W204 W207 W212 esl motor elv motor Mercedes-Benz NEC   BGA 315MHZ 433MHZ  434MHZ GLK GLA GLC ML W204 W20

Spark ML下实现的多分类adaboost+naivebayes算法在文本分类上的应用

1. Naive Bayes算法 朴素贝叶斯算法算是生成模型中一个最经典的分类算法之一了,常用的有Bernoulli和Multinomial两种.在文本分类上经常会用到这两种方法.在词袋模型中,对于一篇文档$d$中出现的词$w_0,w_1,...,w_n$, 这篇文章被分类为$c$的概率为$$p(c|w_0,w_1,...,w_n) = \frac{p(c,w_0,w_1,...,w_n)}{p(w_0,w_1,...,w_n)} = \frac{p(w_0,w_1,...,w_n|c)*p(c

Notes : &lt;Hands-on ML with Sklearn &amp; TF&gt; Chapter 7

.caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px solid #000; } .table { border-collapse: collapse !important; } .table td, .table th { background-color: #fff !important; } .table-bordered th, .table-bordere