NLP From Scratch: 使用char-RNN对姓氏进行分类

news2024/12/23 13:15:33

NLP From Scratch: 使用char-RNN对姓氏进行分类

本篇我们将构建并训练基本的字符级 RNN 来对单词进行分类。 本教程,以及后续两个教程,展示了如何“从头开始”针对 NLP 建模过程中所需的数据进行预处理,抛开torchtext的许多便利功能进行编码,能够让您了解在底层针对 NLP 建模所需的数据是如何预进行处理的。

字符级 RNN 将单词看做字符序列进行读取并在每个步骤输出预测结果和“隐藏状态”,然后将其先前的隐藏状态输入到下一步。 我们将最终的预测结果作为输出,即该单词属于哪个类别。

具体来说,我们将训练来自 18 种语言的数千种姓氏,并根据拼写方式预测该名称属于哪种语言,如下示例:

$ python predict.py Hinton
(-0.47) Scottish
(-1.52) English
(-3.57) Irish

$ python predict.py Schmidhuber
(-0.19) German
(-2.48) Czech
(-2.68) Dutch

推荐读物:

本篇教程假设您至少已经安装了 PyTorch,了解 Python 和 Tensors:

  • https://pytorch.org/ 有关安装说明
  • 使用 PyTorch 进行深度学习:60 分钟的闪电战如何快速开始使用 PyTorch
  • 根据示例学习Pytorch对 Pytorch 进行更广泛深入的了解
  • PyTorch(以前的 Torch 用户)(如果您以前是 Lua Torch 用户)

了解 RNN 及其工作方式也很重要:

  • 循环神经网络的超常效果显示了许多现实生活中的例子
  • 了解 LSTM 网络主要是关于 LSTM 的,但总体上也是有关 RNN 的

准备数据

Note

  • 从这里下载数据,并将其提取到当前目录。

data/names目录中包含 18 个文本文件,名为“ [Language] .txt”。 每个文件包含多行,每行一个姓氏,大多数都是罗马字符(但谨慎起见我们仍然需要从 Unicode 编码转换为 ASCII 编码)。

处理之后我们得到一个字典,字典包含每种语言的姓氏列表{language: [names ...]}。 通用变量categoryline(在本例中分别为语言和姓氏)在后续还会使用。

from __future__ import unicode_literals, print_function, division
from io import open
import glob
import os

def findFiles(path): return glob.glob(path)

print(findFiles('data/names/*.txt'))

import unicodedata
import string

all_letters = string.ascii_letters + " .,;'"
n_letters = len(all_letters)

# Turn a Unicode string to plain ASCII, thanks to https://stackoverflow.com/a/518232/2809427
def unicodeToAscii(s):
    return ''.join(
        c for c in unicodedata.normalize('NFD', s)
        if unicodedata.category(c) != 'Mn'
        and c in all_letters
    )

print(unicodeToAscii('Ślusàrski'))

# Build the category_lines dictionary, a list of names per language
category_lines = {}
all_categories = []

# Read a file and split into lines
def readLines(filename):
    lines = open(filename, encoding='utf-8').read().strip().split('\n')
    return [unicodeToAscii(line) for line in lines]

for filename in findFiles('data/names/*.txt'):
    category = os.path.splitext(os.path.basename(filename))[0]
    all_categories.append(category)
    lines = readLines(filename)
    category_lines[category] = lines

n_categories = len(all_categories)

Out:

['data/names/French.txt', 'data/names/Czech.txt', 'data/names/Dutch.txt', 'data/names/Polish.txt', 'data/names/Scottish.txt', 'data/names/Chinese.txt', 'data/names/English.txt', 'data/names/Italian.txt', 'data/names/Portuguese.txt', 'data/names/Japanese.txt', 'data/names/German.txt', 'data/names/Russian.txt', 'data/names/Korean.txt', 'data/names/Arabic.txt', 'data/names/Greek.txt', 'data/names/Vietnamese.txt', 'data/names/Spanish.txt', 'data/names/Irish.txt']
Slusarski

经过上述处理,我们获得了变量category_lines,这是一个字典,字典索引为每个类别(语言)值为一个列表,列表包含多个行(姓氏)。 我们还保存了all_categories(类别(语言)列表)和n_categories(语言类别数量),以供后续使用。

print(category_lines['Italian'][:5])

Out:

['Abandonato', 'Abatangelo', 'Abatantuono', 'Abate', 'Abategiovanni']

将名称转换为张量

获取所有姓氏之后,我们需要将它们转换为张量。

为了表示单个字母,我们使用大小为<1 x n_letters>的“ one-hot vector”。 一个“one hot”向量是当前字母的索引处为 1,其余部分为 0 的向量,例如 "b" = <0 1 0 0 0 ...>

我们将每行的所有字母的“one hot”向量连接成 2D 矩阵<line_length x 1 x n_letters>来表示一个单词(姓氏)。

额外的 1 维是因为 PyTorch 假设所有内容都是批量的-我们这里批量大小为 1 。

import torch

# Find letter index from all_letters, e.g. "a" = 0
def letterToIndex(letter):
    return all_letters.find(letter)

# Just for demonstration, turn a letter into a <1 x n_letters> Tensor
def letterToTensor(letter):
    tensor = torch.zeros(1, n_letters)
    tensor[0][letterToIndex(letter)] = 1
    return tensor

# Turn a line into a <line_length x 1 x n_letters>,
# or an array of one-hot letter vectors
def lineToTensor(line):
    tensor = torch.zeros(len(line), 1, n_letters)
    for li, letter in enumerate(line):
        tensor[li][0][letterToIndex(letter)] = 1
    return tensor

print(letterToTensor('J'))

print(lineToTensor('Jones').size())

Out:

tensor([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
         0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.,
         0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
         0., 0., 0.]])
torch.Size([5, 1, 57])

建立网络

在 Torch 中创建一个循环神经网络需要在多个时间步上克隆神经层的参数。 现在不同的时间步骤下网络层所保存的隐藏状态和梯度均由计算图自身处理,编程者无需关心,因此您可以向构建常见的前馈网络一样在Torch中简便的构建循环神经网络。

下图的 RNN 模块(主要从 the PyTorch for Torch users tutorial 复制)仅是 2 个线性层,它们读取输入和隐藏状态,并将其进行线性映射后,在讲输出结果通过 LogSoftmax 层作为本层输出。

import torch.nn as nn

class RNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(RNN, self).__init__()

        self.hidden_size = hidden_size

        self.i2h = nn.Linear(input_size + hidden_size, hidden_size)
        self.i2o = nn.Linear(input_size + hidden_size, output_size)
        self.softmax = nn.LogSoftmax(dim=1)

    def forward(self, input, hidden):
        combined = torch.cat((input, hidden), 1)
        hidden = self.i2h(combined)
        output = self.i2o(combined)
        output = self.softmax(output)
        return output, hidden

    def initHidden(self):
        return torch.zeros(1, self.hidden_size)

n_hidden = 128
rnn = RNN(n_letters, n_hidden, n_categories)

要对该网络进行单步运行,我们需要传递输入(在本例中为当前字母的张量)和上一步的隐藏状态(首先将其初始化为零)。 该网络将返回输出(每种语言的概率)和下一个隐藏状态(我们将其保留用于下一步)。

input = letterToTensor('A')
hidden =torch.zeros(1, n_hidden)

output, next_hidden = rnn(input, hidden)

为了提高效率,我们不想为每个步骤创建一个新的 Tensor,因此我们将使用lineToTensor生成向量再进行切片,而不是多次使用letterToTensor。 这可以通过预先计算一批张量来进一步优化。

input = lineToTensor('Albert')
hidden = torch.zeros(1, n_hidden)

output, next_hidden = rnn(input[0], hidden)
print(output)

Out:

tensor([[-2.9504, -2.8402, -2.9195, -2.9136, -2.9799, -2.8207, -2.8258, -2.8399,
         -2.9098, -2.8815, -2.8313, -2.8628, -3.0440, -2.8689, -2.9391, -2.8381,
         -2.9202, -2.8717]], grad_fn=<LogSoftmaxBackward>)

如上,输出为<1 x n_categories>张量,其中每项对应于该类别的可能性(数值更高的可能性更大)。

训练

准备训练

在训练之前,我们需要设置一些辅助函数。 首先我们需要针对网络的输出(每个类别的可能性)进行处理,以输出其最可能的类别。 我们可以使用Tensor.topk来获得最大值的索引:

def categoryFromOutput(output):
    top_n, top_i = output.topk(1)
    category_i = top_i[0].item()
    return all_categories[category_i], category_i

print(categoryFromOutput(output))

Out:

('Chinese', 5)

我们还将需要一个快速获取训练示例的函数(姓氏及其语言):

import random

def randomChoice(l):
    return l[random.randint(0, len(l) - 1)]

def randomTrainingExample():
    category = randomChoice(all_categories)
    line = randomChoice(category_lines[category])
    category_tensor = torch.tensor([all_categories.index(category)], dtype=torch.long)
    line_tensor = lineToTensor(line)
    return category, line, category_tensor, line_tensor

for i in range(10):
    category, line, category_tensor, line_tensor = randomTrainingExample()
    print('category =', category, '/ line =', line)

Out:

category = Italian / line = Pastore
category = Arabic / line = Toma
category = Irish / line = Tracey
category = Portuguese / line = Lobo
category = Arabic / line = Sleiman
category = Polish / line = Sokolsky
category = English / line = Farr
category = Polish / line = Winogrodzki
category = Russian / line = Adoratsky
category = Dutch / line = Robert

训练网络

现在,训练该网络所需要做的就是向它输入大量示例,让网络进行猜测,并告诉它该猜测是否错误。

nn.NLLLoss是比较合适的损失函数,因为 RNN 的最后一层是nn.LogSoftmax

criterion = nn.NLLLoss()

每个训练循环将:

  • 创建输入和目标张量
  • 创建归零的初始隐藏状态
  • 读入每个字母
    • 保存隐藏状态用于下个字母
  • 比较最终输出与目标张量的差距
  • 反向传播
  • 返回输出和损失
learning_rate = 0.005 # If you set this too high, it might explode. If too low, it might not learn

def train(category_tensor, line_tensor):
    hidden = rnn.initHidden()

    rnn.zero_grad()

    for i in range(line_tensor.size()[0]):
        output, hidden = rnn(line_tensor[i], hidden)

    loss = criterion(output, category_tensor)
    loss.backward()

    # Add parameters' gradients to their values, multiplied by learning rate
    for p in rnn.parameters():
        p.data.add_(-learning_rate, p.grad.data)

    return output, loss.item()

现在,我们只需要使用大量示例来运行该网络即可。 由于train函数同时返回输出和损失,因此我们可以打印其猜测结果并跟踪绘制损失变化。 因为有 1000 个示例,所以我们每隔print_every个示例打印一次,并平均这段时间内的损失然后保存下来。

import time
import math

n_iters = 100000
print_every = 5000
plot_every = 1000

# Keep track of losses for plotting
current_loss = 0
all_losses = []

def timeSince(since):
    now = time.time()
    s = now - since
    m = math.floor(s / 60)
    s -= m * 60
    return '%dm %ds' % (m, s)

start = time.time()

for iter in range(1, n_iters + 1):
    category, line, category_tensor, line_tensor = randomTrainingExample()
    output, loss = train(category_tensor, line_tensor)
    current_loss += loss

    # Print iter number, loss, name and guess
    if iter % print_every == 0:
        guess, guess_i = categoryFromOutput(output)
        correct = '✓' if guess == category else '✗ (%s)' % category
        print('%d %d%% (%s) %.4f %s / %s %s' % (iter, iter / n_iters * 100, timeSince(start), loss, line, guess, correct))

    # Add current loss avg to list of losses
    if iter % plot_every == 0:
        all_losses.append(current_loss / plot_every)
        current_loss = 0

Out:

5000 5% (0m 12s) 3.1806 Olguin / Irish ✗ (Spanish)
10000 10% (0m 21s) 2.1254 Dubnov / Russian ✓
15000 15% (0m 29s) 3.1001 Quirke / Polish ✗ (Irish)
20000 20% (0m 38s) 0.9191 Jiang / Chinese ✓
25000 25% (0m 46s) 2.3233 Marti / Italian ✗ (Spanish)
30000 30% (0m 54s) nan Amari / Russian ✗ (Arabic)
35000 35% (1m 3s) nan Gudojnik / Russian ✓
40000 40% (1m 11s) nan Finn / Russian ✗ (Irish)
45000 45% (1m 20s) nan Napoliello / Russian ✗ (Italian)
50000 50% (1m 28s) nan Clark / Russian ✗ (Irish)
55000 55% (1m 37s) nan Roijakker / Russian ✗ (Dutch)
60000 60% (1m 46s) nan Kalb / Russian ✗ (Arabic)
65000 65% (1m 54s) nan Hanania / Russian ✗ (Arabic)
70000 70% (2m 3s) nan Theofilopoulos / Russian ✗ (Greek)
75000 75% (2m 11s) nan Pakulski / Russian ✗ (Polish)
80000 80% (2m 20s) nan Thistlethwaite / Russian ✗ (English)
85000 85% (2m 29s) nan Shadid / Russian ✗ (Arabic)
90000 90% (2m 37s) nan Finnegan / Russian ✗ (Irish)
95000 95% (2m 46s) nan Brannon / Russian ✗ (Irish)
100000 100% (2m 54s) nan Gomulka / Russian ✗ (Polish)

绘制结果

all_losses绘制损失的变化情况可以显示网络学习情况:

import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

plt.figure()
plt.plot(all_losses)

评估结果

为了查看网络在不同类别上的表现如何,我们将创建一个混淆矩阵,行对应于每种语言,列对应于网络猜测的语言。为了计算混淆矩阵,使用evaluate()函数通过训练好的网络运行一批样本,这一步类似于训练函数train,但是没有反向传播过程。

# Keep track of correct guesses in a confusion matrix
confusion = torch.zeros(n_categories, n_categories)
n_confusion = 10000

# Just return an output given a line
def evaluate(line_tensor):
    hidden = rnn.initHidden()

    for i in range(line_tensor.size()[0]):
        output, hidden = rnn(line_tensor[i], hidden)

    return output

# Go through a bunch of examples and record which are correctly guessed
for i in range(n_confusion):
    category, line, category_tensor, line_tensor = randomTrainingExample()
    output = evaluate(line_tensor)
    guess, guess_i = categoryFromOutput(output)
    category_i = all_categories.index(category)
    confusion[category_i][guess_i] += 1

# Normalize by dividing every row by its sum
for i in range(n_categories):
    confusion[i] = confusion[i] / confusion[i].sum()

# Set up plot
fig = plt.figure()
ax = fig.add_subplot(111)
cax = ax.matshow(confusion.numpy())
fig.colorbar(cax)

# Set up axes
ax.set_xticklabels([''] + all_categories, rotation=90)
ax.set_yticklabels([''] + all_categories)

# Force label at every tick
ax.xaxis.set_major_locator(ticker.MultipleLocator(1))
ax.yaxis.set_major_locator(ticker.MultipleLocator(1))

# sphinx_gallery_thumbnail_number = 2
plt.show()

主轴上的一些亮点代表神经网络容易猜错哪些语言,例如 中文和朝鲜语,西班牙语和意大利语。 神经网络在希腊语上表现很好,在英语上表现得很差(可能是因为与其他语言重叠较多)。

在用户输入上运行

def predict(input_line, n_predictions=3):
    print('\n> %s' % input_line)
    with torch.no_grad():
        output = evaluate(lineToTensor(input_line))

        # Get top N categories
        topv, topi = output.topk(n_predictions, 1, True)
        predictions = []

        for i in range(n_predictions):
            value = topv[0][i].item()
            category_index = topi[0][i].item()
            print('(%.2f) %s' % (value, all_categories[category_index]))
            predictions.append([value, all_categories[category_index]])

predict('Dovesky')
predict('Jackson')
predict('Satoshi')

Out:

> Dovesky
(nan) Russian
(nan) Arabic
(nan) Korean

> Jackson
(nan) Russian
(nan) Arabic
(nan) Korean

> Satoshi
(nan) Russian
(nan) Arabic
(nan) Korean

实际 PyTorch 存储库中的脚本将上述代码分成几个文件:

  • data.py(加载文件)
  • model.py(定义 RNN)
  • train.py(进行训练)
  • predict.py(使用命令行参数运行predict()
  • server.py (通过bottle.py将预测用作 JSON API)

运行train.py训练并保存网络。

将姓氏作为输入运行predict.py来查看预测结果:

$ python predict.py Hazaki
(-0.42) Japanese
(-1.39) Polish
(-3.51) Czech

运行server.py并访问http://localhost:5533/您的名字以获取预测的 JSON 格式输出。

练习题

  • 尝试使用其他行->类别的数据集,例如:
    • 任何字词->语言
    • 名->性别
    • 角色名称->作家
    • 页面标题->博客或 subreddit
  • 通过更大和/或形状更好的网络获得更好的结果
    • 添加更多线性层
    • 尝试nn.LSTMnn.GRU
    • 将多个这些 RNN 合并为更高级别的网络

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/801020.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言基础教程(fgets和fputs)

文章目录 前言一、fputs函数二、fgets函数三、fputc和fgetc函数总结 前言 本篇文章我们来讲解一下fgets和fputs函数&#xff0c;这两个函数通常用来作为输入和输出功能使用。 一、fputs函数 fputs函数是C语言标准库中的一个输出函数&#xff0c;用于将字符串写入到指定的文件…

mysql主从同步怎么跳过错误

今天介绍两种mysql主从同步跳过错误的方法&#xff1a; 一、两种方法介绍 1、跳过指定数量的事务&#xff1a; mysql>slave stop; mysql>SET GLOBAL SQL_SLAVE_SKIP_COUNTER 1 #跳过一个事务 mysql>slave start2、修改mysql的配置文件&#xff0c;通过slav…

The Sandbox 重新上线,带来全新体验!

在经历了一个充满史诗般新回忆的全力开局后&#xff0c;我们短暂休息了片刻&#xff0c;为玩家准备了全新的、惊心动魄的游戏活动。 我们已经完成了功能的微调&#xff0c;准备将您的游戏体验提升到一个全新高度&#xff01; 想知道我们正在做什么吗&#xff1f;现在还无法公开…

iTOP-STM32MP157开发板Linux Misc驱动-编译驱动程序

这里我们以 stm32mp157 开发板为例&#xff0c;将杂项设备驱动编译成模块&#xff0c;请参考本手册第三十七章 Linux 内核模块。我们将 misc.c 文件拷贝到 Ubuntu 的/home/nfs/03 目录下。将上次编译 helloworld 的 Makefile 文 件拷贝到 misc.c 同级目录下&#xff0c;修改 …

指针学习(特殊指针)

1.char型指针 char型指针实质上跟别的类型的指针并无本质区别&#xff0c;但是C语言中的字符串以字符数组的方式存储&#xff0c;而数组在大多数场合又会表现为指针&#xff0c;因此字符串在绝大多数场合就表现为char型指针。 例如&#xff1a; char *p "abcd"; …

axios的如何使用

1、axios的使用第一步先装包 npm i axios-S 2、axios的使用方法&#xff0c;先导入包&#xff0c;再绑定事件&#xff0c;再注册事件 3、axios如何实现post请求 4、Vue挂载axios,简便输入地址&#xff1a; 5、通过this实例&#xff0c;可以访问到axios的链接 6、给他改成$http…

【李宏毅 DLHLP 深度学习人类语言处理 HW1】

李宏毅 DLHLP 深度学习人类语言处理 HW1 相关资料HW1 语音小白在网上没有找到这门课的作业分享&#xff0c;那就记录一下自己的作业吧。 相关资料 课程官网&#xff1a;https://speech.ee.ntu.edu.tw/~hylee/dlhlp/2020-spring.php 作业github代码1&#xff1a;https://githu…

用抓包工具结合局域网代理技术爬取meituan某些商家的数据

众所周知&#xff0c;爬虫玩的好&#xff0c;牢饭吃的早&#xff08;如有侵犯利益&#xff0c;请您告知&#xff0c;我将立删&#xff01;&#xff09;。 其实抓包嘛&#xff0c;简单的H5网页直接就能用浏览器的开发者工具进行抓包&#xff0c;但是很多平台剔除了网页版&#…

《面试1v1》Kafka与传统消息系统区别

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…

C语言:动态版本通讯录(静态版本的改进)

文章目录 一、改进方向1.结构2.初始化3.增加联系人and检查容量4.退出 二、代码实现总结 通讯录静态版本的实现思路与完整代码 一、改进方向 对于管理数据&#xff0c;我们主要进行增删查改操作&#xff0c;我们要改进静态版本的通讯录&#xff0c;主要在于增加数据方向。而删除…

C++数组、向量和列表的练习

运行代码&#xff1a; //C数组、向量和列表的练习 #include"std_lib_facilities.h"int main() try {int ii[10] { 0,1,2,3,4,5,6,7,8,9 };for (int i 0; i < 10; i)//把数组中的每个元素值加2ii[i] 2;vector<int>vv(10);for (int i 0; i < 10; i)vv…

Transformer模型简单介绍

Transformer是一个深度学习模型。主要功能通俗的来说就是翻译。输入&#xff0c;处理&#xff0c;输出。 https://zhuanlan.zhihu.com/p/338817680 大牛写的很完整 目录 总框架Encoder输入部分注意力机制前馈神经网络 Decoder 总框架 Encoders: 编码器Decoders: 解码器 Encoder…

AT指令介绍

一、基础知识 1、用途&#xff1a;用来控制TE&#xff08;TerminalEquipment&#xff09;和MT(Mobile Terminal)之间交互的规则&#xff0c;如下图所示。在GSM网络中&#xff0c;用户可以通过AT命令进行呼叫、短信、电话本、数据业务、传真等方面的控制。&#xff08;AT指令只…

BUG:pm2启动verdaccio报错:Invalid or unexpected toke

输入命令&#xff1a; pm2 state verdaccio 问题描述&#xff1a; pm2 logs verdaccio报错翻译&#xff1a;数据格式错误 导致我呢提原因&#xff0c;没有找到运行文件&#xff0c; 发现问题&#xff1a;因为命令默认查找verdaccio是去系统盘查找。 解决方式 1&#xff1a;…

探索单例模式:设计模式中的瑰宝

文章目录 常用的设计模式有以下几种&#xff1a;一.创建型模式&#xff08;Creational Patterns&#xff09;&#xff1a;二.结构型模式&#xff08;Structural Patterns&#xff09;&#xff1a;三.行为型模式&#xff08;Behavioral Patterns&#xff09;&#xff1a;四.并发…

js逆向中高级案例-文章标题汇总

一、详细文章 点击链接查看如图案例标题

Tensorflow benchmark 实操指南

环境搭建篇见环境搭建-CentOS7下Nvidia Docker容器基于TensorFlow1.15测试GPU_东方狱兔的博客-CSDN博客 1. 下载Benchmarks源码 从 TensorFlow 的 Github 仓库上下载 TensorFlow Benchmarks&#xff0c;可以通过以下命令来下载 https://github.com/tensorflow/benchmarks 我…

LeetCode每日一题-接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表…

宋版“三国演义”(北宋、辽、西夏和南宋、金、蒙古)

1 北宋、辽、西夏三国演义 宋、辽、西 夏鼎立形势图 公元960年&#xff08;后周显德七年&#xff09;&#xff0c;后周大将赵匡胤陈桥兵变黄袍加身&#xff0c;建立了宋朝。 然而&#xff0c;北方有一个资格比它老的国家&#xff0c;是为契丹人建立的辽国。 辽创立于五代初。…

《MySQL》第十一篇 SQL_MODEL模式简述

目录 一. 介绍与使用二. 模式类型三. 常用模式演示ANSI 模式TRADITIONAL 模式STRICT_TRANS_TABLES 模式 一. 介绍与使用 SQL Mode定义了MySQL应支持的SQL语法、数据校验等&#xff0c;这样可以更容易地在不同的环境中使用MySQL 常用来解决下面几类问题&#xff1a; 通过设置S…