神经网络与深度学习练习


神经网络与深度学习作业

大垃圾一年没写python辣(其实去年也学的稀烂),今年要机器学习不得不捡起py开始学

为了逐步把自己的算法水平移植到py上,于是决定开始Py恢复训练(其实就是重新学)

然后这个笔记主要是存放西安科技大学的神经网络与深度学习的作业代码

然后也会放一些自己在kaggle或者其他网站数据分析的练习

练习1:

( 20分 )

作业题1

要求用户输入一个1-100之间的整数。在屏幕上输出1-1000中所有可以被这个输入数字整除的整数,并把它们写入文本文件中。

1.基本要求:

(1) 接收用户输入,并判断是否为1-100之间的整数。如果输入符合要求,则继续执行第(2)步,否则结束程序。

(2) 根据用户输入,在屏幕上输出1-1000中,所有可以被这个数字整除的数字,并打印序号。序号从1开始,依次加1.

例如,用户输入20,的情况:

请输入一个1-100之间的整数:20

1 20

2 40

3 60

4 80

5 100

……

46 920

47 940

48 960

49 980

50 1000

(3)将第(2)步的输出结果,写入C盘根目录下的文本文件中,文件名为“x的倍数.txt”,例如,输入20,则文件名为:“20的倍数.txt”。

(4) 添加必要的注释,说明程序设计思路。

2.提高要求:

(1) 如果输入不符合要求,则要求用户重新输入,并给出提示信息。具体要求参见第4讲单元作业1。

(2) 将基本要求中的(1)和(2),通过函数实现。

(3) 在程序中需要的地方,捕捉异常,或使用with语句管理资源。

说明:提交一份程序代码即可。根据实现功能综合得分。

满足基本要求最高14分,满足提高要求最高20分。

代码:

print("请输入1-100之间的整数")
while True:
    str=input()
    if not str.isdigit():
        print("输入有误,不是整数,请继续")
        continue
    elif int(str)>100:
        print("输入有误,不在范围内,请继续")
        continue
    elif int(str)<1:
        print("输入有误,不在范围内,请继续")
        continue
    else:
        print("输入正确,继续程序")
        with open("记录用文件.txt","w") as f:
            count=1;
            for i in range(1,10001):
                if i%int(str)==0:
                    f.write('%d: %s \n'%(count,i))
                    count+=1

        with open("记录用文件.txt","r") as f:
            content=f.readlines()
            for i in content:
                print(i)

练习2:

( 10分 )

生成一个[0,1)之间均匀分布的随机数数组,包含1000个元素, 随机种子为612。接收用户输入一个1-100之间的数字。打印随机数组中所有索引值可以被输入整数整除的数字,并打印序号和索引值。序号从1开始,依次加1. 例如,用户输入50,则打印数组中索引值为0,50,100…1000的随机数。

程序运行示例:

请输入一个1-100之间的整数:50

序号 索引值 随机数

1 50 0.685693777029538

2 100 0.8447931162144151

3 150 0.7043694996423318

……

19 950 0.5979676151428348

20 1000 0.5714978209525051

提示:输出时可以使用制表符”\t”,对齐各列。

代码:

import numpy as np
num=int(input("请输入一个整数,我将会打印打印随机数组中所有索引值可以被输入整数整除的数字:"))
np.random.seed(612)
a=np.random.rand(1000)
count=0
for i in range(1,1002):
    if i%num ==0:
        count += 1
        print("%d\t%d\t%f\n"%(count,i,a[i]))

练习3:

已知:

x=[ 64.3,99.6,145.45,63.75,135.46,92.85,86.97,144.76,59.3,116.03]

y=[ 62.55,82.42,132.62,73.31,131.05,86.57,85.49,127.44,55.25,104.84]

利用最小二乘法求x与y的回归曲线,代码如下:

import numpy as np
x1=[ 64.3,99.6,145.45,63.75,135.46,92.85,86.97,144.76,59.3,116.03]
y1=[ 62.55,82.42,132.62,73.31,131.05,86.57,85.49,127.44,55.25,104.84]
x=np.array(x1)
y=np.array(y1)
_x=np.sum(x,axis=0)/np.size(x)
_y=np.sum(y,axis=0)/np.size(y)
x=x-_x
y=y-_y
CovXY=np.sum(x*y,axis=0)
DX=np.sum(x*x,axis=0)
w=CovXY/DX
b=_y-w*_x
print("y=%.3f*x+%.3f"%(w,b))

练习4:

己知:

x0是一个包含长度为10、元素值全部为1的一维数组

x1=[ 64.3,99.6,145.45,63.75,135.46,92.85,86.97,144.76,59.3,116.03]

x2=[2,3,4,2,3,4,2,4,1,3]

y=[ 62.55,82.42,132.62,73.31,131.05,86.57,85.49,127.44,55.25,104.84]

要求:

(1)将x0、x1、x2堆叠为一个10x3的二维数组X,其中 x0、x1、x2依次是第1列,第2列和第3列;

​ 将y变换为10x1的二维数组Y。

(2)计算: w=(XTx)1xTY,并回答: w 的shape 属性结果是什么?

(3)分别输出X,Y和W。

(1)

import numpy as np
x0=np.ones(10)
x1=np.array([ 64.3,99.6,145.45,63.75,135.46,92.85,86.97,144.76,59.3,116.03])
x2=np.array([2,3,4,2,3,4,2,4,1,3])
y=np.array([ 62.55,82.42,132.62,73.31,131.05,86.57,85.49,127.44,55.25,104.84])
X=np.stack((x0,x1,x2),axis=1)
Y=y.reshape(10,1)
print(X)
print("\n")
print(Y)

(2)

import numpy as np
x0=np.ones(10)
x1=np.array([ 64.3,99.6,145.45,63.75,135.46,92.85,86.97,144.76,59.3,116.03])
x2=np.array([2,3,4,2,3,4,2,4,1,3])
y=np.array([ 62.55,82.42,132.62,73.31,131.05,86.57,85.49,127.44,55.25,104.84])
X=np.stack((x0,x1,x2),axis=1)
Y=y.reshape(10,1)
X=np.mat(X)
Y=np.mat(Y)
W=(X.T*X).I*X.T*Y
print(W.shape)
#输出(3,1)

(3)

import numpy as np
x0=np.ones(10)
x1=np.array([ 64.3,99.6,145.45,63.75,135.46,92.85,86.97,144.76,59.3,116.03])
x2=np.array([2,3,4,2,3,4,2,4,1,3])
y=np.array([ 62.55,82.42,132.62,73.31,131.05,86.57,85.49,127.44,55.25,104.84])
X=np.stack((x0,x1,x2),axis=1)
Y=y.reshape(10,1)
X=np.mat(X)
Y=np.mat(Y)
W=(X.T*X).I*X.T*Y
print(W.shape)
print(X,'\n',Y,'\n',W)

练习5:

( 20分 )

按下列要求完成程序。

(1) 下载波士顿数据集,读取全部506条数据,放在NumPy数组x、y中(x:属性,y:标记)。(5分)

(2) 使用全部506条数据,实现波士顿房价数据集可视化,如图1所示。(10分)

(3) 要求用户选择属性,如图2所示,根据用户的选择,输出对应属性的散点图,如图3所示。(5分)

图1

图2

图3

代码:

import tensorflow as tf
import matplotlib.pyplot as plt
boston_housing=tf.keras.datasets.boston_housing
(x_train,y_tain),(x_test,y_test)=boston_housing.load_data(test_split=0)
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

titles = ["CRIM","ZN","INDUS","CHAS","NOX","RM","AGE","DIs","RAD","TAX","PTRATIO","B-1000","LSTAT","MEDV"]
plt.figure(figsize=(12,15))

for i in range(13):
    plt.subplot(4,4,(i+1))
    plt.scatter(x_train[:,i],y_tain)
    plt.xlabel(titles[i])
    plt.ylabel("Price")
    plt.title(str(i+1)+'.'+titles[i]+'-Price')
plt.tight_layout()
plt.suptitle("各个属性与房价的关系",x=0.5,y=1.02, fontsize=20)
plt.show() 

实现用户交互功能:

import tensorflow as tf
import matplotlib.pyplot as plt
boston_housing=tf.keras.datasets.boston_housing
(x_train,y_tain),(x_test,y_test)=boston_housing.load_data(test_split=0)
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

titles = ["CRIM","ZN","INDUS","CHAS","NOX","RM","AGE","DIs","RAD","TAX","PTRATIO","B-1000","LSTAT","MEDV"]
plt.figure(figsize=(12,12))

print("现在有如下属性与索引值:\n")
for i in titles:
    print("%d      %s\n"%(titles.index(i),i))
user=int(input("请输入您想查询的属性与房价的关系(请输入数字):"))

print("显示关系如图:")
plt.scatter(x_train[:,user],y_tain)
plt.xlabel(titles[user])
plt.ylabel("Price")
plt.title(titles[user]+"与房价的关系图")
plt.show()

这里有一个实践上的问题,需要vpn代理开启全局模式才能正常下载数据集,否则无法下载

练习6:

( 20分 )

使用鸢尾花数据集,绘制如下图形,其中对角线为属性的直方图。

示例

import tensorflow as tf
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
import numpy as np


iris=load_iris()
x_train,x_test,y_train,y_test=train_test_split(iris.data,iris.target,test_size=0)

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.figure("鸢尾花数据集", figsize=(15, 15))
plt.subplot("鸢尾花数据图像\nBlue->Setosa|Red->Versicolor|Green->Virginica")
for i in range(4):
    for j in range(4):
        plt.subplot(4, 4, 4 * i + j + 1)
        if j != i:
            plt.scatter(x_train[:, j], x_train[:, i], c=y_train, cmap='brg')
        else:
            plt.hist(x_train[:i], align=mid, color="g")
        if i == 0:
            plt.title(COLUN_NAMES[j])
        if j == 0:
            plt.title(COLUN_NAMES[i])
plt.tight_layout(rect=[0, 0, 1, 0.93])
plt.show()

练习7:

( 20分 )

按下列要求完成程序,随机显示MNIST数据集中的样本,效果如图1所示。

图1

要求:

(1)下载手写数字数据集,读取训练集和测试集数据,放在NumPy数组train_x、train_y、test_x、test_y中;(train_x:训练集图像,train_y:训练集标签,test_x:测试集图像,test_y:测试集标签)

(2)随机从所有测试集数据中显示16幅数字图像;

(3)16幅图像按照4×4方式排列在一张画布中,每幅图像的子标题为该图像的标签值,字体大小为14,全局标题为“MNIST测试集样本”,字体大小为20,颜色为红色。

代码如下:

import tensorflow as tf
import  numpy as np
import matplotlib.pyplot as plt
mnist=tf.keras.datasets.mnist
(x1,y1),(x2,y2)=mnist.load_data()
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

for i in range(16):
    num=np.random.randint(1,5000)
    plt.subplot(4,4,i+1)
    plt.axis("off")
    plt.imshow(x1[i],cmap="gray")
    plt.title(y1[i])
plt.tight_layout()
plt.suptitle("手写数字样本 ",x=0.5,y=1.02, fontsize=20)
plt.show()

练习8:

15分 )

使用TensorFlow张量运算计算w和b,并输出结果。

已知:

x=[ 64.3, 99.6, 145.45, 63.75, 135.46, 92.85, 86.97, 144.76, 59.3, 116.03]

y=[ 62.55, 82.42, 132.62, 73.31, 131.05, 86.57, 85.49, 127.44, 55.25, 104.84]

计算:

图片

(3)分别输出W和b的结果。

提示:

正确的输出结果为

w= 0.83215……

b= 10.2340…….

代码如下:

import tensorflow as tf

x=tf.constant([ 64.3, 99.6, 145.45, 63.75, 135.46, 92.85, 86.97, 144.76, 59.3, 116.03])
y=tf.constant([ 62.55, 82.42, 132.62, 73.31, 131.05, 86.57, 85.49, 127.44, 55.25, 104.84])
_x=tf.reduce_mean(x)
_y=tf.reduce_mean(y)
w=tf.reduce_sum((x-_x)*(y-_y))/tf.reduce_sum(tf.square(x-_x))
b=_y-w*_x
print("W的值是:",w)
print("b的值是:",b)

#输出
#W的值是: tf.Tensor(0.83215153, shape=(), dtype=float32)
#b的值是: tf.Tensor(10.234009, shape=(), dtype=float32)

练习9:

( 15分 )

使用TensorFlow张量运算计算w和b,并输出结果。

已知:

x=[ 64.3, 99.6, 145.45, 63.75, 135.46, 92.85, 86.97, 144.76, 59.3, 116.03]

y=[ 62.55, 82.42, 132.62, 73.31, 131.05, 86.57, 85.49, 127.44, 55.25, 104.84]

计算:

(3)分别输出W和b的结果。

代码如下:

import tensorflow as tf

x=tf.constant([ 64.3, 99.6, 145.45, 63.75, 135.46, 92.85, 86.97, 144.76, 59.3, 116.03])
y=tf.constant([ 62.55, 82.42, 132.62, 73.31, 131.05, 86.57, 85.49, 127.44, 55.25, 104.84])
w=(len(x)*tf.reduce_sum(x*y)-tf.reduce_sum(x)*tf.reduce_sum(y))/(len(x)*tf.reduce_sum(tf.square(x))-tf.square(tf.reduce_sum(x)))
b=(tf.reduce_sum(y)-w*tf.reduce_sum(x))/len(x)
print("W的值是:",w)
print("b的值是:",b)

# 输出
# W的值是: tf.Tensor(0.83215135, shape=(), dtype=float32)
# b的值是: tf.Tensor(10.234021, shape=(), dtype=float32)

可见结果同上一题,说明这是最小二乘法变式

注意tf.size()无法获取张量元素数(准确说的返回值不是数字),这里用len 来表示

练习10:

下载lena.tiff图像(见7.2小节课件),将R、G、B三通道分离,采用灰度图表示颜色的亮度,并分别对各个通道按要求进行处理,结果显示在如图1所示的画布中。

要求:

(1)将R通道的图像缩小为50×50,显示在子图1中,子标题为:“R-缩放”,字体大小为14;

(2)将G通道的图像先水平镜像,再顺时针旋转90度,显示在子图2中,子标题为:“G-镜像+旋转”,字体大小为14,并显示坐标轴;

(3)对B通道的图像进行裁剪,裁剪位置:左上角(0, 0) 右下角(150, 150),显示在子图3中,子标题为:“B-裁剪”,字体大小为14;

(4)将原始的R、G、B通道的图像合并,显示在子图4中,子标题显示图像的色彩模式,字体大小为14;

(5)将要求(4)的处理结果保存为PNG格式的图片,路径为当前工作目录,文件名为“test.png”,如图2所示;

(6)将以上生成的4幅图像显示在2×2的画布中,全局标题为“图像基本操作”,标题字体大小为20,颜色为蓝色。

代码如下:

from PIL import Image
import matplotlib.pyplot as plt
lenna=Image.open("Lenna.jpg")
lenna_r,lenna_g,lenna_b=lenna.split()
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
plt.figure(figsize=(10,10))

plt.subplot(221)
plt.axis("off")
r_resize=lenna_r.resize((50,50))
plt.imshow(r_resize,cmap="gray")
plt.title("R-缩放",fontsize=14)

plt.subplot(222)
g_trans=lenna_g.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_270)
plt.imshow(g_trans,cmap="gray")
plt.title("G-镜像+旋转",fontsize=14)

plt.subplot(223)
plt.axis("off")
b_sub=lenna_b.crop((0,0,150,150))
plt.imshow(b_sub,cmap="gray")
plt.title("B-剪切",fontsize=14)

plt.subplot(224)
plt.axis("off")
merge=Image.merge("RGB",[lenna_r,lenna_g,lenna_b])
plt.imshow(merge)
plt.title("RGB",fontsize=14)

plt.tight_layout()
plt.suptitle("图像基本操作 ",x=0.5,y=1.02, fontsize=20,color="blue")
plt.show()
plt.savefig("test.png")

展示图片如下:

lenna图

这里用的图是网上下载的,所以出来的结果和展示不一样(尺寸问题)

练习11:

使用9.5小节中的“商品房销售记录表”作为样本数据,编程实现一个房价预测系统。

要求:

\1. 矩阵运算部分采用TensorFlow实现,数据加载、输入、输出等可以根据需要采用Python/NumPy来实现。

\2. 提示用户输入商品房面积和房间数,并进行输入校验。合理的输入如下:

面积:20-500之间的实数

房间数:1-10之间的整数

如果输入正确,根据模型估计房价,并显示。

如果输入数据类型错误,或者输入数据范围不合理,根据错误类型提示,并等待用户重新输入。

\3. 可视化数据以及预测超平面

提示:TensorFlow中矩阵求逆函数tf.linalg.inv()

数据(符合对应关系):

面积:[137.97,104.50,100.00,124.32,79.20,99.00,124.00,114.00,106.69,138.05,53.75,46.91,68.00,63.02,81.26,86.21]

房间数:

[3,2,2,3,1,2,3,2,2,3,1,1,1,1,2,2]

销售价格:

[145.00,110.00,93.00,116.00,65.32,104.00,118.00,91.00,62.00,133.00,51.00,45.00,78.50,69.65,75.69,95.30]

代码如下:

解析法:

import numpy as  np
import tensorflow as tf
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
plt.rcParams['font.sans-serif']=['SimHei']
x1=np.array([137.97,104.50,100.00,124.32,79.20,99.00,124.00,114.00,106.69,138.05,53.75,46.91,68.00,63.02,81.26,86.21])
x2=np.array([3,2,2,3,1,2,3,2,2,3,1,1,1,1,2,2])
y=np.array([145.00,110.00,93.00,116.00,65.32,104.00,118.00,91.00,62.00,133.00,51.00,45.00,78.50,69.65,75.69,95.30])
x0=np.ones(len(x1))
X=np.stack((x0,x1,x2),axis=1)
Y=np.array(y).reshape(-1,1)
Xt=np.transpose(X)
XtX_1=np.linalg.inv(np.matmul(Xt,X))
XtX_1Xt=np.matmul(XtX_1,Xt)
W=np.matmul(XtX_1Xt,Y)
W=W.reshape(-1)
Y_pre=W[1]*x1+W[2]*x2+W[0]
X=np.arange(20,150.1)
Y=np.arange(1,10,0.1)
X,Y=np.meshgrid(X,Y)
Z=W[1]*X+W[2]*Y+W[0]
fig=plt.figure()
ax3d=Axes3D(fig)
surf=ax3d.plot_surface(X,Y,Z,cmap="rainbow")
ax3d.set_xlabel("X",color="r",fontsize=14)
ax3d.set_ylabel("Y",color="r",fontsize=14)
ax3d.set_zlabel("price",color="r",fontsize=14)
ax3d.scatter(x1,x2,y,color="b",marker="*",label="label")
ax3d.scatter(x1,x2,Y_pre,color="r",marker="+",label="pred")
plt.suptitle("回归图",fontsize=20)
print("请输入商品房面积和房间数,要求符合:\n面积:20-150之间的实数\n房间数:1-10之间的整数")
a=float(input("请输入面积:"))
b=int(input("请输入房间数:"))
# 懒得做输入校验了
pred=W[1]*a+W[2]*b+W[0]
print("预测的价格是:%.3f"%pred)
ax3d.scatter(a,b,pred,color="g",label="U_pred")
plt.legend()
plt.show()

结果如下:

请输入商品房面积和房间数,要求符合:
面积:20-150之间的实数
房间数:1-10之间的整数
请输入面积:>? 120
请输入房间数:>? 4
预测的价格是:133.480

图片1

图片1

梯度下降法:

import numpy as  np
import tensorflow as tf
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
plt.rcParams['font.sans-serif']=['SimHei']
area=np.array([137.97,104.50,100.00,124.32,79.20,99.00,124.00,114.00,106.69,138.05,53.75,46.91,68.00,63.02,81.26,86.21])
room=np.array([3,2,2,3,1,2,3,2,2,3,1,1,1,1,2,2])
price=np.array([145.00,110.00,93.00,116.00,65.32,104.00,118.00,91.00,62.00,133.00,51.00,45.00,78.50,69.65,75.69,95.30])

num=len(area)
x0=np.ones(num)
#归一化处理
x1=(area-area.min())/(area.max()-area.min())
x2=(room-room.min())/(room.max()-room.min())
X=np.stack((x0,x1,x2),axis=1)
Y=price.reshape(-1,1)

learn_rate=0.2
epoch=50

display_step=5
np.random.seed(612)
W=tf.Variable(np.random.randn(3,1))

mse=[]
for i in range(0,epoch+1):
    with tf.GradientTape() as tape:
        Pred=tf.matmul(X,W)
        Loss=0.5*tf.reduce_mean(tf.square(Y-Pred))
    mse.append(Loss)

    dL_dw=tape.gradient(Loss,W)
    W.assign_sub(learn_rate*dL_dw)

    if i % display_step==0:
        print("第%d轮的损失为:%f"%(i,Loss))
plt.figure(figsize=(20,8),dpi=120)
n=range(0,epoch+1)
plt.plot(n,mse,label="损失函数")
plt.legend(loc="best")
plt.suptitle("损失曲线")
plt.show()

损失可视化

练习12:

( 20分 )

使用波士顿房价数据集中的“低收入人口比例”属性,来训练和测试一元线性回归模型,并对模型进行可视化。

要求:程序+文本(记录下超参数的调试过程,并简要总结。)

结论就是线性回归train不起来

首先,这个数据长这个样子:

我用线性回归硬train了一发,然后显示预测数据nan(无穷大),然后查看损失,损失可视化显示训练到某一轮的时候突然增大,大概是梯度下降的时候出现问题了

怀疑是数据的问题,然后我就改了下,选择的数据改成了房间数(就改了数据集切片其他一点也没动)

然后成功了

import numpy as  np
import tensorflow as tf
import matplotlib.pyplot as plt
boston_housing=tf.keras.datasets.boston_housing
(train_x,train_y),(test_x,test_y)=boston_housing.load_data()
x_train=train_x[:,5]
y_train=train_y
x_test=test_x[:,5]
y_test=test_y

learn_rate=0.04
epoch=2000
display_step=200
np.random.seed(612)
w=tf.Variable(np.random.randn(),dtype=tf.float32)
b=tf.Variable(np.random.randn(),dtype=tf.float32)

mse_train=[]
mse_test=[]

for i in range(0,epoch+1):
    with tf.GradientTape() as tape:
        pred_train=w*x_train+b
        loss=0.5*tf.reduce_mean(tf.square(y_train-pred_train))
        pred_test=w*x_test+b
        loss_=0.5*tf.reduce_mean(tf.square(y_test-pred_test))
    mse_train.append(loss)
    mse_test.append(loss_)
    dl_dw,dl_db=tape.gradient(loss,[w,b])
    w.assign_sub(learn_rate*dl_dw)
    b.assign_sub(learn_rate*dl_db)

plt.figure(figsize=(15,10),dpi=150)
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.subplot(221)
plt.scatter(x_train,y_train,color="blue",label="data")
plt.plot(x_train,pred_train,color="red",label="predict")
plt.legend(loc="upper right")
plt.title("数据与预测曲线")

plt.subplot(222)
plt.plot(mse_train,color="blue",linewidth=3,label="train loss")
plt.plot(mse_test,color="red",linewidth=1.5,label="test loss")
plt.legend(loc="upper right")
plt.title("损失可视化")

plt.subplot(223)
plt.plot(y_train,color="blue",marker="*",label="true_price")
plt.plot(pred_train,color="red",marker=".",label="predict")
plt.legend()
plt.title("训练集对照")

plt.subplot(224)
plt.plot(y_test,color="blue",marker="*",label="true_price")
plt.plot(pred_test,color="red",marker=".",label="predict")
plt.legend()
plt.title("测试集对照")

plt.tight_layout()
plt.show()

练习13:

使用波士顿房价数据集中的所有属性,训练和测试多元线性回归模型,并可视化模型。

要求:程序+文本(记录下超参数的调试过程,并简要总结)

import numpy as  np
import tensorflow as tf
import matplotlib.pyplot as plt
boston_housing=tf.keras.datasets.boston_housing
(train_x,train_y),(test_x,test_y)=boston_housing.load_data()
x_train=(train_x-train_x.min(axis=0))/(train_x.max(axis=0)-train_x.min(axis=0))
y_train=train_y
x_test=(test_x-test_x.min(axis=0))/(test_x.max(axis=0)-test_x.min(axis=0))
y_test=test_y

x0_train=np.ones(len(train_x)).reshape(-1,1)
x0_test=np.ones(len(test_x)).reshape(-1,1)

X_train=tf.cast(tf.concat([x0_train,x_train],axis=1),tf.float32)
X_test=tf.cast(tf.concat([x0_test,x_test],axis=1),tf.float32)

Y_train=tf.constant(y_train.reshape(-1,1),tf.float32)
Y_test=tf.constant(y_test.reshape(-1,1),tf.float32)

learn_rate=0.01
epoch=2000
np.random.seed(612)
w=tf.Variable(np.random.randn(14,1),dtype=tf.float32)
b=tf.Variable(np.random.randn(14,1),dtype=tf.float32)

mse_train=[]
mse_test=[]

for i in range(0,epoch+1):
    with tf.GradientTape() as tape:
        pred_train=tf.matmul(X_train,w)
        loss=0.5*tf.reduce_mean(tf.square(Y_train-pred_train))
        pred_test=tf.matmul(X_test,w)
        loss_=0.5*tf.reduce_mean(tf.square(Y_test-pred_test))
    mse_train.append(loss)
    mse_test.append(loss_)
    dl_dw=tape.gradient(loss,w)
    w.assign_sub(learn_rate*dl_dw)

plt.figure(figsize=(15,4),dpi=150)
plt.rcParams['font.sans-serif'] = ['SimHei']

plt.subplot(131)
plt.plot(mse_train,color="blue",linewidth=3,label="train loss")
plt.plot(mse_test,color="red",linewidth=1.5,label="test loss")
plt.legend(loc="upper right")
plt.title("损失可视化")

plt.subplot(132)
plt.plot(y_train,color="blue",marker="*",label="true_price")
plt.plot(pred_train,color="red",marker=".",label="predict")
plt.legend()
plt.title("训练集对照")

plt.subplot(133)
plt.plot(y_test,color="blue",marker="*",label="true_price")
plt.plot(pred_test,color="red",marker=".",label="predict")
plt.legend()
plt.title("测试集对照")

plt.tight_layout()
plt.show()

可见预测比单一数据要好

练习14:

( 15分 )

选择不同的2种属性组合,区分山鸢尾和维吉尼亚鸢尾,编写程序,记录并分析结果,给出总结。

(1) 编写代码 (8分)

(2) 记录结果 (5分)

比较选择不同属性组合时的学习率、迭代次数、以及在训练集和测试集上的交叉熵损失和准确率,以表格或合适的图表形式展示。

(3) 总结 (2分)

采用不同的属性组合效果是否相同,如果相同或者不同,对你有什么启发。

示例

由这张之前的图(蓝色和绿色是我们想区分的,可见还是很容易的)

于是我们选取花瓣长与花瓣宽开始训练

代码如下:

import numpy as  np
import tensorflow as tf
import matplotlib.pyplot as plt
import matplotlib as mpl
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
iris=load_iris()
x_train,x_test,y_train,y_test=train_test_split(iris.data,iris.target,test_size=0.2,random_state=22)

x_train=x_train[y_train!=1][:,2:4]
y_train=y_train[y_train!=1]
for i in range(len(y_train)):
    if y_train[i]==2:
        y_train[i]=1
x_test=x_test[y_test!=1][:,2:4]
y_test=y_test[y_test!=1]
for i in range(len(y_test)):
    if y_test[i]==2:
        y_test[i]=1
#数据处理区分

x_train=x_train-np.mean(x_train,axis=0)
#中心化数据

x0_train=np.ones(len(x_train)).reshape(-1,1)

X=tf.cast(tf.concat((x0_train,x_train),axis=1),tf.float32)
Y=tf.cast(y_train.reshape(-1,1),tf.float32)

learn_rate=0.2
epoch=100
display_step=30
np.random.seed(612)
W=tf.Variable(np.random.randn(3,1),dtype=tf.float32)
ce =[]
acc=[]
for i in range(0,epoch):
    with tf.GradientTape() as tap:
        Pred=1/(1+tf.exp(-tf.matmul(X,W)))
        Loss=-tf.reduce_mean(Y*tf.math.log(Pred)+(1-Y)*tf.math.log(1-Pred))
    accuracy=tf.reduce_mean(tf.cast(tf.equal(tf.where(Pred.numpy()<0.5,0.,1.),Y),tf.float32))
    ce.append(Loss)
    acc.append(accuracy)

    dL_dW=tap.gradient(Loss,W)
    W.assign_sub(learn_rate*dL_dW)
    if i % display_step ==0:
        print("i: %d, Acc:%f, Loss:%f"%(i,accuracy,Loss))
plt.figure(figsize=(20,8),dpi=150)

plt.subplot(121)
plt.plot(ce,color="b",label="Loss")
plt.plot(acc,color="r",label="acc")
plt.legend()
plt.title("损失与准确率")

plt.show()
plt.subplot(122)
cm_pt=mpl.colors.ListedColormap(["blue","red"])
plt.scatter(x_train[:,0],x_train[:,1],c=y_train,cmap=cm_pt)
x_=[-1.5,1.5]
y_=-(W[1]*x_+W[0])/W[2]
plt.plot(x_,y_,color='r')
plt.title("数据与决策平面")
plt.tight_layout()
plt.show()

数据可视化结果

练习15:

( 20分 )

分别选择2种、3种和4种属性,编写程序,区分变色鸢尾、山鸢尾和维吉尼亚鸢尾。记录和分析实验结果,并给出总结。

这里属于多分类,这里我们 同样选取花瓣长与花瓣宽

import matplotlib.pyplot as plt
import  tensorflow as tf
import  numpy as np
import  matplotlib as mpl
from sklearn.datasets import  load_iris
from sklearn.model_selection import train_test_split

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
iris=load_iris()
x_train,x_test,y_train,y_test=train_test_split(iris.data,iris.target,test_size=0.2,random_state=22)

x_train=x_train[:,2:4]
y_train=y_train
x_test=x_test[:,2:4]
y_test=y_test
#数据处理区分

x0_train=np.ones(len(x_train)).reshape(-1,1)
x0_test=np.ones(len(x_test)).reshape(-1,1)
X_train=tf.cast(tf.concat([x0_train,x_train],axis=1),tf.float32)
Y_train=tf.one_hot(tf.constant(y_train,dtype=tf.int32),3)
Y_test=tf.one_hot(tf.constant(y_test,dtype=tf.int32),3)
X_test=tf.cast(tf.concat([x0_test,x_test],axis=1),tf.float32)
#处理数据

learn_rate=0.2
epoch=500
display_step=100
np.random.seed(612)
W=tf.Variable(np.random.randn(3,3),dtype=tf.float32)

acc=[]
cce=[]
acc_=[]
cce_=[]

for i in range(epoch+1):
    with tf.GradientTape() as tape:
        pred=tf.nn.softmax(tf.matmul(X_train,W))
        Loss_train=-tf.reduce_mean(Y_train*tf.math.log(pred))
    pred_= tf.nn.softmax(tf.matmul(X_test, W))
    Loss_test = -tf.reduce_mean(Y_test * tf.math.log(pred_))
    accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(pred.numpy() ,axis=1), y_train), tf.float32))
    accuracy_= tf.reduce_mean(tf.cast(tf.equal(tf.argmax(pred_.numpy(), axis=1), y_test), tf.float32))
    #argmax()返回最大值索引号,所以这里校验时不用独热码而是用原始数据

    acc.append(accuracy)
    cce.append(Loss_train)
    acc_.append(accuracy_)
    cce_.append(Loss_test)

    dl_dw=tape.gradient(Loss_train,W)
    W.assign_sub(learn_rate*dl_dw)

    if i%display_step ==0:
        print("i: %d, trainAcc:%f, trainLoss:%f"%(i,accuracy,Loss_train))
        print("        testAcc:%f,  testLoss:%f" % (accuracy_, Loss_test))

plt.figure(figsize=(20,24),dpi=150)

plt.subplot(221)
plt.plot(cce,color="b",label="训练集损失")
plt.plot(cce_,color="r",label="测试集损失")
plt.legend()
plt.title("数据集损失")

plt.subplot(222)
plt.plot(cce,color="b",label="训练集准确率")
plt.plot(cce_,color="r",label="测试集准确率")
plt.legend()
plt.title("数据集准确率")


plt.subplot(223)
M=500
x1_min,x2_min=x_train.min(axis=0)
x1_max,x2_max=x_train.max(axis=0)
t1=np.linspace(x1_min,x1_max,M)
t2=np.linspace(x2_min,x2_max,M)
m1,m2=np.meshgrid(t1,t2)
m0=np.ones(M*M)
X_=tf.cast(np.stack((m0,m1.reshape(-1),m2.reshape(-1)),axis=1),tf.float32)
Y_=tf.nn.softmax(tf.matmul(X_,W))
Y_=tf.argmax(Y_.numpy(),axis=1)
n=tf.reshape(Y_,m1.shape)
cm_bg=mpl.colors.ListedColormap(["#A0FFA0","#FFA0A0","#A0A0FF"])
plt.pcolormesh(m1,m2,n,cmap=cm_bg)
plt.scatter(x_train[:,0],x_train[:,1],c=y_train,cmap="brg")
plt.title("训练数据与决策平面")

plt.subplot(224)
cm_bg_=mpl.colors.ListedColormap(["#A0FFA0","#FFA0A0","#A0A0FF"])
plt.pcolormesh(m1,m2,n,cmap=cm_bg)
plt.scatter(x_test[:,0],x_test[:,1],c=y_test,cmap="brg")
plt.title("测试数据与决策平面")

plt.tight_layout()
plt.show()

输出如下:

i: 0, trainAcc:0.366667, trainLoss:1.422851
testAcc:0.200000, testLoss:1.845798
i: 100, trainAcc:0.683333, trainLoss:0.237928
testAcc:0.666667, testLoss:0.234590
i: 200, trainAcc:0.808333, trainLoss:0.194367
testAcc:0.833333, testLoss:0.200174
i: 300, trainAcc:0.858333, trainLoss:0.170748
testAcc:0.866667, testLoss:0.180454
i: 400, trainAcc:0.875000, trainLoss:0.155550
testAcc:0.900000, testLoss:0.167200
i: 500, trainAcc:0.916667, trainLoss:0.144651
testAcc:0.933333, testLoss:0.157360

画出来图如下,有点丑了,但还算能看:

现在有个问题,就是这个决策平面显然并不是我们想要的,直觉告诉我,应该平面像是这样分类的准确性才会高一点:

特别是在蓝绿两个类之间,不该是贯穿的切法,而应该是横切,认为是训练不充分,于是把训练轮数提高8倍到4000轮:

结果是:

i: 0, trainAcc:0.366667, trainLoss:1.422851
testAcc:0.200000, testLoss:1.845798
i: 100, trainAcc:0.683333, trainLoss:0.237928
testAcc:0.666667, testLoss:0.234590
i: 200, trainAcc:0.808333, trainLoss:0.194367
testAcc:0.833333, testLoss:0.200174
i: 300, trainAcc:0.858333, trainLoss:0.170748
testAcc:0.866667, testLoss:0.180454
i: 400, trainAcc:0.875000, trainLoss:0.155550
testAcc:0.900000, testLoss:0.167200
i: 500, trainAcc:0.916667, trainLoss:0.144651
testAcc:0.933333, testLoss:0.157360

​ ……………….

i: 3800, trainAcc:0.966667, trainLoss:0.068734
testAcc:0.933333, testLoss:0.081017
i: 3900, trainAcc:0.966667, trainLoss:0.067992
testAcc:0.933333, testLoss:0.080229
i: 4000, trainAcc:0.966667, trainLoss:0.067277
testAcc:0.933333, testLoss:0.079468

虽然训练集上升并且没有产生过拟合但是测试集的准确率已经不动了(可能因为测试的数据少),不过loss在下降,往后非常慢的降

某种意义上是往着我们期望的方向发展,应该是达到了目的,也许会有更好的方法

练习16:

使用多层神经网络实现鸢尾花分类,编写程序,尝试改变隐含层层数、隐含层中节点数以及其他超参数,记录并分析实验结果,给出总结。

要求:

(1)编写程序(7分)

(2)记录超参数的调整过程和结果(3分)

(3)总结(5分)

比较时间代价、分析不同超参数对结果准确性的影响

import matplotlib.pyplot as plt
import  tensorflow as tf
import  numpy as np
import  matplotlib as mpl
from sklearn.datasets import  load_iris
from sklearn.model_selection import train_test_split

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
iris=load_iris()
x_train,x_test,y_train,y_test=train_test_split(iris.data,iris.target,test_size=0.2,random_state=22)

x_train=x_train[:,0:4]
y_train=y_train
x_test=x_test[:,0:4]
y_test=y_test
#数据处理区分

x_train=x_train-np.mean(x_train,axis=0)
x_test=x_test-np.mean(x_test,axis=0)

X_train=tf.cast(x_train,tf.float32)
Y_train=tf.one_hot(tf.constant(y_train,dtype=tf.int32),3)
Y_test=tf.one_hot(tf.constant(y_test,dtype=tf.int32),3)
X_test=tf.cast(x_test,tf.float32)
#处理数据

learn_rate=0.2
epoch=4000
display_step=100
np.random.seed(612)
W1=tf.Variable(np.random.randn(4,16),dtype=tf.float32)
B1=tf.Variable(tf.zeros([16]),dtype=tf.float32)
W2=tf.Variable(np.random.randn(16,3),dtype=tf.float32 )
B2=tf.Variable(tf.zeros([3]),dtype=tf.float32)
acc=[]
cce=[]
acc_=[]
cce_=[]

for i in range(epoch+1):
    with tf.GradientTape() as tape:
        Hidden_train=tf.nn.relu(tf.matmul(X_train,W1)+B1)
        pred=tf.nn.softmax(tf.matmul(Hidden_train,W2)+B2)
        Loss_train=tf.reduce_mean(tf.keras.losses.categorical_crossentropy(y_true=Y_train,y_pred=pred))

        Hidden_test = tf.nn.relu(tf.matmul(X_test, W1) + B1)
        pred_= tf.nn.softmax(tf.matmul(Hidden_test, W2) + B2)
        Loss_test = tf.reduce_mean(tf.keras.losses.categorical_crossentropy(y_true=Y_test, y_pred=pred_))


    accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(pred.numpy() ,axis=1), y_train), tf.float32))
    accuracy_= tf.reduce_mean(tf.cast(tf.equal(tf.argmax(pred_.numpy(), axis=1), y_test), tf.float32))

    #argmax()返回最大值索引号,所以这里校验时不用独热码而是用原始数据

    acc.append(accuracy)
    cce.append(Loss_train)
    acc_.append(accuracy_)
    cce_.append(Loss_test)

    grade=tape.gradient(Loss_train,[W1,B1,W2,B2])
    W1.assign_sub(learn_rate*grade[0])
    B1.assign_sub(learn_rate * grade[1])
    W2.assign_sub(learn_rate * grade[2])
    B2.assign_sub(learn_rate * grade[3])
        if i>0 and cce_[i]>cce_[i-1]:
        print("--------------------stop at %d epoch-----------------------"%i)
        break

    if i%display_step ==0:
        print("i: %d, trainAcc:%f, trainLoss:%f"%(i,accuracy,Loss_train))
        print("        testAcc:%f,  testLoss:%f" % (accuracy_, Loss_test))

plt.figure(figsize=(20,8),dpi=150)

plt.subplot(121)
plt.plot(cce,color="b",label="训练集损失")
plt.plot(cce_,color="r",label="测试集损失")
plt.legend()
plt.title("数据集损失")

plt.subplot(122)
plt.plot(acc,color="b",label="训练集准确率")
plt.plot(acc_ ,color="r",label="测试集准确率")
plt.legend()
plt.title("数据集准确率")



plt.tight_layout()
plt.show()

这次同样训练了4k轮,结果很amzing啊

过拟合了

看起来使用relu优化的两层神经网络好像没有在感知机中表现的好………,因为最后测试集的准确率连80%都没有

不过relu下降的倒是很快,现在用early_stopping的方法控制,即当验证集损失开始上升时停止训练(这里就把测试集当验证集了

  if i>0 and cce_[i]>cce_[i-1]:
        print("--------------------stop at %d epoch-----------------------"%i)
        break

输出是:

i: 0, trainAcc:0.450000, trainLoss:2.028374
testAcc:0.233333, testLoss:2.409625
——————–stop at 30 epoch———————–

30轮就训练完了,可见下降相当之快啊,就是最后泛化性有点差

练习17:

使用TensorFlow中的keras库,实现Minist手写数字识别。编写程序,尝试调整神经网络的层数、节点个数以及优化器等参数,记录并分析实验结果,保存最佳训练模型,给出总结。

要求:

(1)编写程序(7分)

(2)记录参数的调整过程和结果(3分)

(3)总结。(5分)

从准确率、时间效率等方面对实验结果进行分析

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

mnist=tf.keras.datasets.mnist
(train_x,train_y),(test_x,test_y)=mnist.load_data()

# X_train=train_x.reshape((60000,28*28))
# X_test=test_x.reshape((10000,28*28))
#如果没有拉伸的层就用这个语句

X_train,X_test=tf.cast(train_x/255.0,tf.float32),tf.cast(test_x/255.0,tf.float32)
Y_train,Y_test=tf.cast(train_y,tf.int16),tf.cast(test_y,tf.int16)

model=tf.keras.Sequential()
model.add(tf.keras.layers.Flatten(input_shape=(28,28)))
model.add(tf.keras.layers.Dense(128,activation="relu"))
model.add(tf.keras.layers.Dense(10,activation="softmax"))

model.compile(optimizer="adam",loss="sparse_categorical_crossentropy",metrics=['sparse_categorical_accuracy'])

model.fit(X_train,Y_train,batch_size=64,epochs=5,validation_split=0.2)
model.evaluate(X_test,Y_test,verbose=2)

y_pred=model.predict_classes(X_test[0:1000])

plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
plt.figure(dpi=150)
for i in range(25):
    num=np.random.randint(0,1000)
    plt.subplot(5,5,i+1)
    plt.axis("off")
    plt.imshow(test_x[num],cmap="gray")
    title="y="+str(test_y[num])+"\ny_pred="+str(y_pred[num])
    plt.title(title)
plt.tight_layout()
plt.suptitle("手写数字样本预测 ",x=0.5,y=1.02, fontsize=20)
plt.show()

训练5轮的结果:

Epoch 1/5
750/750 [==============================] - 2s 2ms/step - loss: 0.5641 - sparse_categorical_accuracy: 0.8408 - val_loss: 0.1859 - val_sparse_categorical_accuracy: 0.9454
Epoch 2/5
750/750 [==============================] - 1s 1ms/step - loss: 0.1547 - sparse_categorical_accuracy: 0.9554 - val_loss: 0.1272 - val_sparse_categorical_accuracy: 0.9621
Epoch 3/5
750/750 [==============================] - 1s 1ms/step - loss: 0.1054 - sparse_categorical_accuracy: 0.9691 - val_loss: 0.1139 - val_sparse_categorical_accuracy: 0.9653
Epoch 4/5
750/750 [==============================] - 1s 1ms/step - loss: 0.0788 - sparse_categorical_accuracy: 0.9764 - val_loss: 0.0931 - val_sparse_categorical_accuracy: 0.9721
Epoch 5/5
750/750 [==============================] - 1s 1ms/step - loss: 0.0609 - sparse_categorical_accuracy: 0.9825 - val_loss: 0.0902 - val_sparse_categorical_accuracy: 0.9720
313/313 - 0s - loss: 0.0823 - sparse_categorical_accuracy: 0.9748

可见下降很快

训练加到100轮后,几次训练集达到100%准确率,时间太长就不展示了

总的来说使用tensorflow的高阶api不仅代码量少了很多而且更加准确

练习18:

( 10分 )

编写程序,使用作业1中训练好的模型,实现对自制手写数字数据集的识别。

要求:

(1) 将下面名为“自制手写数字.zip”压缩包中自制的手写数字转换为28*28的数组形式,并将数字放在图片中心。(5分)

(2) 加载作业1中训练好的模型,使用该模型对要求(1)中的手写数字进行识别。(5分)

提示:

图像操作部分可参考第7讲“数字图像基础”

可能用到的函数:

裁剪图像:crop()

转换成二值图像 :convert()

改变大小:resize()

训练模型:

import tensorflow as tf
import numpy as np

mnist=tf.keras.datasets.mnist
(train_x,train_y),(test_x,test_y)=mnist.load_data()

X_train,X_test=tf.cast(train_x/255.0,tf.float32),tf.cast(test_x/255.0,tf.float32)
Y_train,Y_test=tf.cast(train_y,tf.int16),tf.cast(test_y,tf.int16)

model=tf.keras.Sequential()
model.add(tf.keras.layers.Flatten(input_shape=(28,28)))
model.add(tf.keras.layers.Dense(128,activation="relu"))
model.add(tf.keras.layers.Dense(10,activation="softmax"))

model.compile(optimizer="adam",loss="sparse_categorical_crossentropy",metrics=['sparse_categorical_accuracy'])

model.fit(X_train,Y_train,batch_size=64,epochs=100,validation_split=0.2)
#训练100轮,由于没有用GPU加速所以每轮用了1s
model.evaluate(X_test,Y_test,verbose=2)

model.save("mist_model.h5")

使用模型:

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

mnist=tf.keras.datasets.mnist
(train_x,train_y),(test_x,test_y)=mnist.load_data()

X_train,X_test=tf.cast(train_x/255.0,tf.float32),tf.cast(test_x/255.0,tf.float32)
Y_train,Y_test=tf.cast(train_y,tf.int16),tf.cast(test_y,tf.int16)

model=tf.keras.models.load_model("mist_model.h5")
y_pred=model.predict_classes(X_test[0:1000])

plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
plt.figure(dpi=150)
for i in range(25):
    num=np.random.randint(0,1000)
    plt.subplot(5,5,i+1)
    plt.axis("off")
    plt.imshow(test_x[num],cmap="gray")
    title="y="+str(test_y[num])+"\ny_pred="+str(y_pred[num])
    plt.title(title)
plt.tight_layout()
plt.suptitle("手写数字样本预测 ",x=0.5,y=1.02, fontsize=20)
plt.show()

说明保存成功,并且可以应用了

现在开始实际应用:

首先这是我们的测试样本:

我们先处理下图片:

基本处理操作包括:

  • 加载图像
  • 处理图像尺寸变成28*28
  • 二值化图像(事实上是灰度化)
  • 必要时对图像反色处理(因为这里是黑笔写的所以与MNIST不同)
import matplotlib.pyplot as plt
from PIL import Image
import tensorflow as tf

plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
plt.figure(figsize=(10,4),dpi=150)

MyData=[]
for i in range(9):
    path="D:\code\ML\data\手写数字\\"+str(i+1)+".png"
    MyData.append(Image.open(path))

for i in range(9):
    plt.subplot(2,5,i+1)
    plt.axis("off")
    plt.imshow(MyData[i], cmap="gray")

单个图片数据的形状:

for i in range(9):
    print(MyData[0].shape)

(93, 73, 4)
(93, 73, 4)
(93, 73, 4)
(93, 73, 4)
(93, 73, 4)
(93, 73, 4)
(93, 73, 4)
(93, 73, 4)
(93, 73, 4)

可见这是一个尺寸93*73的rgba彩色文件,我们的目标是要把每个文件处理成28x28的二值文件

import matplotlib.pyplot as plt
from PIL import Image
import tensorflow as tf
import numpy as np

plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

MyData=[]
for i in range(9):
    path="D:\code\ML\data\手写数字\\"+str(i+1)+".png"
    Img=Image.open(path)
    Img=Img.convert("1")#二值化图片
    Img=Img.resize((28,28))#转换尺寸
    Img=np.array(Img)
    MyData.append(Img)

for i in range(9):
    plt.subplot(2,5,i+1)
    plt.axis("off")
    plt.imshow(MyData[i], cmap="gray")

但是,加载出来的图片却是这样的:

这是个啥玩意。。。。。。,噪声太多了

看来不是变成二值化啊,于是转换成灰度图

效果好很多了,但不是我们想要的,因为我们训练的模型使用的数据是数字白,背景黑,而我们目标数据是数字黑背景白,所以要进行一个反色处理,结果就是这样

与MNIST几乎一样了

然后就可以套用模型辣

结果是:

这机器学了个寂寞啊。。。。。。

但是在测试集上准确率的确是我们想要的,为什么应用起来就有问题了呢

观察了下手写数字样本:

和我们处理的图片比,可见图片中数字的部分占比比我们制作图的要大,应该是我的图还缺少一个裁切主体的部分

于是把图片裁剪了下:

裁剪前

裁剪后

然后预测。。。。。

裁剪处理后的

对比之前

好歹对了一个……….准确率从10%提升到了20%,可喜可贺可喜可贺(泪目)

现在分析问题原因可能在于我所用的数据笔画太细,而训练用的数据笔画太粗,也就是说训练的时候学到了不该考虑进去的征兆,很可能是训练次数过大

调低训练次数到30次,再使用模型,但是并没有用。。。。。。

可能还是有不足吧,以后学习了更多在再来挑战

代码在这

import matplotlib.pyplot as plt
from PIL import Image
import tensorflow as tf
import numpy as np

plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

MyData=[]
for i in range(9):
    path="D:\code\ML\data\手写数字\\"+str(i+1)+".png"
    Img=Image.open(path)
    Img=Img.convert("L")#二值化图片
    Img=Img.resize((73,73))#转换尺寸
    Img=Img.crop((9,9,63,63))
    Img = Img.resize((28, 28))  # 转换尺寸
    Img=np.array(Img)
    Img = 255 - Img  # 图像反色
    MyData.append(Img)

MyData=np.array(MyData)
MyData=tf.cast(MyData/255.0,tf.float32)#归一化处理

model=tf.keras.models.load_model("mist_model.h5")
y_pred=np.argmax(model.predict(MyData[0:9]),axis=1)


for i in range(9):
    plt.subplot(2,5,i+1)
    plt.axis("off")
    path = "D:\code\ML\data\手写数字\\" + str(i + 1) + ".png"
    Img = Image.open(path)
    plt.imshow(Img,cmap="gray")
    title="pred="+str(y_pred[i])
    plt.title(title)
plt.tight_layout()
plt.suptitle("自制手写数字样本预测 ",x=0.5,y=1.02, fontsize=20)
plt.show()

自此整个课程的作业就结束了,接下来要学习的是北京大学的Tensorflow课程

尝试1

重新制作了数据集,图片更加纯净而且笔画也更加粗

结果是:

实验结果提升到40%诶

训练20轮的效果比100要好点

import matplotlib.pyplot as plt
from PIL import Image
import tensorflow as tf
import numpy as np

plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

MyData=[]
for i in range(10):
    path="D:\code\ML\data\手写数字\\"+str(i)+".png"
    Img=Image.open(path)
    Img=Img.convert("L")#二值化图片
    Img=Img.resize((73,73))#转换尺寸
    Img=Img.crop((9,9,63,63))
    Img = Img.resize((28, 28))  # 转换尺寸
    Img=np.array(Img)
    Img = 255 - Img  # 图像反色
    MyData.append(Img)

MyData=np.array(MyData)
MyData=tf.cast(MyData/255.0,tf.float32)#归一化处理

model=tf.keras.models.load_model("mist_model.h5")
y_pred=np.argmax(model.predict(MyData[0:10]),axis=1)


for i in range(10):
    plt.subplot(2,5,i+1)
    plt.axis("off")
    path = "D:\code\ML\data\手写数字\\" + str(i) + ".png"
    Img = Image.open(path)
    plt.imshow(MyData[i],cmap="gray")
    title="pred="+str(y_pred[i])
    plt.title(title)
plt.tight_layout()
plt.suptitle("自制手写数字样本预测 ",x=0.5,y=1.02, fontsize=20)
plt.show()

针对练习18的最终解决方案

今天看了北京大学的mooc展示后我发现一个问题

tensorflow提供的图片和图片矩阵是这样的:

而要识别的图片经过灰度化以及裁剪反色等处理后,图片以及矩阵是这样的:

也就是说我们处理后的图片还不够纯净,需要对图片进行进一步清洗

把要识别的图片中所有小于102的数据变成0以后

图片纯净多了

调高阈值到130,进一步清洗,再对每个图片应用清洗的方法后,再套上模型

这一次准确率大幅度提高:

而且判别错误的两个就算判别有误也比原来5更加合理

至于为什么8和9会判错,原因应该是8和9整体亮度比其他低,而我们用的是统一的阈值,所以更脏的8和9就没有洗干净

放代码

import matplotlib.pyplot as plt
from PIL import Image
import tensorflow as tf
import numpy as np

plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

MyData=[]

mnist=tf.keras.datasets.mnist
(x1,y1),(x2,y2)=mnist.load_data()

for i in range(9):
    path="D:\code\ML\data\手写数字_\\"+str(i+1)+".png"
    Img=Image.open(path)
    Img=Img.convert("L")#二值化图片
    Img=Img.resize((73,73))#转换尺寸
    Img=Img.crop((9,9,63,63))
    Img = Img.resize((28, 28))  # 转换尺寸
    Img=np.array(Img)
    Img = 255 - Img  # 图像反色
    MyData.append(Img)
for k in range(9):
    for i in range(28):
        for j in range(28):
            if MyData[k][i][j] <130:
                MyData[k][i][j]=0



MyData=np.array(MyData)
MyData=tf.cast(MyData/255.0,tf.float32)#归一化处理

model=tf.keras.models.load_model("mist_model_.h5")
y_pred=np.argmax(model.predict(MyData[0:9]),axis=1)


for i in range(9):
    plt.subplot(2,5,i+1)
    plt.axis("off")
    path = "D:\code\ML\data\手写数字_\\" + str(i + 1) + ".png"
    Img = Image.open(path)
    plt.imshow(Img,cmap="gray")
    title="pred="+str(y_pred[i])
    plt.title(title)
plt.tight_layout()
plt.suptitle("自制手写数字样本预测 ",x=0.5,y=1.02, fontsize=20)
plt.show()

文章作者: 晓沐
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 晓沐 !
评论
  目录