轻松搞懂Word2vec / FastText+BiLSTM、TextCNN、CNN+BiLSTM、BiLSTM+Attention实现中英文情感分类

轻松搞懂Word2vec / FastText+BiLSTM、TextCNN、CNN+BiLSTM、BiLSTM+Attention实现中英文情感分类前言讲道理,这篇博客应该可以帮助很多只有一点点NLP的朋友,在较短的时间内了解文本分类的整个过程并用代码复现整个流程。事先说明,这里大家先不要过分要求自己去理解整个模型的原理,先搞清楚整个实现流程,体验一下敲代码并成功应用的快感。实现流程找数据集首先第一步,就是要找好数据集,没有数据集模型怎么学习,怎么涨知识。那这里呢,我们采用的情感数据集是weibo_senti_100k数据集,一共有119988条带情感标注的新浪微博评论,其中正负向评论均为59994条,非常平衡的一个数据集。其中lab.

大家好,又见面了,我是你们的朋友全栈君。

代码(包括数据集)链接放在文末。

本人在大三期间做了一个关于“疫苗接种”主题的舆情分析,主要涉及的技术有:爬虫(微博和知乎评论)、数据清洗、文本特征提取、建立模型(SVM、BiLSTM、TextCNN、CNN+BiLSTM、BiLSTM+Attention)、文本摘要等。

本篇主要会涉及到关于数据清洗、文本特征提取以及建模(BiLSTM、TextCNN、CNN+BiLSTM、BiLSTM+Attention)几个部分,剩下的内容可以查看我另外几篇博客。

文本特征提取:常见的文本特征(句向量)提取方法有哪些?什么是One-Hot、TF-IDF?word2vec如何训练?【Python】

SVM:轻松搞懂word2vec+SVM(支持向量机)实现中英文情感分类

爬虫:我爬取了知乎和微博上网友们在热门话题讨论的内容,并对其进行了情感分析和关键词提取

英文文本:【TF-IDF、word2vec、svm、cnn、textcnn、bilstm、cnn+bilstm、bilstm+attention】英文长文本分类实战

前言

讲道理,这篇博客应该可以帮助很多只有一点点NLP的朋友,在较短的时间内了解文本分类的整个过程并用代码复现整个流程。事先说明,这里大家先不要过分要求自己去理解整个模型的原理,先搞清楚整个实现流程,体验一下敲代码并成功应用的快感。

模型简介

Bi-LSTM

LSTM的全称是Long Short-Term Memory,它是RNN(Recurrent Neural Network)的一种。LSTM由于其设计的特点,非常适合用于对时序数据的建模,如文本数据,该模型可以学习长期依赖信息,它通过特殊的门结构来去除或增加信息到细胞状态的能力,门是一种让信息选择式通过的方法,一共有三个门。第一层是忘记门,决定我们会从细胞状态中丢弃什么信息,下一步是确定什么样的新信息会被存放在细胞状态,下一步是更新细胞状态,最后输出信息。

而Bi-LSTM模型由前向的LSTM和后向的LSTM组合而成,能够很好的处理双向数据的序列信息。一个LSTM层式从左往右处理,而另一个是从右往左处理。总体而言,更适合应用于长文本的分类任务。

TextCNN

TextCNN模型是由 Yoon Kim提出的Convolutional Naural Networks for Sentence Classification一文中提出的使用卷积神经网络来处理NLP问题的模型。TextCnn在文本分类问题上有着更加卓越的表现。从直观上理解,TextCNN通过一维卷积来获取句子中n-gram的特征表示。TextCNN对文本浅层特征的抽取能力很强,在短文本领域如搜索、对话领域专注于意图分类时效果很好,应用广泛,且速度快,一般是首选;对长文本领域,TextCNN主要靠filter窗口抽取特征,在长距离建模方面能力受限,且对语序不敏感。

CNN+BiLSTM

在一些任务当中,会选择在卷积层后加上一层LSTM或BiLSTM(反过来则不行),用于增强模型对语义的理解。CNN负责提取文本的特征,而BiLSTM负责理解句子的语义信息。当CNN融合了循环神经网络时,就是结合了这两者的功能,往往效果会有所提升。

PS:不要想着拿TextCNN去融合BiLSTM,不是说不能融合,是没有必要。TextCNN本身就是一个非常优秀的模型了,在TextCNN后面加上一层循环神经网络,往往只是带来了更多的计算时间,其本身对于语义的理解,并没有什么帮助,甚至有可能对结果进行干扰。

BiLSTM+注意力机制

当输入的文本非常长的时候,我们之前引以为傲的双向长短期记忆模型也难以成为学霸,对文本有一个很好的向量表达。所以,这个时候就可以考虑使用注意力机制,来尝试抓住文本的重点。具体来讲,Attention机制就是通过保留BiLSTM编码器对输入序列的中间输出结果,再训练一个模型来对这些输入进行选择性的学习并且在模型输出时将输出序列与之进行关联。

实现流程

(1) 找数据集

首先第一步,就是要找好数据集,没有数据集模型怎么学习,怎么涨知识。
那这里呢,我们采用的情感数据集是weibo_senti_100k数据集,一共有119988条带情感标注的新浪微博评论,其中正负向评论均为 59994条,非常平衡的一个数据集。
weibo_senti_100k
其中label为文本标签,1代表正面评论,0代表负面评论。

(2) 数据观察

找完数据集之后呢,我们需要观察对数据集进行观察,判定它是否会不适合我们后续的任务,以及数据集的文本长度大致如何。
这里我们先利用提取关键词的思想,生成一个词云图,用于观察该数据集的热门词。

import os
import numpy as np
import pandas as pd
import jieba.analyse
from jieba import analyse
from PIL import Image
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
from wordcloud import WordCloud,ImageColorGenerator
if __name__ == '__main__':
data = pd.read_csv('weibo_senti_100k.csv', header=0, encoding='utf-8-sig')['review']
tfidf = analyse.extract_tags
for line in data:
if line.strip() == '':
continue
text = line
# tfidf 仅仅从词的统计信息出发,而没有充分考虑词之间的语义信息
keywords = tfidf(text,
allowPOS=('ns', 'nr', 'nt', 'nz', 'nl', 'n', 'vn', 'vd', 'vg', 'v', 'vf', 'a', 'an', 'i'))
result = []
for keyword in keywords:
result.append(keyword)
fo = open('keywords.txt', "a+", encoding='utf-8')  # 生成每句文本的关键词
for j in result:
fo.write(j)
fo.write(' ')
fo.write('\n')
fo.close()
# 开始生成词云图
lyric = ''
f = open('keywords.txt', 'r', encoding='utf-8')
for i in f:
lyric += f.read()
# print(lyric)#自动加+'\n'
# 考虑了相邻词的语义关系、基于图排序的关键词提取算法TextRank
result = jieba.analyse.textrank(lyric, topK=50, withWeight=True)
keywords = dict()
for i in result:
keywords[i[0]] = i[1]
print(keywords)
image = Image.open('./background.png')
graph = np.array(image)
print(graph)
wc = WordCloud(font_path='SIMLI.TTF', background_color='White', max_words=200, mask=graph)
wc.generate_from_frequencies(keywords)
image_color = ImageColorGenerator(graph)  # 设置背景图像
plt.imshow(wc)  # 画图
plt.imshow(wc.recolor(color_func=image_color))  # 根据背景图片着色
plt.axis("off")  # 不显示坐标轴
plt.show()
wc.to_file('wordCloud.png')

数据集词云
通过这个词云图,我们可以发现这个数据集并没有明显的领域偏向,也就是说它并不是单独在某一个领域下的文本内容。比方说,如果该数据集是汽车领域的文本内容,那么当使用该数据集进行其他领域的情感标注时的准确率就会变得相对较低。

在进行实验之前,我进行了对数据集的句子长度与对应的数量进行了统计,大致结果如图所示。
数据集长度统计图
这里我以词为句子长度的基本单位,对数据集的句子长度进行了统计。不难发现的是,数据集的句子长度主要集中在了20附近,当长度超过100时,句子数量就几乎没有了。

(3) 数据预处理

首先,我们可以观察文本的内容,看是否有一些文本内容是对最终的情感标注没有影响甚至会有干扰的。假设我们在后续操作做自己爬取了数据的话,数据多少都会存在一些问题,比方说一些没有意义的标签符号。或者你发现你的任务是对长文本进行情感分类,但是数据集是短文本的时候,是否需要对这些长文本进行文本摘要。(这里我们就不对数据集的文本进行清洗,毕竟人家标注就是针对整个文本标注好的)

接着,我们需要进行文本分词,这里我们用到的是结巴分词。同时我们也可以加载一些语料库,提高分词的准确性。

import jieba
jieba.load_userdict("SogouLabDic.txt")
jieba.load_userdict("dict_baidu_utf8.txt")
jieba.load_userdict("dict_pangu.txt")
jieba.load_userdict("dict_sougou_utf8.txt")
jieba.load_userdict("dict_tencent_utf8.txt")
#jieba.load_userdict("my_dict.txt")
def tokenizer(dataset_texts):
text = [jieba.lcut(document.replace('\n', '')) for document in dataset_texts]
return text

需要注意的是,在很多文本分类的任务中,都会选择去除停用词。但是在情感分类中,也往往会选择不去除停用词。比方说“我可以!!!”和“我可以。”这两句话表达的情感差异是比较大的。当然啦,是否需要去除停用词,最好还是做下对比实验。

(4) 文本特征提取

分完词之后,就是准备将数据扔到模型训练啦。但是,模型可认不得自然语言,你需要将这些文本转换成模型认识的数据格式——矩阵。所以,我们需要对文本进行特征提取,即将文本转换成矩阵的形式。这里就需要用到一些方法啦,比方说传统的平权统计的方法、TF-IDF、BOW等。那在这里我们用到的方法是Word2vec的方法。

Word2vec,是一群用来产生词向量的相关模型。这些模型为浅而双层的神经网络,用来训练以重新建构语言学之词文本。网络以词表现,并且需猜测相邻位置的输入词,在word2vec中词袋模型假设下,词的顺序是不重要的。训练完成之后,word2vec模型可用来映射每个词到一个向量,可用来表示词对词之间的关系,该向量为神经网络之隐藏层。通过Word2Vec算法得到每个词语的高维向量(词向量,Word Embedding)表示,词向量把相近意思的词语放在相近的位置。我们只需要有大量的某语言的语料,就可以用它来训练模型,获得词向量。

那么在这里呢,我们就用数据集的文本来训练word2vec。

from gensim.models.word2vec import Word2Vec
cpu_count = multiprocessing.cpu_count()  
vocab_dim = 100
n_iterations = 1
n_exposures = 10  # 所有频数超过10的词语
window_size = 7
def word2vec_train(data):
"""训练word2vec模型 Parameters ---------- data : 分词后的二维列表 """
model = Word2Vec(size=vocab_dim,
min_count=n_exposures,
window=window_size,
workers=cpu_count,
iter=n_iterations)
model.build_vocab(data)  # input: list
model.train(combined, total_examples=model.corpus_count, epochs=model.iter)
model.save('Word2vec_model.pkl')

此时我们已经得到了训练好的word2vec模型,即可以得到词语对应的词向量。到这里的话,文本特征提取就可以算结束了。但是由于标注是针对整一句话的,而非单独的一个词,我们需要求每一句话的句向量。

from keras.preprocessing import sequence
from gensim.corpora.dictionary import Dictionary
def create_dictionaries(model=None, data=None):
"""将数据集文本转换成句向量,并得到两个词典(单词to序号、单词to向量) Parameters ---------- model : 训练好的word2vec模型 data : 分词后的文本列表 Returns ------- w2indx 数据集中所有单词映射成序号的词典 w2vec 数据集中所有单词映射成向量的词典 data 数据集文本特征矩阵 """
if (data is not None) and (model is not None):
gensim_dict = Dictionary()
gensim_dict.doc2bow(model.wv.vocab.keys(),
allow_update=True)
# freqxiao10->0 所以k+1
w2indx = { 
v: k + 1 for k, v in gensim_dict.items()}  # 频数超过10的词语的索引
f = open("word2index.txt", 'w', encoding='utf8')
for key in w2indx:
f.write(str(key))
f.write(' ')
f.write(str(w2indx[key]))
f.write('\n')
f.close()
w2vec = { 
word: model[word] for word in w2indx.keys()}  # 频数超过10的词语的词向量
def parse_dataset(combined):
data = []
for sentence in combined:
new_txt = []
for word in sentence:
try:
new_txt.append(w2indx[word])
except:
new_txt.append(0)
data.append(new_txt)
return data  # word=>index
data = parse_dataset(data)
data = sequence.pad_sequences(data, maxlen=maxlen)  
return w2indx, w2vec, data
else:
print('文本为空!')

为了满足后续建模的格式要求,这里采用的句特征的表示方法并非这种:[[词1向量], [词2向量], [词3向量], …, [词n向量]],这种表示方式的话,句特征就是一个二维的矩阵,而最终的表示方式为:[词1序号, 词2序号, 词3序号, …, 词n序号],此时句特征就成了一个向量。

另外,由于模型对于输入格式的要求必须是矩阵的形式,那么就要求每个句向量的长度必须统一,但是实际上的句子长度并非统一的形式,所以我们设置了一个maxlen作为句子的最大长度值(这个值的选择可以参考我们在数据观察时得到的数据),当maxlen取100时,句子大于100的话就需要进行切割,句子小于100时,则进行填充(通常是直接补零),这里是直接调用了pad_sequences方法。

注:如果想将word2vec换成fastText,只需要将
from gensim.models.word2vec import Word2Vec换成
from gensim.models.fasttext import FastText再将对应位置的Word2Vec换成FastText即可。

(5) 划分训练集

import numpy as np
import keras
from sklearn.model_selection import train_test_split
def get_data(w2indx, w2vec, data, y):
n_symbols = len(w2indx) + 1  # 补上索引为0(频数小于10)的词
embedding_weights = np.zeros((n_symbols, vocab_dim))  
for word, index in w2indx.items(): 
embedding_weights[index, :] = w2vec[word]
x_train, x_test, y_train, y_test = train_test_split(data, y, test_size=0.2)
y_train = keras.utils.to_categorical(y_train, num_classes=2)  # 转换为one-hot特征
y_test = keras.utils.to_categorical(y_test, num_classes=2)
return n_symbols, embedding_weights, x_train, y_train, x_test, y_test

这里是将数据集按8:2的比例划分成了训练集和测试集,并且得到了一个词典,该词典的关键词为词序号,对应的值为词向量。

(6) 建立模型

采用的损失函数为都是交叉熵损失函数,使用Adam进行优化。

BiLSTM代码复现如下:

from keras.models import Sequential
from keras.models import load_model
from keras.layers import Bidirectional, Activation
from keras.layers.embeddings import Embedding
from keras.layers.recurrent import LSTM
from keras.layers.core import Dense, Dropout
def train_bilstm(n_symbols, embedding_weights, x_train, y_train):
model = Sequential()  # or Graph or whatever
model.add(Embedding(output_dim=vocab_dim,
input_dim=n_symbols,
mask_zero=True,
weights=[embedding_weights],
input_length=maxlen))  
model.add(Bidirectional(LSTM(output_dim=50, activation='tanh')))
model.add(Dropout(0.5))
model.add(Dense(2, activation='softmax'))  
model.compile(loss='categorical_crossentropy',
optimizer='adam', metrics=['accuracy'])
model.fit(x_train, y_train, batch_size=batch_size, epochs=n_epoch, verbose=2)
model.save('bilstm.h5')
train_bilstm(n_symbols, embedding_weights, x_train, y_train)

TextCNN代码复现如下:

import keras
from keras import Input, Model
from keras.preprocessing import sequence
from keras.models import load_model
from keras.layers import Conv1D, MaxPooling1D, concatenate
from keras.layers.embeddings import Embedding
from keras.layers.core import Dense, Dropout, Flatten
def train_textcnn(n_symbols, embedding_weights, x_train, y_train):
main_input = Input(shape=(maxlen,), dtype='float64')
embedder = Embedding(output_dim=vocab_dim,
input_dim=n_symbols,
input_length=maxlen,
weights=[embedding_weights])
embed = embedder(main_input)
cnn1 = Conv1D(256, 3, padding='same', strides=1, activation='relu')(embed)
cnn1 = MaxPooling1D(pool_size=38)(cnn1)
cnn2 = Conv1D(256, 4, padding='same', strides=1, activation='relu')(embed)
cnn2 = MaxPooling1D(pool_size=37)(cnn2)
cnn3 = Conv1D(256, 5, padding='same', strides=1, activation='relu')(embed)
cnn3 = MaxPooling1D(pool_size=36)(cnn3)
# 合并三个输出向量
cnn = concatenate([cnn1, cnn2, cnn3], axis=-1)
flat = Flatten()(cnn)
drop = Dropout(0.5)(flat)
main_output = Dense(2, activation='softmax')(drop)
model = Model(inputs=main_input, outputs=main_output)
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(x_train, y_train, batch_size=batch_size, epochs=n_epoch, verbose=2)
model.save('textcnn.h5')
train_textcnn(n_symbols, embedding_weights, x_train, y_train)

CNN+BiLSTM代码复现如下:

import keras
from keras import Input, Model
from keras.preprocessing import sequence
from keras.models import load_model
from keras.layers import Conv1D, MaxPooling1D, concatenate
from keras.layers import Bidirectional
from keras.layers.embeddings import Embedding
from keras.layers.recurrent import LSTM
from keras.layers.core import Dense, Dropout, Flatten
def train_cnn_bilstm(n_symbols, embedding_weights, x_train, y_train):
main_input = Input(shape=(maxlen,), dtype='float64')
embedder = Embedding(output_dim=vocab_dim,
input_dim=n_symbols,
input_length=maxlen,
weights=[embedding_weights])
embed = embedder(main_input)
cnn = Conv1D(64, 3, padding='same', strides=1, activation='relu')(embed)
bilstm = Bidirectional(LSTM(output_dim=50, dropout=0.5, activation='tanh', return_sequences=True))(cnn)
flat = Flatten()(bilstm)
main_output = Dense(2, activation='softmax')(flat)
model = Model(inputs=main_input, outputs=main_output)
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(x_train, y_train, batch_size=batch_size, epochs=n_epoch)
model.save('cnnbilstm.h5')
train_cnn_bilstm(n_symbols, embedding_weights, x_train, y_train)

BiLSTM+注意力机制代码复现如下:

import keras
from keras import backend as K
from keras.models import Sequential
from keras.engine.topology import Layer
from keras.layers import Bidirectional
from keras.layers.embeddings import Embedding
from keras.layers.recurrent import LSTM
from keras.layers.core import Dense
# 自定义Attention层
class AttentionLayer(Layer):
def __init__(self, attention_size=None, **kwargs):
self.attention_size = attention_size
super(AttentionLayer, self).__init__(**kwargs)
def get_config(self):
config = super().get_config()
config['attention_size'] = self.attention_size
return config
def build(self, input_shape):
assert len(input_shape) == 3
self.time_steps = input_shape[1]
hidden_size = input_shape[2]
if self.attention_size is None:
self.attention_size = hidden_size
self.W = self.add_weight(name='att_weight', shape=(hidden_size, self.attention_size),
initializer='uniform', trainable=True)
self.b = self.add_weight(name='att_bias', shape=(self.attention_size,),
initializer='uniform', trainable=True)
self.V = self.add_weight(name='att_var', shape=(self.attention_size,),
initializer='uniform', trainable=True)
super(AttentionLayer, self).build(input_shape)
def call(self, inputs):
self.V = K.reshape(self.V, (-1, 1))
H = K.tanh(K.dot(inputs, self.W) + self.b)
score = K.softmax(K.dot(H, self.V), axis=1)
outputs = K.sum(score * inputs, axis=1)
return outputs
def compute_output_shape(self, input_shape):
return input_shape[0], input_shape[2]
##定义网络结构
def train_bilstm_att(n_symbols, embedding_weights, x_train, y_train, ATT_SIZE):
model = Sequential()
model.add(Embedding(output_dim=vocab_dim,
input_dim=n_symbols,
weights=[embedding_weights],
input_length=maxlen))
model.add(Bidirectional(LSTM(output_dim=50, dropout=0.5, return_sequences=True)))
model.add(AttentionLayer(attention_size=ATT_SIZE))
model.add(Dense(2, activation='softmax'))  
model.compile(loss='categorical_crossentropy',
optimizer='adam', metrics=['accuracy'])
model.fit(x_train, y_train, batch_size=batch_size, epochs=n_epoch)
model.save('bilstmAtt.h5')
train_bilstm_att(n_symbols, embedding_weights, x_train, y_train)

补充一下,实现CNN+BiLSTM+Attention的融合模型的话,只需简单的在CNN+BiLSTM后加上一层Attention,或者在BiLSTM+Attention模型中的嵌入层后加上一层卷积层即可。

(7) 模型评估

from keras.models import load_model
from sklearn.metrics import classification_report
if __name__ == '__main__':
model = load_model('bilstm.h5')
# model = load_model('textcnn.h5')
# model = load_model('cnnbilstm.h5')
# model = load_model('bilstmAtt.h5', custom_objects={'AttentionLayer':AttentionLayer})
y_pred = model.predict(x_test)
for i in range(len(y_pred)):
max_value = max(y_pred[i])
for j in range(len(y_pred[i])):
if max_value == y_pred[i][j]:
y_pred[i][j] = 1
else:
y_pred[i][j] = 0
# target_names = ['负面', '正面']
print(classification_report(y_test, y_pred))

自己玩玩

在这里插入图片描述

“智能”推荐:
轻松搞懂word2vec+SVM(支持向量机)实现中英文情感分类
【TF-IDF、word2vec、svm、cnn、textcnn、bilstm、cnn+bilstm、bilstm+attention】英文长文本分类实战


代码下载链接,有需要的请自行提取,不想hua前的朋友,可评论同我说,我会回复你,但可能会比较慢。祝好!

https://download.csdn.net/download/qq_44186838/60887420


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/154000.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • vb.net从数据库中取数据

    vb.net从数据库中取数据1.设置从Model中的SubMain启动2.程序结构3.Model14.FormStudentSysMain.vb5.FormSearchStudent.vb6.运行结果

  • 小白学电脑计算机的组成,新手学电脑步骤,从零开始学电脑「建议收藏」

    小白学电脑计算机的组成,新手学电脑步骤,从零开始学电脑「建议收藏」如今,手机已经成为我们生活中不可缺少的必需品,各种手机应用软件的层出不穷,使得智能手机占据了互联网的半壁江山,似乎手机无所不能了,平时,很多人觉得一手机在手便可以仗剑走天涯,但当我们走进职场,你就会发现,对于办公而言,手机还是有很大的局限性,掌握电脑知识,熟悉电脑基本操作是胜任工作的必备技能。真是“书到用时方恨少”。今天开始,涛哥就带你走进电脑的世界,让你从电脑小白跃升为办公自动化高手。那么对于一…

  • spark 入门_新手入门

    spark 入门_新手入门一Spark概述 111什么是Spark 2Spark特点 3Spark的用户和用途 二Spark集群安装 1集群角色 2机器准备 3下载Spark安装包 4配置SparkStandalone 5配置JobHistoryServerStandalone 6配置SparkHAStandalone 7配置SparkYarn …

    2022年10月24日
  • 潜意识的牢笼——为什么这件事情这么难

    潜意识的牢笼——为什么这件事情这么难

  • so文件在线加固加密_安卓so文件解密

    so文件在线加固加密_安卓so文件解密这篇是一系列的关于SO文件保护的自我理解,SO文件保护分为加固,混淆以及最近炒的比较火的虚拟机,由于本人菜鸟,无力分析虚拟机,我相信以后会有机会。。。加固就是将真正的so代码保护起来,不让攻击者那么轻易的发现,至于混淆,由于ART机制的介入,使得O-LLVM越来越火,这以后有机会再分析,这次主要是基于有源码的so文件保护,下次介绍无源码的so文件保护,废话不多说,开搞。在这之前首先对e

  • nginx面试常见问题_面试官应该问哪些问题

    nginx面试常见问题_面试官应该问哪些问题1.什么是Nginx?Nginx是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器目前使用的最多的web服务器或者代理服务器,像淘宝、新浪、网易、迅雷等都在使用2.为什么要用Nginx?优点:*跨平台、配置简单*非阻塞、高并发连接:处理2-3万并发连接数,官方…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号