tensorflow 拟合sin曲线,并绘图

tensorflow使用深度模型进行分类问题训练大概分为以下几步:

1:提取数据,包括数据打乱,训练和测试数据分割

2:定义深度网络模型

3:训练模型,包括定义损失函数、梯度下降最小化损失函数

4:测试模型

下面是一个二分类的模型学习与测试。数据是用sin生成要给曲线,曲线上面的数据定义标签为1,下面的定义为0。

输入数据就两个特征,分别为横轴和纵轴坐标。

两层网络模型,第一层32个神经元,第二层8个神经元。

使用交叉熵损失,梯度下降(未使用SGDM、Adam等梯度下降)

测试结果使用matplot组图,并作出网格分割图。

import numpy as np 
import pandas as pd
import tensorflow as tf 
#第一步:生成数据
x_data=np.random.random([1000,2])
df=pd.DataFrame(x_data,columns=["x1","x2"])
df["x1"]=df["x1"]*10
df["x2"]=10*(df["x2"]-0.5)
def fun(x):
    if x["x2"] > 3 * np.sin(x["x1"]):
        return 1
    else:
        return 0
df["label"]=df.apply(lambda x: fun(x),axis=1)
x_data=df.loc[:,["x1","x2"]].values
y_data=df["label"]

#加入一点噪声
df["label"][::51]=1
df["label"][::50]=0
x_data=x_data.astype(np.float32)
y_data=y_data.astype(np.int32)

#打乱数据
np.random.seed(10)
np.random.shuffle(x_data)
np.random.seed(10)
np.random.shuffle(y_data)
print(x_data.shape)
print(y_data.shape)

#分割训练和测试数据
x_train=x_data[:-100]
y_train=y_data[:-100]
x_test=x_data[-100:]
y_test=y_data[-100:]

#每次喂入神经网络32个样本
train_db=tf.data.Dataset.from_tensor_slices((x_train,y_train)).batch(32)
test_db=tf.data.Dataset.from_tensor_slices((x_test,y_test)).batch(32)

lr=0.0005#学习率
epoch=200#定义训练轮次
loss_results=[]
acc=[]
#第二步:定义网络参数
w1=tf.Variable(tf.random.truncated_normal([2,32],stddev=0.1))
b1=tf.Variable(tf.random.truncated_normal([32],stddev=0.1))
w2=tf.Variable(tf.random.truncated_normal([32,16],stddev=0.1))
b2=tf.Variable(tf.random.truncated_normal([16],stddev=0.1))
w3=tf.Variable(tf.random.truncated_normal([16,2],stddev=0.1))
b3=tf.Variable(tf.random.truncated_normal([2],stddev=0.1))

#第三步:训练模型
for epoch in range(epoch):
    loss_all=0
    for i,(x_train,y_train) in enumerate(train_db):
        with tf.GradientTape() as tape:
            z1=tf.matmul(x_train,w1)+b1
            a1=tf.nn.relu(z1)
            
            z2=tf.matmul(a1,w2)+b2
            a2=tf.nn.relu(z2)
            
            z3=tf.matmul(a2,w3)+b3
            y=tf.nn.softmax(z3)
            y_=tf.one_hot(y_train,depth=2)
            #交叉熵损失
            loss=tf.reduce_sum(-y_*tf.math.log(y))
            loss_all+=loss.numpy()
            grad=tape.gradient(loss,[w1,b1,w2,b2,w3,b3])
            w1.assign_sub(lr*grad[0])
            b1.assign_sub(lr*grad[1])
            w2.assign_sub(lr*grad[2])
            b2.assign_sub(lr*grad[3])     
            w3.assign_sub(lr*grad[4])
            b3.assign_sub(lr*grad[5]) 
    loss_results.append(loss_all/(i+1))  
    
    #第四步:测试模型
    correct=0
    num_all=0
    for x_test,y_test in test_db:
        z1=tf.matmul(x_test,w1)+b1
        a1=tf.nn.relu(z1)
        
        z2=tf.matmul(a1,w2)+b2
        a2=tf.nn.softmax(z2)
        
        z3=tf.matmul(a2,w3)+b3
        a3=tf.nn.softmax(z3)
        y=tf.argmax(a3,axis=1)
        y=tf.cast(y,tf.int32)
        y_=tf.cast(y_test,tf.int32)
        correct+=tf.reduce_sum(tf.cast(tf.equal(y,y_),tf.int32)).numpy()
        num_all+=x_test.shape[0]
    print(correct)
    acc.append(correct/num_all)
#%%
import matplotlib.pyplot as plt
plt.title("loss curve")
plt.xlabel("epoch")
plt.ylabel("loss")
plt.plot(loss_results,label="$loss$")
plt.show()

plt.title("acc curve")
plt.xlabel("epcoh")
plt.ylabel("acc")
plt.plot(acc,label="##acc##")
plt.show()
#%%
x,y=np.mgrid[0:10:0.5,-5:5:0.5]
test_xx=np.c_[np.ravel(x),np.ravel(y)]
test_xx=test_xx.astype(np.float32)
test_xx.dtype

z1=tf.matmul(test_xx,w1)+b1
a1=tf.nn.relu(z1)
        
z2=tf.matmul(a1,w2)+b2
a2=tf.nn.softmax(z2)
        
z3=tf.matmul(a2,w3)+b3
a3=tf.nn.softmax(z3)
test_yy=tf.argmax(a3,axis=1).numpy()
x.shape
test_yy=test_yy.reshape(x.shape)
test_yy.shape
plt.contour(x,y,test_yy,levels=[0.5],colors="r",linewidths=5)
plt.scatter(x_data[:,0],x_data[:,1],c=y_data)
plt.show

 

测试结果还需研究,有兴趣的同学可以交流,随着训练的进行,训练损失倒是不短减小,但是测试准确度却突然从90%开始下降。

 

 

 

如下图准确率随损失陡升,然后损失趋缓时开始下降,看来损失和准确率还有某种关系,可能需要调整损失函数或者学习率,懂行的朋友可以评论指导下。

 

换均方损失后,偶尔能拟合的像样,贴一个拟合的还能看出时sin曲线的图吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值