学习记录

  • 一级目录
  • 二级目录
  • 1.CNN(Convolutional Neural Networks,卷积神经网络)
  • 1.1神经元
  • 1.2激活函数
  • 1.3神经网络
  • 1.4卷积神经网络
  • 1.5什么是卷积
  • 2.RNN(Recurrent Neural Networks,循环神经网络)
  • 3.LSTM(Long Short Term Memory,长时间记忆网络)
  • 4.GRU(Gated Recurrent Unit)
  • 5.LSTM实例(非原创)


一级目录

二级目录

1.CNN(Convolutional Neural Networks,卷积神经网络)

1.1神经元

就像人类的神经网络一样,卷积神经网络也是由大量的神经元相互连接而成,每个神经元接受线性组合的输入之后,最开始只是简单的线性加权,后来给每个神经元加上了非线性的激活函数,从而进行非线性变换后输出。每两个神经元之间的连接代表权值,称之为权重(weight)。不同的权重和激活函数,就会导致神经网络不同的输出。

神经网络的每个神经元如下:

attention 学习权重分布 cnn 权重_权重


基本wx+b的形式,其中x1、x2表示输入的变量,w1,w2为权重,有几个输入就会有几个权重,b为偏置bias,g(z)为激活函数,a为输出,g(z)=g(w1x1+w2x2+b)。

一开始为了简单,将激活函数定义为一个线性函数,如g(z)=z,后来实际应用中发现,线性激活函数太过于局限,于是引入了非线性激活函数,如sigmoid,tanh,relu等。

1.2激活函数

常见的非激活函数有sigmoid,tanh,relu等等,其中sigmoid和tanhchang常用于全连接层,relu常用于卷积层。

sigmoid函数表达式如下:

attention 学习权重分布 cnn 权重_激活函数_02


sigmoid函数图像如下:

attention 学习权重分布 cnn 权重_神经网络_03

由sigmoid的图像可知,sigmoid函数的作用是将一个实数压缩在0-1之间。当z为很大的正数时,g(z)会趋近于1,当z为很小的负数的时候,g(z)会趋近于0。这样做有一个好处就是可以将激活函数看成是一种分类的概率,即当激活函数为0.5时,便可以解释为50%的概率为正样本。

1.3神经网络

将单个的神经元组织在一起就成为了一个神经网络,如图所示:

attention 学习权重分布 cnn 权重_attention 学习权重分布_04

上图中,最左边的原始输入信息称为输入层,中间的叫隐藏层,最右边的为输出层。

1.4卷积神经网络

卷积网络层级结构:

attention 学习权重分布 cnn 权重_激活函数_05


最左边为数据输入层,对数据进行一些处理,比如去均值,归一化,PCA/白化等。CNN只对训练集做“去均值”这一步。

中间是

CONV:卷积计算层,线性乘积求和

RELU:激励层

POOL:池化层,即取区域平均或最大

最右边是

FC:全连接层

1.5什么是卷积

对图像(不同的数据窗口数据)和滤波矩阵(一组固定的权重:因为每个神经元的多个权重固定,所以又可以看作一个恒定的滤波器filter)做内积(逐个元素相乘再求和)的操作就是所谓的“卷积”操作。

attention 学习权重分布 cnn 权重_自然语言处理_06

2.RNN(Recurrent Neural Networks,循环神经网络)

传统的神经网络不能做到持久性,这是一个巨大的弊端。例如,假设你希望使用电影中的先前的事件推断后续的事件。RNN解决了这个问题,RNN是包含循环的网络,允许信息的持久化。

RNN结构图:

attention 学习权重分布 cnn 权重_神经网络_07

其中,t-1,t,t+1为时间序列,x为输入的样本,St为t时刻样本的记忆,W为输入的权重,U为输入的样本的权重,V为输出的样本的权重。最终的输出为:

attention 学习权重分布 cnn 权重_attention 学习权重分布_08


其中,f,g均为激活函数,其中f可以为sigmoid,tanh和relu等激活函数,g一般为softmax函数也可以是其他函数。

每一次的输出都会存在一个误差值,总的误差值就是所有输出的误差值之和,所以损失函数可以用交叉熵损失函数也可以用平方误差损失函数。

由于每一步不止依靠当前的网络,还依靠之前的网络状态,因此需要将输出的误差值进行反向传递,运用梯度下降法进行更新U,W,V 。但这样存在着一些问题,其中较为严重的是造成梯度消失或者梯度爆炸,其中,梯度消失是指由于时间过长造成记忆值过小的问题。

为了解决这些问题,提出了LSTM和GRU。

3.LSTM(Long Short Term Memory,长时间记忆网络)

attention 学习权重分布 cnn 权重_神经网络_09


LSTM 的核心思想是细胞状态,水平线在图上方贯穿而行。细胞状态类似于传送带,只有少量的线性交互。信息在上面保持不变会很容易。

LSTM有精心设计的门来保护和控制细胞状态。门是一种让信息选择式通过的方法。他们包含一个 sigmoid 神经网络层和一个 pointwise 乘法操作。

Sigmoid 层输出 0 到 1 之间的数值,描述每个部分有多少量可以通过。0 代表“不许任何量通过”,1 就指“允许任意量通过”!

在LSTM第一步是一个“忘记门”,决定从细胞状态中丢弃什么信息。下一步是确定什么样的新的信息存放到细胞状态中,“输入门层“会决定我们更新什么信息。确定了什么信息需要更新后,就会将新的信息存放到细胞状态中,更新旧细胞状态。最终,我们需要确定输出什么值。这个输出将会基于我们的细胞状态,但是也是一个过滤后的版本。首先,我们运行一个 sigmoid 层来确定细胞状态的哪个部分将输出出去。

4.GRU(Gated Recurrent Unit)

GRU是一种LSTM的改进算法,它将忘记门和输入门合并成为一个单一的更新门, 同时合并了数据单元状态和隐藏状态, 使得模型结构比之于LSTM更为简单.

attention 学习权重分布 cnn 权重_权重_10

5.LSTM实例(非原创)

import numpu as np

wordlist = np.load('wordsList.npy')
print('载入word列表')
wordList = wordsList.tolist()
wordList = [word.decode('UTF-8')
		for word in wordList]
wordvectors = np.load('woedVectors.npy')
print('载入文本向量')

print(len(wordList))
#print("wordsList",wordList)
#'mughti','boidin','madueke','smikle','uteritz','gusin',....40万个
print(wordVectors.shape)
#print("wordVectors",wordVector)
#wordVector [[0.         0.          0.         0.      ...0.          0.     0.        ]
#[0.013441   0.23682   -0.16899   ... -0.56657    0.044691   0.30392]
#[0.15164   0.30177   -0.016763   ... -0.35652   0.016413   0.10216]
#...
#[-0.51181   0.058706   1.0913   ... -0.25003   -1.125   1.5863]
#[-0.75898   -0.47426   0.4737   ... 0.78954   -0.014116   0.6448]
#[-0.79149   0.86617   0.11998   ... -0.29996   -0.0063003   0.3954]
#40万*50维的向量

import os 
from os.path import isfile,join

pos_files = ['pos/' + f for f in os.listdir(
	     'pos/') if isfile(join('pos/',f))]
neg_files = ['neg/' + f for f in os.listdir(
	     'neg/') if isfile(join('neg/',f))]
num_words = []
for pf in pos_files:
	with open(pf, "r", encoding='utf-8') as f:
		line = f.readline()
		counter = len(line.split())
		num_words.append(counter)
print('正面评价完结')

for nf in neg_files:
	with open(nf, "r", encoding='utf-8') as f:
		line = f.readline()
		counter = len(line.split())
		num_words.append(counter)
print('负面评价完结')

num_files = len(num_words)
print('文件总数', num_files)
print('所有的词的数量', sum(num_words))
print('平均文件词的长度', sum(num_words) / len(num_words))
print("num_words", num_words)
# num_words [140, 428, 147, 124, 120, 171, 108, 340, 436, 324, 280, 86, 282, 224, 145, 158, ...25000个的列表
# 每个文件的单词长度

# 数据可视化 画直方图  代码未跑通
# import matplotlib.pyplot as plt
# 指定默认字体# plt.figure()
# matplotlib.pyplot.hist(num_words, 50, facecolor='g')
# plt.scatter(num_words, 50,)# plt.xlabel('文本长度')
# plt.ylabel('频次')
# plt.axis([0, 1200, 0, 8000])
# plt.show()

import re
strip_special_chars = re.compile("[^A-Za-z0-9 ]+")
num_dimensions = 300  # Dimensions for each word vector  

def cleanSentences(string):
    string = string.lower().replace("<br />", " ")
    return re.sub(strip_special_chars, "", string.lower())

max_seq_num = 250
# 下面一段代码是将文本生成索引矩阵

"""
# 25000x300索引矩阵
ids = np.zeros((num_files, max_seq_num), dtype='int32')

file_count = 0
for pf in pos_files:
  with open(pf, "r", encoding='utf-8') as f:
      indexCounter = 0
      line = f.readline()    
      cleanedLine = cleanSentences(line)    
      split = cleanedLine.split()    
      for word in split:      
         try:        
           ids[file_count][indexCounter] = wordsList.index(word)
         except ValueError:        
           ids[file_count][indexCounter] = 399999  # 未知的词      
           indexCounter = indexCounter + 1      
           if indexCounter >= max_seq_num:        
              break    
       file_count = file_count + 1

for nf in neg_files:
  with open(nf, "r", encoding='utf-8') as f:
      indexCounter = 0    
      line = f.readline()    
      cleanedLine = cleanSentences(line)    
      split = cleanedLine.split()    
      for word in split:   
         try:     
            ids[file_count][indexCounter] = wordsList.index(word)      
         except ValueError:      
           ids[file_count][indexCounter] = 399999  # 未知的词语      
           indexCounter = indexCounter + 1    
           if indexCounter >= max_seq_num:      
              break  
      file_count = file_count + 1np.save('idsMatrix', ids)
"""  

from random import randint 

batch_size = 24
lstm_units = 64
num_labels = 2
iterations = 100
lr = 0.001
ids = np.load('idsMatrix.npy')  

def get_train_batch():
    labels = []    
    # 25000x300    
    # batch x300  每次取批次数据 batch_size =24    
    # 随机取24个  训练集    
    arr = np.zeros([batch_size, max_seq_num])    
    for i in range(batch_size):     
       if (i % 2 == 0):          
         num = randint(1, 11499)            
         # pos            
         labels.append([1, 0])        
       else:          
         num = randint(13499, 24999)            
         # neg            
         labels.append([0, 1])        
       arr[i] = ids[num - 1:num]    
   return arr, labels  

def get_test_batch():   
  labels = []    
  arr = np.zeros([batch_size, max_seq_num])    
  for i in range(batch_size):      
    # 13499 -11499 = 2000 做测试集  这里可以看出在训练的过程中 分好测试集和训练集的        
    num = randint(11499, 13499)        
    if (num <= 12499):          
      labels.append([1, 0])        
    else:          
      labels.append([0, 1])      
    arr[i] = ids[num - 1:num]    
  return arr, labels  
import tensorflow as tf 

tf.reset_default_graph() 

labels = tf.placeholder(tf.float32, [batch_size, num_labels])
input_data = tf.placeholder(tf.int32, [batch_size, max_seq_num])
# labels = tf.get_variable(tf.float32, [batch_size, num_labels])
# input_data = tf.placeholder(tf.int32, [batch_size, max_seq_num])
data = tf.Variable(    
	tf.zeros([batch_size, max_seq_num, num_dimensions]),dtype=tf.float32)
# data = tf.get_variable(
#    tf.zeros([batch_size, max_seq_num, num_dimensions]), dtype=tf.float32)
data = tf.nn.embedding_lookup(wordVectors, input_data) 

lstmCell = tf.contrib.rnn.BasicLSTMCell(lstm_units)
lstmCell = tf.contrib.rnn.DropoutWrapper(cell=lstmCell, output_keep_prob=0.5)
value, _ = tf.nn.dynamic_rnn(lstmCell, data, dtype=tf.float32) 

weight = tf.Variable(tf.truncated_normal([lstm_units, num_labels]))
bias = tf.Variable(tf.constant(0.1, shape=[num_labels])) 

value = tf.transpose(value, [1, 0, 2])
last = tf.gather(value, int(value.get_shape()[0]) - 1)
prediction = (tf.matmul(last, weight) + bias) 

correct_pred = tf.equal(tf.argmax(prediction, 1), tf.argmax(labels, 1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32)) 

loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(    	 
      logits=prediction, labels=labels))
optimizer = tf.train.AdamOptimizer(lr).minimize(loss)

# saver = tf.train.Saver()
saver = tf.train.Saver(save_relative_paths=True) 

with tf.Session() as sess:
    if os.path.exists("models") and os.path.exists("models\\checkpoint"):        
       saver.restore(sess, tf.train.latest_checkpoint('models'))    
   else:     
      if int((tf.__version__).split('.')[1]) < 12 and int((tf.__version__).split('.')[0]) < 1:
          init = tf.initialize_all_variables()        
      else:         
          init = tf.global_variables_initializer()        
      sess.run(init)   
   iterations = 100    
   for step in range(iterations):     
      next_batch, next_batch_labels = get_test_batch()        
      if step % 20 == 0:         
         print("step:", step, " 正确率:", (sess.run(                
         accuracy, {input_data: next_batch, 
         labels:next_batch_labels})) * 100)     
   if not os.path.exists("models"):      
     os.mkdir("models")    
   save_path = saver.save(sess, "models\\model.ckpt")    
   print("Model saved in path: %s" % save_path)