判断图片上是否有猫

搭建算法架构需要引入以下包
1.numpy 科学计算库
2.h5py 遍历存在于H5文件里的数据集
3.matplotlib python画图工具库
4.PIL和scipy 用自己的图片测试模型

数据data.h5中包括
1.训练集,标明了y=1(cat)和y=0(non cat)
2.测试集,标记了cat或者non-cat
3.每张图片shape为(num_px,num_px,3)

加载数据

Loading the data (cat/non-cat)

train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()

查看数据集合信息
m_train = train_set_x_orig.shape[0]

m_test = test_set_x_orig.shape[0]

num_px = train_set_x_orig.shape[1]

将图片的shape((m_train, num_px, num_px, 3)转换成为shape(num_pxnum_px3,m_train)的形式
train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0], -1).T

test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0], -1).T

标准化数据集
train_set_x = train_set_x_flatten/255.

test_set_x = test_set_x_flatten/255.

以上步骤为准备阶段,准备数据集:
1.弄清楚数据集的dimension和shape
2.将每个向量reshape成为(num_pxnum_px3,1)的形式
3.标准化输入(0-1之间)

以下主要步骤搭建算法框架
1.初始化模型参数
2.通过最小化损失函数训练参数
3.使用训练得到的参数做测试集预测
4.分析结果

搭建算法架构
1.搭建sigmoid函数
def sigmoid(z):

s = 1/(1+np.exp(-z))

2.初始化参数
def initialize_with_zeros(dim):

w = np.zeros((dim, 1))

b = 0
3.计算损失函数和梯度
def propagate(w, b, X, Y):

A = sigmoid(np.dot(w.T,X)+b) # compute activation
cost = (-1/m)np.sum(Ynp.log(A)+(1-Y)*np.log(1-A)) # compute cost

BACKWARD PROPAGATION (TO FIND GRAD)

dw = (1/m)*np.dot(X,(A-Y).T)
db = (1/m)*np.sum(A-Y)
4.使用梯度下降方法更新w和b
def optimize(w, b, X, Y, num_iterations, learning_rate, print_cost = False):

w = w - learning_rate*dw

b = b - learning_rate*db
5.根据X以及学习得到的w和b预测
def predict(w, b, X):
A = sigmoid(np.dot(w.T,X)+b)
6.把以上五个方法整合到一个model里面
def model(X_train, Y_train, X_test, Y_test, num_iterations = 2000, learning_rate = 0.2, print_cost = False):

ps:过拟合现象指的是增加学习次数,在训练集上的准确率提高,但在整个数据集的准确率下降
设置学习步长过大或者过小都不合适

python代码附上:

import numpy as np   # 加载numpy工具库,并给它取了个别名为np,后面就可以通过np来调用numpy工具库里面的函数了。
import matplotlib.pyplot as plt   # 这个库是用来画图的
import h5py         # 这个库是用来加载训练数据集的。我们数据集的保存格式是HDF。
import skimage.transform as tf      # 这里是我们用来缩放图片
import pylab  # 图片显示库


def load_dataset():
    train_dataset = h5py.File('datasets/train_catvnoncat.h5', "r")          # 加载训练数据
    train_set_x_orig = np.array(train_dataset["train_set_x"][:])            # 从训练数据中提取出图片的特征数据
    train_set_y_orig = np.array(train_dataset["train_set_y"][:])            # 从训练数据中提取出图片的标签数据

    test_dataset = h5py.File('datasets/test_catvnoncat.h5', "r")             # 加载测试数据
    test_set_x_orig = np.array(test_dataset["test_set_x"][:])
    test_set_y_orig = np.array(test_dataset["test_set_y"][:])

    classes = np.array(test_dataset["list_classes"][:])                     # 加载标签类别数据,这里的类别只有两种,1代表有猫,0代表无猫

    train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0]))  # 把数组的维度从(209,)变成(1,209),这样方便后面进行计算
    test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0]))     # 从(50,)变成(1,50)   .shape[0]代表矩阵的行数,.shape[1]代表矩阵的列数

    return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes

# 调用上面定义的函数将数据加载到各个变量中
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()

index = 5
plt.imshow(train_set_x_orig[index])     # 显示图片
pylab.show()
print("标签为" + str(train_set_y[:, index]) + ",这是一个'" + classes[np.squeeze(train_set_y[:, index])].decode("utf-8") + "'图片.")

# 打印变量的维度,方便程序的书写,各个维度的含义(样本数,图片宽,图片长,3个RGB通道)
print("train_set_x_orig shape:" + str(train_set_x_orig.shape))
print("train_set_y shape:" + str(train_set_y.shape))
print("test_set_x_orig shape:" + str(test_set_x_orig.shape))
print("test_set_y shape:" + str(test_set_y.shape))

# 提取样本数和长宽像素数
m_train = train_set_x_orig.shape[0]
m_test = test_set_x_orig.shape[0]
num_px = test_set_x_orig.shape[1]   # 由于我们的图片是正方形的,所以长宽相等

print("训练样本数:m_train = " + str(m_train))
print("测试样本数:m_test = " + str(m_test))
print("每张图片的宽/高:num_px = " + str(num_px))

# 为了方便后面进行矩阵运算,我们需要将样本数数据进行扁平化和转置
# 处理后的数组各维度的含义是(图片数据,样本数)

train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0], -1).T
test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0], -1).T

print("train_set_x_flatten shape:" + str(train_set_x_flatten.shape))
print("test_set_x_flatten shape:" + str(test_set_x_flatten.shape))

# 下面我们对特征数据进行了简单的标准化处理(除以255,使所有值都在[0,1]范围内)
# 为什么要对数据进行标准化处理呢?简单来说就是为了方便后面进行计算,详情以后再给解释
train_set_x = train_set_x_flatten/255.
test_set_x = test_set_x_flatten/255.

# 以上已经加载了数据,并对数据进行了预处理,使其便于进行后面的运算。后面我们将会构建一个神经网络模型对上面的数据进行运算

# 激活函数sigmoid,作用是把预测结果转换为0到1之间的值
def sigmoid(z):
    """
    :param z: 一个数值或者一个numpy数组
    :return: 经过sigmoid算法计算后的值,在[0,1]范围内
    """
    s = 1 / (1 + np.exp(-z))
    return s

# 该函数用于初始化权重数组w和阈值b
def initialize_with_zeros(dim):
    """
    :param dim: w的大小,由神经网络模型图可知,dim在本例中为12288(64*64*3),一个特征对应一个权重
    :return: w --- 权重数组; b --- 偏置/阈值bias
    """
    w = np.zeros((dim,1))
    b = 0
    return w,b

# 下面函数用于执行前向传播,计算出成本cost; 以及执行后向传播,计算出w和b的偏导数/梯度(后续用来进行梯度下降)
def propagate(w, b, X, Y):
    """
    :param w: 权重数组,维度是(12288,1)
    :param b: 偏置bias
    :param X: 图片的特征数据,维度是(12288,209)
    :param Y: 图片对应的标签,0或1,0是无猫,1是有猫,维度是(1,209)
    :return: cost --- 成本; dw --- w的梯度; db --- b的梯度
    """
    m = X.shape[1]

    # 前向传播
    A = sigmoid(np.dot(w.T, X) + b)
    cost = -np.sum(Y * np.log(A) + (1-Y) * np.log(1-A)) / m
    # 反向传播
    dZ = A -Y
    dw = np.dot(X, dZ.T) / m
    db = np.sum(dZ) / m
    # 将dw和db保存到字典里面
    grads = {"dw":dw,
             "db":db}
    return grads, cost

# 通过梯度下降算法来更新参数w和b,达到越来越优化的目的
def optimize(w, b, X, Y, num_iterations, learning_rate, print_cost = False):
    """
    :param w: 权重数组,维度是(12288,1)
    :param b: 偏置bias
    :param X: 图片的特征数据,维度是(12288,209)
    :param Y: 图片对应的标签,0或1,0是无猫,1是有猫,维度是(1,209)
    :param num_iterations: 指定要优化多少次
    :param learning_rate: 学习步讲,是我们用来控制优化步进的参数
    :param print_cost: 为True时,每优化100次就把成本cost打印出来,以便我们观察成本变化
    :return: params --- 优化后的w和b; costs --- 每优化100次,将成本记录下来,成本越小,表示参数越优化
    """
    costs = []
    for i in range (num_iterations):
         grads, cost = propagate(w, b, X, Y)   # 计算得出梯度和成本
        # 从字典中取出梯度
         dw = grads["dw"]
         db = grads["db"]
        # 进行梯度下降,更新参数,使其越来越优化,使成本越来越小
         w = w - learning_rate * dw
         b = b - learning_rate * db

        # 将成本记录下来
         if i % 100 == 0:
             costs.append(cost)
             if print_cost:
                 print ("优化%i次后成本是:%f" %(i, cost))

    params = {"w": w,
               "b":b}
    return params, costs

# 上面的函数得出优化后的参数w和b。
# 下面函数进行预测
def predict(w, b, X):
    """
    :param w: 权重数组,维度是(12288,1)
    :param b: 偏置bias
    :param X: 图片的特征数据,维度是(12288, 图片张数)
    :return:  对每张图片的预测结果
    """
    m = X.shape[1]
    Y_prediction = np.zeros((1,m))

    A = sigmoid(np.dot(w.T, X) + b)  # 通过这行代码来对图片进行预测

    # 上面得出的预测结果是小数形式,为了方便后面显示,我们再将其转换成0或1的形式(大于等于0.5就是1(有猫),小于0.5就是0(无猫))
    for i in range(A.shape[1]):
        if A[0,i] >= 0.5:
            Y_prediction[0,i] = 1

    return Y_prediction

# 到此,所需的工具函数都已经编写完
# 构建神经网络模型的函数
def model(X_train, Y_train, X_test, Y_test, num_iterations = 2000, learning_rate = 0.5, print_cost = False):
    """
    :param X_train:  训练图片,维度是(12288,2090)
    :param Y_train:  训练图片对应的标签,维度是(1, 209)
    :param X_test:  测试图片,维度是(12288,50)
    :param Y_test:  测试图片对应的标签,维度是(1,50)
    :param num_iterations:  需要训练/优化次数
    :param learning_rate:  学习步进,是我们用来控制优化步进的参数
    :param print_cost:  为True时,每优化100次就把成本cost打印出来,以便我们观察成本的变化
    :return:  返回一些信息
    """
    # 初始化待训练的参数
    w, b = initialize_with_zeros(X_train.shape[0])
    # 使用训练数据来训练/优化参数
    parameters, costs = optimize(w, b, X_train, Y_train, num_iterations, learning_rate, print_cost)

    # 从字典中分别取出训练好的w和b
    w = parameters["w"]
    b = parameters["b"]

    # 使用训练好的w和b来分别对训练图片和测试图片进行预测
    Y_prediction_train = predict(w, b, X_train)
    Y_prediction_test = predict(w, b, X_test)
    # 打印出预测的准确率
    print ("对训练图片的预测准确率为:{}%" .format(100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100))
    print ("对测试图片的预测准确率为:{}%" .format(100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100))

    d = {"costs":costs,
      "Y_prediction_test": Y_prediction_test,
      "Y_prediction_train": Y_prediction_train,
      "w":w,
      "b":b,
      "learning_rate":learning_rate,
      "num_iterations":num_iterations}
    return d
# 调用上面的模型函数对我们最开始加载的数据进行训练
d = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 2000, learning_rate = 0.005, print_cost = True )

# 这里我们可以改变index,来看看哪些图片预测对了
index = 8
plt.imshow(test_set_x[:,index].reshape((num_px, num_px, 3)))
pylab.show()
print ("这张图的标签是" + str(test_set_y[0, index]) + ",预测结果是" + str(int(d["Y_prediction_test"][0, index])))


# 下面我们打印出成本随着训练次数增加时的变化情况,可以很直观地看出,训练次数越多,成本越小,也就是预测越准确
costs = np.squeeze(d['costs'])
plt.plot(costs)
plt.ylabel('cost')  # 成本
plt.xlabel('iterations(per hundreds)')  # 横坐标为训练次数,以100为单位
plt.title("Learning rate =" + str(d["learning_rate"]))
plt.show()
pylab.show()

# 至此,选择一个正确的学习率很重要。选错了,那么你的神经网络可能会永远找不到损失函数的最小值处,即神经网络预测永远不会很准。
# 下面,我们使用了3个不同的学习率来给大家直观地展示它们对训练过程的影响。

learning_rates = [0.01, 0.001, 0.0001]
models = {}
for i in learning_rates:
    print ("学习率为:" + str(i) + "时")
    models[str(i)] = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 1500, learning_rate = i, print_cost = False)
    print('\n' + "----------------------" + '\n')

for i in learning_rates:
    plt.plot(np.squeeze(models[str(i)]["costs"]), label=str(models[str(i)]["learning_rate"]))
plt.ylabel('cost')
plt.xlabel('iterations (hundreds)')

legend = plt.legend(loc='upper center', shadow=True)
frame = legend.get_frame()
frame.set_facecolor('0.90')
plt.show()
pylab.show()

# 在本文档的同目录下创建一个文件夹images,把你的任意图片改名为my_image1.jpg后放入文件夹
my_image = "my_image1.jpg"
fname = "images/" + my_image

image = np.array(plt.imread(fname))
my_image = tf.resize(image,(num_px,num_px),mode = 'reflect').reshape((1, num_px * num_px * 3)).T
my_predicted_image = predict(d["w"], d["b"], my_image)

plt.imshow(image)
pylab.show()
print ("预测结果为 " + str(int(np.squeeze(my_predicted_image))))

你可能感兴趣的:(神经网络)