获取数据
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets(r'D:\PycharmProjects\HandWritingRecognition\TF\data',
one_hot=True) # 读取数据(如果是初次运行则需要下载)
# 数据分为3部分:train, test, validation
print(mnist.train.images.shape) # 输入X的维度55000 x 784, 表示5w多训练样本,28*28的像素得到784个灰度,没有考虑结构关系
print(mnist.train.labels.shape) # 输出维度为55000 x10, 识别结果是0-9,维度为10;one-hot编码:向量的识别数字对应位子为1其他为0
print(mnist.validation.images.shape) # 5000 x 784
print(mnist.test.images.shape) # 10000 x 784
softmax模型
212.PNG在上介绍后直接简化为下面(不支持latex,只能截图):
捕获.PNGSGD训练模型
过程中需要定义损失函数:交叉熵
# SGD
sess = tf.InteractiveSession() # 创建一个默认的交互session,不同的session里面的运算是独立的
X = tf.placeholder(dtype=tf.float32, shape=[None, 784]) # feed数据占位,None直接取决于minibatch的数量,用None代替
W = tf.Variable(initial_value=tf.zeros(shape=[10, 784]), name='W', dtype=tf.float32) # 初始化权重变量
b = tf.Variable(initial_value=tf.zeros(shape=[10]), name='b', dtype=tf.float32)
y = tf.nn.softmax(tf.matmul(X, W, transpose_b=True) + b) # 预测值
y_ = tf.placeholder(dtype=tf.float32, shape=[None, 10]) # 真实值
loss = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1])) # reducemean:对每个batch数据训练结果取平均
train = tf.train.GradientDescentOptimizer(learning_rate=0.5).minimize(loss) # 采用随机梯度下降法
tf.global_variables_initializer().run() # 所有参数初始化并,直接调用run方法, 前面采用的InteractiveSession,所以不需要sess.run
for i in range(1000):
# iteration:1000
batch_x, batch_y = mnist.train.next_batch(100) # size of batch:100
train.run({X: batch_x, y_: batch_y})
# 计算模型的准确率
predres = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1)) # 找到两者的最大数值的位置,判断是否一致,返回bool型
accuracy = tf.reduce_mean(tf.cast(predres, tf.float32)) # cast转化数据的类型
print(accuracy.eval({X: mnist.test.images, y_: mnist.test.labels}))
准确率:0.9183
reduce_sum:reduction_indices=[1]理解为pandas的按行求和,minibatch数据求交叉熵得到100 x 10 的矩阵结果。
自动编码
212.PNGdef xavier_init(in_num, out_num, const=1):
"""
:param in_num:
:param out_num:
"""
value = const * np.sqrt(6 / (in_num + out_num))
return tf.random_uniform(shape=(in_num, out_num), minval=-value, maxval=value,
dtype=tf.float32)
-
类初始化定义:
一个隐藏层, n_input 输入信号个数784, n_hidden隐藏层节点数量, transfer信号函数, optimizer最优求解方法,scale利用高斯函数加入信号噪声的参数。
class AdditiveGaussianNoiseAutoEncoder(object):
def __init__(self, n_input, n_hidden, transfer=tf.nn.softplus,
optimizer=tf.train.AdamOptimizer(learning_rate=0.1), scale=0.01):
self.n_input = n_input # 输入节点数
self.n_hidden = n_hidden # 下一隐藏层层网络的节点数(仅仅考虑一个隐藏层)
self.transfer = transfer # 激活函数
self.training_scale = scale # 高斯噪声系数
self.x = tf.placeholder(dtype=tf.float32, shape=[None, n_input])
self.weight = self.__init_weight()
# 计算隐藏层的输出信息号
self.hidden = self.transfer(
tf.add(
# 给输入信号加入高斯分布的噪声
tf.matmul(self.x + scale * tf.random_normal(shape=[n_input, ]),
self.weight['w1']), self.weight['b1']
)
)
# 给将隐藏层的输出信号hadden复原
self.reconstruction = tf.add(tf.matmul(self.hidden, self.weight['w2']),
self.weight['b2']
)
# 计算复原信号与原来信号的差距:平方误差
self.cost = 0.5 * tf.reduce_sum(tf.pow(tf.subtract(self.reconstruction, self.x), 2.0))
self.optimizer = optimizer.minimize(self.cost) # 优化损失函数
init = tf.global_variables_initializer()
self.sess = tf.Session()
self.sess.run(init)
-
权重初始化方法
self.weight = self.__init_weight(), 类的初始化中我们用的代码,权重有两组一组,w1 b1与前面所讲到的softmax模型的矩阵运算一致,得到初始化权重和偏执的转置,但是w1调用了xavier函数。w2、b2则是用来对前面的过程的逆向操作(不是求矩阵的逆,仅仅代表流程:信息 -> hidden输出 -> +噪声 -> 还原成初始信号,类似于后面多了个隐藏层节点个数等于输入节点个数),得到在hidden的输出并加入高斯噪声,然后还原信号过程,次过程结果为reconstruction。cost是用二次损失函数来衡量还原后的信号和原始信号的误差程度。
def __init_weight(self):
weights = {}
weights['w1'] = tf.Variable(xavier_init(self.n_input, self.n_hidden))
weights['b1'] = tf.Variable(tf.zeros(shape=[self.n_hidden], dtype=tf.float32))
weights['w2'] = tf.Variable(tf.zeros(shape=[self.n_hidden, self.n_input], dtype=tf.float32))
weights['b2'] = tf.Variable(tf.zeros(shape=[self.n_input], dtype=tf.float32))
return weights
-
定义图节点调用函数
前面在init中定义了所需要的一切,但是这仅仅都是图的节点,并不会执行,只有你在调用时候,才会执行,那么这个函数就是调用函数。(如果对图和节点困惑,就参考tensorflow的官网定义)
def patial_fit(self, X):
# X :batch数据
# 执行损失cost和优化器的节点
cost, opt = self.sess.run((self.cost, self.optimizer), feed_dict={self.x: X})
return cost
-
定义单独调用损失函数节点的函数
这里主要为了用在测试数据上计算,信号还原的泛化能力
def calc_total_cost(self, X):
# 仅仅执行cost节点:自动编码完成后,用于训练数据评价模型
return self.sess.run(self.cost, feed_dict={self.x: X})
- 信号归一化处理调用sklearn模块函数和随机生成batch训练数据
def standard(X_train, X_test):
prep = preprocessing.StandardScaler().fit(X_train)
X_train = prep.transform(X_train)
X_test = prep.transform(X_test)
return X_test, X_train
def get_block(data, batch_size):
start_index = np.random.randint(0, len(data) - batch_size)
return data[start_index:(start_index + batch_size)]
- 结果
自动编码代码
Epoch: 0001 cost= 418982712119.877807617
Epoch: 0011 cost= 17215478609.007709503
Epoch: 0021 cost= 23005525169.679157257
Epoch: 0031 cost= 3799043043.911016464
Epoch: 0041 cost= 37020387.181381851
Epoch: 0051 cost= 390609961.420690894
Epoch: 0061 cost= 68717674183.661369324
Epoch: 0071 cost= 4283807699.044072151
Epoch: 0081 cost= 428911581.832145751
Epoch: 0091 cost= 10010243.328763649
Total cost: 1.11217e+14
多层感知机
- dropout 是一种bagging技术。
- 神经网络是一个非凸优化的问题,SGD经常会陷入局部最优解,局部最优解一般能得到比较好的分类效果,并且有时全局最优解的泛华能力并不好。
- 对于不同的学习速率结果有很大的变化,
- Adam:a method for stockastic optimization
- Adadelta: an adaptive learning rate method
- ReLU:解决梯度弥散(gradient vanishment)
$$max(0, x)$$
a. 单侧抑制
b. 相对宽阔的兴奋区间
c. 洗漱性的激活函数 - 优化器的介绍
- tensorflow 实现
前面已经接触过softmax来拟合输出,现在仅仅需要在前面的基础上加入中间一个隐藏层如下,矩阵的计算方式不变,随着?的加入。那么权重的初始也会发生变化。这里需要两个初始化权重矩阵。矩阵的维度units_next x units。
捕获.PNG
隐藏层使用ReLU线性整流,损失采用交叉熵。对测试数据的准确率提升到约为98%。
感知机代码
网友评论