基于LSTM的情绪分析
1. 摘要
自然语言处理是当代机器学习一块很重要的分支,而情绪分析也是NLP中的重要研究部分。本文为基于简单的“情绪数据集”,通过词向量模型,LSTM等方法训练神经网络模型,对句子进行情绪上的分类与识别。最终识别准确率可达到90.95%。
关键词:NLP, 文本情感分析,情绪分析,词向量模型,LSTM,神经网络,深度学习。
2. 引言
自然语言处理(NLP)是一种专业分析人类语言的人工智能。它接收自然语言,
转译自然语言,最后分析自然语言并输出结果。文本情感分析(Sentiment Analysis)是指利用自然语言处理和文本挖掘技术,对带有情感色彩的主观性文本进行分析、处理和抽取的过程。
深度学习技术发展到今天,在自然语言处理领域有很多的应用。而由于人类语言的多样性、多意性,使得NLP的难度成倍增加。例如由相同的三个字形成的组合“不怕辣”、“辣不怕”、“怕不辣”、“怕辣不”表达了不同的含义。因此,对于自然语言的处理仍具有挑战性与发展空间。本文旨在分析自然语言语句(英语为例),来对其表达的情绪进行归类于分析。
3. 主要研究技术与方法
3.1 词向量模型
人类想要读懂一句话往往非常容易,然而对于机器来讲却是一个需要不断学习的漫长而复杂的过程。想要让机器读懂一句话,我们必须将自然语言转化成计算机可识别的数字。文本向量化表示就是用数值向量来表示文本的语义。我们人类在读一段文本后立刻就能明白它要表达的内容,如何让机器也能拥有这样的能力呢?
文本分类领域使用了信息检索领域的词袋模型,词袋模型在部分保留文本语义的前提下对文本进行向量化表示。通过词袋模型(bag of words)对句子进行分词并向量化,形成D维向量,再输入网络中计算:
- One-Hot:
One-Hot表示法的数值计算规则为:词语序列中出现的词语其数值为1,词语序列中未出现的词语其数值为0。对应关系如下图所示:
- Word2Vec:
这个模型根据上下文的语境来推断出每个词的词向量。如果两个词在上下文的语境中,可以被互相替换,那么这两个词的距离就非常近。在自然语言中,上下文的语境对分析词语的意义是非常重要的。所以,这个模型的作用就是从一大堆句子(以Wikipedia为例)中为每个独一无二的单词进行建模,并且输出一个唯一的向量。Word2Vec模型的输出被称为一个嵌入矩阵。
- Tokenizer:
Tokenizer 是keras中一个用于向量化文本,或将文本转换为序列的类。计算机在处理语言文字时,是无法理解文字的含义,通常会把一个词(中文单个字或者词组认为是一个词)转化为一个正整数,于是一个文本就变成了一个序列。Tokenizer 的核心任务就是做这个事情。本文将单词向量化用的方法就是此方法。
3.2 循环神经网络RNN(Recurrent Neural Networks)
在得到了神经网络的输入数据——词向量后,我们需要确定将要构建的神经网络。NLP数据的一个独特之处是它是时间序列数据。每个单词的出现都依赖于它的前一个单词和后一个单词。由于这种依赖的存在,我们使用循环神经网络来处理这种时间序列数据。
循环神经网络的结构和你之前看到的那些前馈神经网络的结构可能有一些不一样。前馈神经网络由三部分组成,输入层、隐藏层和输出层。
前馈神经网络和RNN之前的主要区别就是RNN考虑了时间的信息。在RNN中,句子中的每个单词都被考虑上了时间步骤。实际上,时间步长的数量将等于最大序列长度。
与每个时间步骤相关联的中间状态也被作为一个新的组件,称为隐藏状态向量h(t)。从抽象的角度来看,这个向量是用来封装和汇总前面时间步骤中所看到的所有信息。就像x(t)表示一个向量,它封装了一个特定单词的所有信息。
隐藏状态是当前单词向量和前一步的隐藏状态向量的函数。并且这两项之和需要通过激活函数来进行激活。
然而,RNN存在一个致命的缺点——即梯度消失的问题,很难处理长序列的数据。为了解决此问题,我们又引入了本文所用到的方法:LSTM。
3.3 长时间的短期记忆模型LSTM(Long Short-Term Memory)
为了解决RNN存在问题,后续人们对RNN做了改进,得到了RNN的特例LSTM,它可以避免常规RNN的梯度消失,因此在工业界得到了广泛的应用。LSTM模型是RNN的变体,它能够学习长期依赖,允许信息长期存在。
举个例子来讲:比如人们读文章的时候,人们会根据已经阅读过的内容来对后面的内容进行理解,不会把之前的东西都丢掉从头进行思考,对内容的理解是贯穿的。
传统的神经网络即RNN做不到这一点,LSTM是具有循环的网络,解决了信息无法长期存在的问题,在工业界普遍使用有良好的效果。
RNN与LSTM之间的联系:
RNN具有如下的结构,每个序列索引位置t都有一个隐藏状态h(t):
如果略去每层都有的o(t),L(t),y(t),则RNN的模型可以简化成如下图的形式:
可以看出h(t)由x(t)和h(t−1)得到。得到h(t)后一方面用于当前层的模型损失计算,另一方面用于计算下一层的h(t+1)。
为了避免RNN的梯度消失,LSTM将tanh激活函数转为更为复杂的结构。LSTM的结构如下图:
粉红色圆圈表示点向运算,如向量加法、点乘,而黄色框是学习神经网络层。 线的合并表示连接,而线的交叉表示其内容正在复制,副本将转到不同的位置。
LSTM的工作原理:
对于一个典型的RNN网络,隐藏状态向量对于第二句的存储信息量可能比第一句的信息量会大很多。但是LSTM,基本上就会判断哪些信息是有用的,哪些是没用的,并且把有用的信息在LSTM中进行保存。LSTM的单元根据输入数据x(t),隐藏层输出h(t)。在这些单元中,h(t)的表达形式比经典的RNN网络会复杂很多。这些复杂组件分为四个部分:输入门、输出门、遗忘门和一个记忆控制器。
每个门都将x(t)和h(t-1)作为输入,并且利用这些输入来计算一些中间状态。每个中间状态都会被送入不同的管道,并且这些信息最终会汇集到h(t)。这些门可以被认为是不同的模块,各有不同的功能。Ct是控制参数,控制什么样的值保留,什么样的值舍弃,输入门决定在每个输入上施加多少强调,遗忘门决定我们将丢弃什么信息,输出门根据中间状态来决定最终的h(t)。
简要来说,LSTM 单元能够学习到识别重要输入(输入门作用),存储进长时状态,并保存必要的时间(遗忘门功能),并学会提取当前输出所需要的记忆。这也解释了 LSTM 单元能够在提取长时序列,长文本,录音等数据中的长期模式的惊人成功的原因。
4. 神经网络的搭建与分析
4.1数据集描述及导入
本次的数据集来自Kaggel上专门为情感分析提供的数据集。地址 https://www.kaggle.com/praveengovi/emotions-dataset-for-nlp
该数据集包含了三个文档
- 16000行的训练数据集:train.txt
- 2000行的测试数据集:test.txt
- 2000行的验证数据集:val.txt
通过这三个文档我们将建立机器学习模型。以下是train.txt的部分数据:
Eg: i didnt fell humiliated;sadness,这条数据中包含了:1. 句子的具体内容: i didnt fell humiliated; 2. 事先人为分类号的情绪标签: sadness。
导入并展示:
# 导入数据集
train = pd.read_csv('E:/大三下/机器学习/NLP情感分析/train.txt', sep=';', header=None)
# 重命名Dataframe列名
train.columns=['Sentence', 'Sentiment']
# 统计数据集中情感种类以及出现次数
train['Sentiment'].value_counts()
joy 5362
sadness 4666
anger 2159
fear 1937
love 1304
surprise 572
Name: Sentiment, dtype: int64
train
Sentence | Sentiment | |
---|---|---|
0 | i didnt feel humiliated | sadness |
1 | i can go from feeling so hopeless to so damned... | sadness |
2 | im grabbing a minute to post i feel greedy wrong | anger |
3 | i am ever feeling nostalgic about the fireplac... | love |
4 | i am feeling grouchy | anger |
... | ... | ... |
15995 | i just had a very brief time in the beanbag an... | sadness |
15996 | i am now turning and i feel pathetic that i am... | sadness |
15997 | i feel strong and good overall | joy |
15998 | i feel like this was such a rude comment and i... | anger |
15999 | i know a lot but i feel so stupid because i ca... | sadness |
16000 rows × 2 columns
4.2 数据预处理:数据清洗及向量化
在拿到一份数据集时,首先要做的事就是对数据集进行预处理,以便得到可用于模型训练的数据集。
- 对于该数据集进行了大小写转换,标点去除等操作:
train['Sentence'] = train['Sentence'].apply(lambda x: x.lower())data['Sentence'] = train['Sentence'].apply((lambda x: re.sub('[^a-zA-z0-9\s]','',x)))
- 将情感分类转化为数值,以便后续更方便处理:
#添加一列EmoID,将每种情感对应一个数字方便处理:{"joy": 1, "sadness": 2, "anger": 3, "fear": 4, "love": 5, "surprise": 6} train['SentiID'] = '' for i in train.index:if train.loc[i, 'Sentiment'] == 'joy':train.loc[i, 'SentiID'] = 1elif train.loc[i, 'Sentiment'] == 'sadness':train.loc[i, 'SentiID'] = 2elif train.loc[i, 'Sentiment'] == 'anger':train.loc[i, 'SentiID'] = 3elif train.loc[i, 'Sentiment'] == 'fear':train.loc[i, 'SentiID'] = 4elif train.loc[i, 'Sentiment'] == 'love':train.loc[i, 'SentiID'] = 5elif train.loc[i, 'Sentiment'] == 'surprise':train.loc[i, 'SentiID'] = 6
- 统计各情绪出现的次数,并绘图:
# 绘制情感统计图 sns.countplot(train['Sentiment']) plt.title('The count of sentiment')
- 统计每句话的长度及出现频率:
# 统计每句话的词数 Sentlist = train['Sentence'].tolist() total = [] count = [] for i in range(0, len(Sentlist)):total.append(Sentlist[i].split()) for j in range(0, len(total)):count.append(len(total[j]))# 绘制长度分布图 frequency = Counter(count) x1 = list(frequency.keys()) y1 = list(frequency.values()) plt.bar(x1, y1) plt.xlabel('Sentence Length') plt.ylabel('Frequency') plt.title('Sentence length distribution') plt.show()
我们可以看出,句子的最大长度为70左右,而大多数句子长度分布在15附近。
在清洗完成过后,我们进行词的向量化:
作为该领域的一个最大玩家,Google已经帮我们在大规模数据集上训练出来了Word2Vec模型,包括1000亿个不同的词。在这个模型中,谷歌能创建300万个词向量,每个向量维度为300。在理想情况下,我们将使用这些向量来构建模型,但是因为这个单词向量矩阵想当大(3.6G),跑起来十分缓慢,同时自己训练Word2Vec的效果也不是最佳,因此本文采用更为轻量化的keras提供的Tokenizer
分词器。我定义最大特征的数量为2000,并使用Tokenizer向量化和将文本转换为序列,以便网络可以处理它作为输入。
max_fatures = 2000
tokenizer = Tokenizer(num_words = max_fatures, split=' ')
tokenizer.fit_on_texts(train['Sentence'].values)
X = tokenizer.texts_to_sequences(train['Sentence'].values)
X = pad_sequences(X)
4.3 LSTM神经网络的搭建
超参数调优: 选择合适的超参数来训练你的神经网络是至关重要的。训练损失值与你选择的优化器、学习率和网络架构都有很大的关系。特别是在RNN和LSTM中,单元数量和词向量的大小都是重要因素。embed_dim
、lstm_out
、batch_size
、droupout_x
变量都是超参数,它们的值在某种程度上是直观的,正确地调整使用它们才能获得良好的结果。文中没有设置的参数按照默认参数配置。
max_fatures
: 词汇表大小。这里设置为2000;embed_dim
: 词向量的维度。这里设置为128;input_length
: 输入序列的长度,当它是固定的时。如果你需要连接Flatten和Dense层,则这个参数是必须的。这里设置为61;SpatialDropout1D
: 一种dropout方法。随机地将部分区域置零。这里设置为0.4;lstm_out
: LSTM的输出维度。这里设置为196;dropout
: 使多少比重的神经元输出(unit的输出)激活失效,默认为0。这里设置为0.2;recurrent_dropout
: recurrent_dropout是给递归状态 C 设置的Dropout参数。这里设置为0.2;Dense
: 全连接层,最后输出为6。并且最后一层的激活函数选用softmax
;loss
: 损失函数。这里选用交叉熵损失函数。交叉熵损失函数经常用于分类问题中,它能衡量同一个随机变量中的两个不同概率分布的差异程度,在机器学习中就表示为真实概率分布与预测概率分布之间的差异。交叉熵的值越小,模型预测效果就越好;optimizer
: 优化器。这里选用Adam。它结合AdaGrad和RMSProp两种优化算法的优点。对梯度的一阶矩估计和二阶矩估计进行综合考虑,计算出更新步长;metrics
: 定义评价函数。这里选用accuracy;
embed_dim = 128
lstm_out = 196model = Sequential()
model.add(Embedding(max_fatures, embed_dim,input_length = X.shape[1]))
model.add(SpatialDropout1D(0.4))
model.add(LSTM(lstm_out, dropout=0.2, recurrent_dropout=0.2))
model.add(Dense(6, activation='softmax'))
model.compile(loss = 'categorical_crossentropy', optimizer='adam', metrics = ['accuracy'])
查看神经网络情况:
print(model.summary())
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding_1 (Embedding) (None, 61, 128) 256000
_________________________________________________________________
spatial_dropout1d_1 (Spatial (None, 61, 128) 0
_________________________________________________________________
lstm_1 (LSTM) (None, 196) 254800
_________________________________________________________________
dense_1 (Dense) (None, 6) 1182
=================================================================
Total params: 511,982
Trainable params: 511,982
Non-trainable params: 0
_______________________________________________________________
None
分离训练集,测试集:
Y = pd.get_dummies(train['SentiID']).values
X_train, X_test, Y_train, Y_test = train_test_split(X,Y, test_size = 0.33, random_state = 42)
print(X_train.shape,Y_train.shape)
print(X_test.shape,Y_test.shape)
(10720, 61) (10720, 6)
(5280, 61) (5280, 6)
训练网络:
batch_size = 32
history = model.fit(X_train, Y_train, epochs = 20, batch_size = batch_size, verbose = 1, validation_split = 0.2)
print(model.evaluate(X_test, Y_test))
Instructions for updating:
Use tf.cast instead.
Train on 8576 samples, validate on 2144 samples
Epoch 1/20
8576/8576 [==============================] - 24s 3ms/step - loss: 1.5044 - acc: 0.3981 - val_loss: 1.1840 - val_acc: 0.5648
Epoch 2/20
8576/8576 [==============================] - 24s 3ms/step - loss: 0.7453 - acc: 0.7556 - val_loss: 0.5421 - val_acc: 0.8321
Epoch 3/20
8576/8576 [==============================] - 25s 3ms/step - loss: 0.3271 - acc: 0.8935 - val_loss: 0.3255 - val_acc: 0.8839
Epoch 4/20
8576/8576 [==============================] - 26s 3ms/step - loss: 0.2076 - acc: 0.9254 - val_loss: 0.2561 - val_acc: 0.9072
Epoch 5/20
8576/8576 [==============================] - 25s 3ms/step - loss: 0.1603 - acc: 0.9405 - val_loss: 0.2710 - val_acc: 0.8969
Epoch 6/20
8576/8576 [==============================] - 24s 3ms/step - loss: 0.1316 - acc: 0.9492 - val_loss: 0.2504 - val_acc: 0.9128
Epoch 7/20
8576/8576 [==============================] - 26s 3ms/step - loss: 0.1128 - acc: 0.9574 - val_loss: 0.2466 - val_acc: 0.9104
Epoch 8/20
8576/8576 [==============================] - 27s 3ms/step - loss: 0.1048 - acc: 0.9595 - val_loss: 0.2413 - val_acc: 0.9165
Epoch 9/20
8576/8576 [==============================] - 26s 3ms/step - loss: 0.0837 - acc: 0.9668 - val_loss: 0.2586 - val_acc: 0.9109
Epoch 10/20
8576/8576 [==============================] - 25s 3ms/step - loss: 0.0819 - acc: 0.9684 - val_loss: 0.2777 - val_acc: 0.9095
Epoch 11/20
8576/8576 [==============================] - 24s 3ms/step - loss: 0.0749 - acc: 0.9722 - val_loss: 0.2732 - val_acc: 0.9067
Epoch 12/20
8576/8576 [==============================] - 24s 3ms/step - loss: 0.0700 - acc: 0.9734 - val_loss: 0.2782 - val_acc: 0.9137
Epoch 13/20
8576/8576 [==============================] - 25s 3ms/step - loss: 0.0567 - acc: 0.9788 - val_loss: 0.2935 - val_acc: 0.9062
Epoch 14/20
8576/8576 [==============================] - 27s 3ms/step - loss: 0.0596 - acc: 0.9782 - val_loss: 0.2943 - val_acc: 0.9090
Epoch 15/20
8576/8576 [==============================] - 26s 3ms/step - loss: 0.0548 - acc: 0.9788 - val_loss: 0.3360 - val_acc: 0.9086
Epoch 16/20
8576/8576 [==============================] - 24s 3ms/step - loss: 0.0454 - acc: 0.9836 - val_loss: 0.3751 - val_acc: 0.9016
Epoch 17/20
8576/8576 [==============================] - 27s 3ms/step - loss: 0.0519 - acc: 0.9823 - val_loss: 0.3499 - val_acc: 0.9072
Epoch 18/20
8576/8576 [==============================] - 25s 3ms/step - loss: 0.0381 - acc: 0.9869 - val_loss: 0.3477 - val_acc: 0.9114
Epoch 19/20
8576/8576 [==============================] - 26s 3ms/step - loss: 0.0391 - acc: 0.9865 - val_loss: 0.3552 - val_acc: 0.9062
Epoch 20/20
8576/8576 [==============================] - 26s 3ms/step - loss: 0.0454 - acc: 0.9848 - val_loss: 0.3569 - val_acc: 0.9058
5280/5280 [==============================] - 4s 695us/step
[0.3139003471513702, 0.9094696969696969]
由结果可看出,最终模型准确率达到90.95%。
最终画出模型准确率以及损失随迭代次数的变化图像:
# 准确率的变化
plt.plot(history.history['acc'], color = 'orange')
plt.title("Train_history")
plt.ylabel('accuracy')
plt.xlabel('Epoch')
plt.show()
# 训练中的损失图像
plt.plot(history.history['loss'])
plt.title("Train_history")
plt.ylabel('loss')
plt.xlabel('Epoch')
plt.show()
5.模型测试
# "joy": 0, "sadness": 1, "anger": 2, "fear": 3, "love": 4, "surprise": 5
txt = ['The sentence you are going to predict']
txt = tokenizer.texts_to_sequences(txt)
txt = pad_sequences(txt, maxlen=61, dtype='int32', value=0)
sentiment = model.predict(txt, batch_size=1, verbose = 1)[0]
if(np.argmax(sentiment) == 0):print("情绪为:joy")
elif (np.argmax(sentiment) == 1):print("情绪为:sadness")
elif (np.argmax(sentiment) == 2):print("情绪为:anger")
elif (np.argmax(sentiment) == 3):print("情绪为:fear")
elif (np.argmax(sentiment) == 4):print("情绪为:love")
elif (np.argmax(sentiment) == 5):print("情绪为:surprise")
i had been talking to coach claudia barcomb and coach ali boe for a long time and they both made me feel very welcomed at union,预分类为joy:
txt = ['i had been talking to coach claudia barcomb and coach ali boe for a long time and they both made me feel very welcomed at union']
1/1 [==============================] - 0s 7ms/step情绪为:joy
预测成功;
im feeling rather rotten so im not very ambitious right now,预分类为sadness:
txt = ['im feeling rather rotten so im not very ambitious right now']
1/1 [==============================] - 0s 8ms/step情绪为:sadness
预测成功;
i jest i feel grumpy tired and pre menstrual which i probably am but then again its only been a week and im about as fit as a walrus on vacation for the summer,预分类为anger:
txt = ['i jest i feel grumpy tired and pre menstrual which i probably am but then again its only been a week and im about as fit as a walrus on vacation for the summer']
1/1 [==============================] - 0s 7ms/step情绪为:anger
预测成功;
i cant walk into a shop anywhere where i do not feel uncomfortable,预分类为fear:
txt = ['i cant walk into a shop anywhere where i do not feel uncomfortable']
1/1 [==============================] - 0s 8ms/step情绪为:fear
预测成功;
i were to go overseas or cross the border then i become a foreigner and will feel that way but never in my beloved land,预分类为love:
txt = ['i were to go overseas or cross the border then i become a foreigner and will feel that way but never in my beloved land']
1/1 [==============================] - 0s 7ms/step情绪为:love
预测成功;
i am right handed however i play billiards left handed naturally so me trying to play right handed feels weird,预分类为surprise:
txt = ['i am right handed however i play billiards left handed naturally so me trying to play right handed feels weird']
1/1 [==============================] - 0s 8ms/step情绪为:surprise
预测成功。
基于LSTM的情绪分析相关推荐
- 手把手教你实现基于LSTM的情感分析(LSTM-based Sentiment) Classification
首先推荐一个Jupyter环境,是由Google提供的colab(https://colab.research.google.com/),有免费的GPU可以使用 第一次使用需要在实验环境中下载相关的p ...
- 在冰山一角之下:情绪分析研究的当前挑战和新方向。
摘要:自20年前作为一项任务首次引入以来,抽象情绪分析作为一个领域已经走过了很长的路.它在市场营销.风险管理.市场研究和政治等各个领域都有广泛的商业应用.考虑到它在特定子任务(如情绪极性分类)和数据集 ...
- 实战项目-用户评论数据情绪分析
目录 1.基于词典的方法 2.基于词袋或 Word2Vec 的方法 2.1 词袋模型 2.2 Word2Vec 3.案例:用户评论情绪分析 3.1 数据读取 3.2 语料库分词处理 3.3 Word2 ...
- 基于LSTM的情感识别在鹅漫电商评论分析中的实践与应用
导语 深度学习(深度神经网络)作为机器学习的一个重要分支,持续推动了很多领域的研究和应用取得新的进展,其中包括文本处理领域的情感分类问题.由于可以对文本进行更有效的编码及表达,基于深度学习的情感分类对 ...
- lstm模型_基于LSTM模型的学生反馈文本学业情绪识别方法
| 全文共8155字,建议阅读时长8分钟 | 本文由<开放教育研究>授权发布 作者:冯翔 邱龙辉 郭晓然 摘要 分析学生学习过程产生的反馈文本,是发现其学业情绪的重要方式.传统的学业情绪 ...
- 工程师程序员的自我修养 Episode.4 基于百度飞桨PaddlePaddle框架的女朋友情绪分析防被打消息推荐深度学习系统
具体为什么想到这个题目呢...大概是我也想不出别的什么有趣的话题或者项目的工作了吧. 有一天,柏拉图问老师苏格拉底什么是爱情?老师就让他到理论麦田里去,摘一棵全麦田里最大最金黄的麦穗来,期间只能摘一次 ...
- 基于LSTM的情感识别在鹅漫评论分析中的实践与应用
深度学习(深度神经网络)作为机器学习的一个重要分支,持续推动了很多领域的研究和应用取得新的进展,其中包括文本处理领域的情感分类问题.由于可以对文本进行更有效的编码及表达,基于深度学习的情感分类对比传统 ...
- 论文浅尝 | 嵌入常识知识的注意力 LSTM 模型用于特定目标的基于侧面的情感分析...
MaY, Peng H, Cambria E. Targeted aspect-based sentiment analysis via embedding commonsense knowledge ...
- 基于LSTM三分类的文本情感分析,采用LSTM模型,训练一个能够识别文本postive, neutral, negative三种
基于LSTM三分类的文本情感分析,采用LSTM模型,训练一个能够识别文本postive, neutral, negative三种 ,含数据集可直接运行 完整代码下载地址:基于LSTM三分类的文本情感分 ...
最新文章
- JAVA——Scanner类绑定System.in后调用close()方法所引发的错误及其解决方案
- 「offer来了」面试中必考的15个html知识点
- Java字符串的重要性_java中的字符串相关知识整理
- 计算机对医学影像学的作用,医学影像技术中数字图像处理的重要性
- python最适合做什么-学习Python适合就业哪些岗位?老男孩Python学习
- 堆区和方法区的小认识
- 【最新首发】创维电视安装第三方软件教程
- 什么是数据可视化?hightopo数据可视化助力企业数字化
- Win10如何开启IIS服务以及如何打开IIS管理器
- 恢复被误删的ESP引导分区
- 微信小程序用户隐私保护指引设置怎么填?
- android飞机大战功能,安卓飞机大战(二) SurfaceView实现自制背景
- 【JAVA编程】根据年龄, 来打印出当前年龄的人是哪个阶段
- UVA 1262 Password
- 【线性代数】标准正交矩阵与Gram-Schmidt正交化
- swf怎么和php实现交互,用ActionScript与JavaScript实现Flash与网页的交互
- oracle 分页公式
- 【锐捷无线】AC热备配置
- Java中float_java中float指的是什么意思
- 2019 年,学习WEB前端开发应该关注哪些新技术