机器翻译

Posted Debroon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了机器翻译相关的知识,希望对你有一定的参考价值。

 


现成工具:沙拉查词

网页:https://saladict.crimx.com/

大赞,Google 浏览器最好用的扩展之一!
 


机器翻译原理

如果一个事件的概率会因为某个条件而产生变化,那在这个条件发生的情况下,这个事件发生的概率就是条件概率。

比如,因为昨天晚睡了,所以今天大概率不会早起。

  • P (   早 起   ∣   晚 睡   ) P(~早起~|~晚睡~) P(    )
  • P (   事 件   ∣   条 件   ) P(~事件~|~条件~) P(    )

条件概率公式: P ( Y ∣ X ) = P ( X Y ) P ( X ) P( Y| X)=\\frac{P(XY)}{P(X)} P(YX)=P(X)P(XY)

  • P ( Y ∣ X ) P(Y|X) P(YX):条件概率,表示在 X 条件下 Y 发生的概率
  • P ( X Y ) P(XY) P(XY):条件 X、事件 Y 同时发生的概率
  • P ( X ) P(X) P(X):条件 X 发生的概率

在文本中的两个词 X 和 Y,前面的词就是后面的词的条件,比如 X 是中药,Y 是人参,反过来也成立,X 是人参,Y 是中药。

于是,就有一个想法:

  • P ( Y ∣ X ) = P ( X Y ) P ( X ) P( Y| X)=\\frac{P(XY)}{P(X)} P(YX)=P(X)P(XY)
  • P ( X ∣ Y ) = P ( X Y ) P ( Y ) P( X| Y)=\\frac{P(XY)}{P(Y)} P(XY)=P(Y)P(XY)

我们把俩个式子都变形:

  • P ( X Y ) = P ( Y ∣ X ) ∗ P ( X ) P(XY) = P(Y|X)*P(X) P(XY)=P(YX)P(X)
  • P ( X Y ) = P ( X ∣ Y ) ∗ P ( Y ) P(XY) = P(X|Y)*P(Y) P(XY)=P(XY)P(Y)

对比这个式子和前面的式子,我们发现它们都等于 P ( X , Y ) P(X,Y) P(X,Y),因此两个等式的左边也必然相等。

于是,我们就可以得到一个重要的公式:

  • P ( Y ∣ X ) ∗ P ( X ) = P ( X ∣ Y ) ∗ P ( Y ) P(Y|X)*P(X)=P(X|Y)*P(Y) P(YX)P(X)=P(XY)P(Y)

在这个公式中,如果我们知道了其中三个因子,就能求出第四个。

通常来讲,两个条件概率 P ( X ) P(X) P(X) P ( Y ) P(Y) P(Y) 是容易求的。

另外两个条件概率,一个是 X 条件下 Y 的概率,一个是 Y 条件下 X 的概率,常常一个比较容易得到,另一个比较难得到。

另外两个条件概率,一个是 X 条件下 Y 的概率,一个是 Y 条件下 X 的概率,常常一个比较容易得到,另一个比较难得到。

所以,我们常常从容易得到的条件概率,推导出难得到的概率,这就是著名的贝叶斯公式:

  • P ( X ∣ Y ) = P ( Y ∣ X ) ∗ P ( X ) P ( Y ) P(X|Y)=P(Y|X)*\\frac{P(X)}{P(Y)} P(XY)=P(YX)P(Y)P(X)

在这个公式中,我们假定 Y 条件下 X 的条件概率比较难得到,我们放在了等式的左边,而 X 条件下 Y 的条件概率容易得到,我们放在了等式的右边。

通过这种互换,可以把一个复杂的问题变成三个简单的问题。

这就是贝叶斯公式的本质。利用它,就解决了机器翻译的难题。

假定有一个英语句子 Y,想要翻译成中文句子 X,那怎么翻译呢?

很多人将它想象成语言学问题,其实这是一个数学问题,或者更准确地说,是一个概率的问题。

假定英语句子 Y 有很多种翻译方法 X1,X2,X3……XN,我们只要挑一种翻译 X,使得在已知英语句子 Y 的条件下,X 的概率 P ( X ∣ Y ) P(X|Y) P(XY) 超过其它所有可能的句子的条件概率即可。

比如说,这句话有 10 种翻译方法,它们的条件概率分别是 0.1,0.5,0.01,0.02……你会发现第二种翻译方法 X2 的条件概率是 0.5,是最大的,因此就认为 Y 应该被翻译成X2,或者说 X = X2。

P ( X ∣ Y ) P(X|Y) P(XY) 这个概率该怎么计算呢?

这个条件概率的计算,就要用到贝叶斯公式了。我们将它展开成:

  • P ( X ∣ Y ) = P ( Y ∣ X ) ∗ P ( X ) P ( Y ) P(X|Y)=P(Y|X)*\\frac{P(X)}{P(Y)} P(XY)=P(YX)P(Y)P(X)

P ( Y ∣ X ) P(Y|X) P(YX) 是给定中文的句子,对应的英文句子的概率,它可以通过一个马尔可夫模型计算出来。

P ( X ) P(X) P(X) 是所谓的语言模型,它计算的是哪个句子在语法上更合理,这个也可以通过一个马尔可夫模型计算。

P ( Y ) P(Y) P(Y) 是一个常数,因为要翻译句子 Y,它是个确定的事情,我们把它的概率想象成 1 就可以了(其实不是1)。

于是原来的一个无法直接计算的条件概率,经过贝叶斯公式,变成了三个可以计算的概率。

这样,就能够判断给定一个句子,任何翻译出来的中文句子的可能性,而后我们找出最大的那个即可。

因为条件概率在数学上条件和结果可以互换,通过这种互换,把一个复杂的问题变成三个简单的问题,这就是贝叶斯公式的本质,利用它,就解决了机器翻译的难题。

具体来说,除了贝叶斯,机器翻译的方法还有许多,比如 集束搜索、维特比算法等,记录在《语音识别食用指南》。
 


最佳翻译

以下是 RNN结合集束搜索 实现的语言翻译,但 RNN 需要非常非常大的训练数据集和非常非常长的训练时间。

  • 数据集:

本次我们只用它来实现日期格式的翻译。

  • 1 March 2001
  • 2001-03-01

自定义工具模块:

# nmt_utils.py
import numpy as np
from faker import Faker
import random
from tqdm import tqdm
from babel.dates import format_date
from tensorflow.keras.utils import to_categorical
import tensorflow.keras.backend as K
import matplotlib.pyplot as plt

fake = Faker()
Faker.seed(12345)
random.seed(12345)

FORMATS = ['short',
           'medium',
           'long',
           'full',
           'full',
           'full',
           'full',
           'full',
           'full',
           'full',
           'full',
           'full',
           'full',
           'd MMM YYY', 
           'd MMMM YYY',
           'dd MMM YYY',
           'd MMM, YYY',
           'd MMMM, YYY',
           'dd, MMM YYY',
           'd MM YY',
           'd MMMM YYY',
           'MMMM d YYY',
           'MMMM d, YYY',
           'dd.MM.YY']

LOCALES = ['en_US']

def load_date():
    dt = fake.date_object()

    try:
        human_readable = format_date(dt, format=random.choice(FORMATS),  locale='en_US') 
        human_readable = human_readable.lower()
        human_readable = human_readable.replace(',','')
        machine_readable = dt.isoformat()
        
    except AttributeError as e:
        return None, None, None

    return human_readable, machine_readable, dt

def load_dataset(m):
    human_vocab = set()
    machine_vocab = set()
    dataset = []
    Tx = 30
    
    for i in tqdm(range(m)):
        h, m, _ = load_date()
        if h is not None:
            dataset.append((h, m))
            human_vocab.update(tuple(h))
            machine_vocab.update(tuple(m))
    
    human = dict(zip(sorted(human_vocab) + ['<unk>', '<pad>'], 
                     list(range(len(human_vocab) + 2))))
    inv_machine = dict(enumerate(sorted(machine_vocab)))
    machine = {v:k for k,v in inv_machine.items()}
 
    return dataset, human, machine, inv_machine

def preprocess_data(dataset, human_vocab, machine_vocab, Tx, Ty):
    
    X, Y = zip(*dataset)
    
    X = np.array([string_to_int(i, Tx, human_vocab) for i in X])
    Y = [string_to_int(t, Ty, machine_vocab) for t in Y]
    
    Xoh = np.array(list(map(lambda x: to_categorical(x, num_classes=len(human_vocab)), X)))
    Yoh = np.array(list(map(lambda x: to_categorical(x, num_classes=len(machine_vocab)), Y)))

    return X, np.array(Y), Xoh, Yoh

def string_to_int(string, length, vocab):
    string = string.lower()
    string = string.replace(',','')
    
    if len(string) > length:
        string = string[:length]
        
    rep = list(map(lambda x: vocab.get(x, '<unk>'), string))
    
    if len(string) < length:
        rep += [vocab['<pad>']] * (length - len(string))
    
    return rep


def int_to_string(ints, inv_vocab): 
    l = [inv_vocab[i] for i in ints]
    return l


EXAMPLES = ['3 May 1979', '5 Apr 09', '20th February 2016', 'Wed 10 Jul 2007']

def run_example(model, input_vocabulary, inv_output_vocabulary, text):
    encoded = string_to_int(text, TIME_STEPS, input_vocabulary)
    prediction = model.predict(np.array([encoded]))
    prediction = np.argmax(prediction[0], axis=-1)
    return int_to_string(prediction, inv_output_vocabulary)

def run_examples(model, input_vocabulary, inv_output_vocabulary, examples=EXAMPLES):
    predicted = []
    for example in examples:
        predicted.append(''.join(run_example(model, input_vocabulary, inv_output_vocabulary, example)))
        print('input:', example)
        print('output:', predicted[-1])
    return predicted


def softmax(x, axis=1):
    ndim = K.ndim(x)
    if ndim == 2:
        return K.softmax(x)
    elif ndim > 2:
        e = K.exp(x - K.max(x, axis=axis, keepdims=True))
        s = K.sum(e, axis=axis, keepdims=True)
        return e / s
    else:
        raise ValueError('Cannot apply softmax to a tensor that is 1D')
        

def plot_attention_map(model, input_vocabulary, inv_output_vocabulary, text, n_s = 128, num = 6, Tx = 30, Ty = 10):
    attention_map = np.zeros((10, 30))
    Ty, Tx = attention_map.shape
    
    s0 = np.zeros((1, n_s))
    c0 = np.zeros((1, n_s))
    layer Azure 机器人微软Azure Bot 编辑器系列 : 机器人/用户提问回答模式,机器人从API获取响应并组织答案 (The Bot Framework Composer tutorial(代码片段

Android 逆向使用 Python 解析 ELF 文件 ( Capstone 反汇编 ELF 文件中的机器码数据 | 创建反汇编解析器实例对象 | 设置汇编解析器显示细节 )(代码片段

GLSL:使用片段着色器进行对象翻译

python ipython:机器学习片段

你可能不知道的JavaScript代码片段和技巧(下)

你可能不知道的JavaScript代码片段和技巧(上)