TF girls系列(1)搭建二层全连接神经网络

35 篇文章 1 订阅
10 篇文章 0 订阅

搭建的是如下图所示的二层神经网络。
在这里插入图片描述

输入层的神经元个数由图片的维度决定,教程中使用的是32x32x3的彩色图片,然后灰度化,得到32x32的灰度图,故输入层神经元个数是1024个,隐藏层神经元个数可以自己指定,教程中指定为128个,由于是数字识别任务,故有10个数字,故输出层神经元个数为10。

为了考虑内存的限制,本教程分批量训练图片,每次100张,故每一次训练,输入层矩阵为100x1024,经过第一个全连接层(第一个全连接层的权重矩阵W1为1024x128),得到隐藏层矩阵为100x128,再经过第二个全连接层(第二个全连接层的权重矩阵W2为128x10),得到输出层矩阵为logits为100x10。

# -*- coding: utf-8 -*-
"""
Created on Wed Mar 27 19:38:44 2019

@author: macheng
"""

from __future__ import print_function, division
import tensorflow as tf
from sklearn.metrics import confusion_matrix
import numpy as np
import load

#train_samples 是维度为[num_images, image_size, image_size, num_channels]大小的4维矩阵
#train_labels 是维度为[num_images, 10]大小的2维矩阵
train_samples, train_labels = load._train_samples, load._train_labels
test_samples, test_labels = load._test_samples,  load._test_labels

print('Training set', train_samples.shape, train_labels.shape)
print('    Test set', test_samples.shape, test_labels.shape)

image_size = load.image_size       #32
num_labels = load.num_labels       #10
num_channels = load.num_channels   #channel为1,灰度图

def get_chunk(samples, labels, chunkSize):
    
	'''
	Iterator/Generator: get a batch of data
	这个函数是一个迭代器/生成器,用于每一次只得到 chunkSize 这么多的数据
	用于 for loop, just like range() function
	'''
	if len(samples) != len(labels):
		raise Exception('Length of samples and labels must equal')
	stepStart = 0	# initial step
	i = 0
	while stepStart < len(samples):
		stepEnd = stepStart + chunkSize
		if stepEnd < len(samples):
			yield i, samples[stepStart:stepEnd], labels[stepStart:stepEnd]
			i += 1
		stepStart = stepEnd


class Network():
	def __init__(self, num_hidden, batch_size):
		'''
		@num_hidden: 隐藏层的节点数量
		@batch_size:因为我们要节省内存,所以分批处理数据。每一批的数据量。
		'''
		self.batch_size = batch_size
		self.test_batch_size = 500

		# Hyper Parameters
		self.num_hidden = num_hidden

		# Graph Related
		self.graph = tf.Graph()
		self.tf_train_samples = None
		self.tf_train_labels = None
		self.tf_test_samples = None
		self.tf_test_labels = None
		self.tf_test_prediction = None

	def define_graph(self):
		'''
		定义我的计算图谱
		'''
		with self.graph.as_default():
			# 这里只是定义图谱中的各种变量
			self.tf_train_samples = tf.placeholder(
				tf.float32, shape=(self.batch_size, image_size, image_size, num_channels)
			)
			self.tf_train_labels  = tf.placeholder(
				tf.float32, shape=(self.batch_size, num_labels)
			)
			self.tf_test_samples  = tf.placeholder(
				tf.float32, shape=(self.test_batch_size, image_size, image_size, num_channels)
			)


			""""
			fully connected layer 1:   input layer ---> hidden layer

			fc1_weights是维度为[image_size*imagez_size, num_hidden]大小的二维数组,代表的是输入层到隐藏层的连接上的权重,
			行表示输入层神经元的个数,也就是输入层有image_size*imagez_size大小个神经元(32*32=1024)
			列表示隐藏层神经元的个数,也就是隐藏层有num_hidden大小个神经元(128)
			"""
			fc1_weights = tf.Variable(
				tf.truncated_normal([image_size * image_size, self.num_hidden], stddev=0.1)
			)
			fc1_biases = tf.Variable(tf.constant(0.1, shape=[self.num_hidden]))
			print("fc1_weights.shape: ", fc1_weights.shape)
			print("fc1_biases.shape: ", fc1_biases.shape)

			"""
			fully connected layer 2:  hidden layer --> output layer
			
			fc2_weights的维度为[num_hidden, num_labels]大小的二维数组,代表的是隐藏层到输出层的连接上的权重
			行表示隐藏层神经元的个数(128),列表示输出层神经元的个数(10)
			"""
			fc2_weights = tf.Variable(
				tf.truncated_normal([self.num_hidden, num_labels], stddev=0.1)
			)
			fc2_biases = tf.Variable(tf.constant(0.1, shape=[num_labels]))
			print("fc2_weights.shape: ", fc2_weights.shape)
			print("fc2_biases.shape: ", fc2_biases.shape)
			print("\n")

			# 现在来定义图谱的运算
			def model(data):
				# fully connected layer 1
				shape = data.get_shape().as_list()  #将data的shape变为一个list
				print(data.get_shape(), shape)
				# reshape为batch_size * (image_size*image_size*num_channels)大小的二维数组(100*1024)
				reshape = tf.reshape(data, [shape[0], shape[1] * shape[2] * shape[3]])
				print(reshape.get_shape(), fc1_weights.get_shape(), fc1_biases.get_shape())
				# hidden的维度是batch_size * num_hidden大小的二维数组(100*128)
				hidden = tf.nn.relu(tf.matmul(reshape, fc1_weights) + fc1_biases)
				print(hidden.get_shape())

				# fully connected layer 2
				#最后的得到的是100*10的二维矩阵
				return tf.matmul(hidden, fc2_weights) + fc2_biases

			# Training computation.
			logits = model(self.tf_train_samples)
			self.loss = tf.reduce_mean(
				tf.nn.softmax_cross_entropy_with_logits(labels=self.tf_train_labels, logits=logits)
			)

			# Optimizer.
			self.optimizer = tf.train.GradientDescentOptimizer(0.0001).minimize(self.loss)

			# Predictions for the training, validation, and test data.
			self.train_prediction = tf.nn.softmax(logits)
			self.test_prediction = tf.nn.softmax(model(self.tf_test_samples))

	def run(self):
		'''
		用到Session
		'''
		# private function
		def print_confusion_matrix(confusionMatrix):
			print('Confusion    Matrix:')
			for i, line in enumerate(confusionMatrix):
				print(line, line[i]/np.sum(line))
			a = 0
			for i, column in enumerate(np.transpose(confusionMatrix, (1, 0))):
				a += (column[i]/np.sum(column))*(np.sum(column)/26000)
				print(column[i]/np.sum(column),)
			print('\n',np.sum(confusionMatrix), a)


		self.session = tf.Session(graph=self.graph)
		with self.session as session:
			tf.initialize_all_variables().run()

			### 训练
			print('Start Training')
			# batch 100
			for i, samples, labels in get_chunk(train_samples, train_labels, chunkSize=self.batch_size):
				_, l, predictions = session.run(
					[self.optimizer, self.loss, self.train_prediction],
					feed_dict={self.tf_train_samples: samples, self.tf_train_labels: labels}
				)
				# labels is True Labels
				accuracy, _ = self.accuracy(predictions, labels)
				if i % 50 == 0:
					print('Minibatch loss at step %d: %f' % (i, l))
					print('Minibatch accuracy: %.1f%%' % accuracy)
			###

			### 测试
			accuracies = []
			confusionMatrices = []
			for i, samples, labels in get_chunk(test_samples, test_labels, chunkSize=self.test_batch_size):
				result = self.test_prediction.eval(feed_dict={self.tf_test_samples: samples})
				accuracy, cm = self.accuracy(result, labels, need_confusion_matrix=True)
				accuracies.append(accuracy)
				confusionMatrices.append(cm)
				print('Test Accuracy: %.1f%%' % accuracy)
			print(' Average  Accuracy:', np.average(accuracies))
			print('Standard Deviation:', np.std(accuracies))
			print_confusion_matrix(np.add.reduce(confusionMatrices))
			###

	def accuracy(self, predictions, labels, need_confusion_matrix=False):
		'''
		计算预测的正确率与召回率
		@return: accuracy and confusionMatrix as a tuple
		'''
		_predictions = np.argmax(predictions, 1)
		_labels = np.argmax(labels, 1)
		cm = confusion_matrix(_labels, _predictions) if need_confusion_matrix else None
		# == is overloaded for numpy array
		accuracy = (100.0 * np.sum(_predictions == _labels) / predictions.shape[0])
		return accuracy, cm


if __name__ == '__main__':
	net = Network(num_hidden=128, batch_size=100)
	net.define_graph()
	net.run()

搭建的二层神经网络的正确率只有12.9%,后面会慢慢对这个网络进行改进以提高正确率
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值