代碼:
# coding:utf-8
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
data=[]
label=[]
np.random.seed(0)
##隨機產生訓練集
for i in range(150):
x1=np.random.uniform(-1,1)
x2=np.random.uniform(0,2)
if x1**2+ x2**2<=1:
data.append([np.random.normal(x1,0.1),np.random.normal(x2,0.1)])
label.append(0)
else:
data.append([np.random.normal(x1,0.1),np.random.normal(x2,0.1)])
label.append(1)
# -1就是讓系統根據元素數和已知行或列推算出剩下的列或者行,-1就是模糊控制,(-1,2)
# 就是固定兩列,行不知道
data=np.hstack(data).reshape(-1,2)
label=np.hstack(label).reshape(-1,1)
plt.scatter(data[ : ,0], data[ :, 1], c=label, cmap="RdBu", vmin=-.2, vmax=1.2, edgecolor="white")
plt.show()
#知識點:
#tf.add_to_collection:把變量放入一個集合,把很多變量變成一個列表
#tf.get_collection:從一個結合中取出全部變量,是一個列表
#tf.add_n:把一個列表的東西都依次加起來
def get_weight(shape,lambda1):
var=tf.Variable(tf.random_normal(shape),dtype=tf.float32)
tf.add_to_collection('losses',tf.contrib.layers.l2_regularizer(lambda1)(var))
return var
x=tf.placeholder(tf.float32,shape=(None,2))
y_=tf.placeholder(tf.float32,shape=(None,1))
sample_size=len(data)
#定義的神經結構每一層的節點個數
layer_dimension=[2,10,5,3,1]
n_layers=len(layer_dimension)
cur_layer=x
#輸入層
in_dimension=layer_dimension[0]
#向前遍歷
for i in range(1,n_layers):
out_dimension=layer_dimension[i]
weight=get_weight([in_dimension,out_dimension],0.03)
bias=tf.Variable(tf.constant(0.1,shape=[out_dimension]))
##tf.nn.elu是激活函數
cur_layer=tf.nn.elu(tf.matmul(cur_layer,weight)+bias)
in_dimension=layer_dimension[i]
y=cur_layer
mse_loss=tf.reduce_sum(tf.pow(y_-y,2))/sample_size
tf.add_to_collection('losses',mse_loss)
loss=tf.add_n(tf.get_collection('losses'))
train_op=tf.train.AdamOptimizer(0.001).minimize(mse_loss)
TRAINING_STEPS=40000
with tf.Session() as sess:
tf.initialize_all_variables().run()
for i in range(TRAINING_STEPS):
sess.run(train_op,feed_dict={x:data,y_:label})
if(i%2000)==0:
print("After %d steps, mse_loss:%f" % (i,sess.run(mse_loss,feed_dict={x:data,y_:label})))
#畫出訓練後的分割函數
#mgrid函數產生兩個240×241的數組:-1.2到1.2每隔0.01取一個數共240個
xx,yy= np.mgrid[-1.2:1.2:.01,-0.2:2.2:.01]
##np.c_應該是合併兩個數組
grid=np.c_[xx.ravel(),yy.ravel()]
probs=sess.run(y,feed_dict={x:grid})
probs=probs.reshape(xx.shape)
plt.scatter(data[:,0],data[:,1],c=label,cmap="RdBu",vmin=-.2,vmax=1.2,edgecolors="white")
plt.contour(xx,yy,probs,levels=[.5],cmap="Greys",vmin=0,vmax=.1)
plt.show()
"""
#帶正則化參數訓練
train_op=tf.train.AdamOptimizer(0.001).minimize(loss)
TRAINING_STEPS=40000
with tf.Session() as sess:
tf.initialize_all_variables().run()
for i in range(TRAINING_STEPS):
sess.run(train_op,feed_dict={x:data,y_:label})
if i%2000==0:
print("After %d steps, mse_loss:%f"(i, sess.run(loss, feed_dict={x: data, y_: label})))
xx, yy = np.mgrid[-1.2:1.2:.01, -0.2:2.2:.01]
grid = np.c_[xx.ravel(), yy.ravel()]
probs = sess.run(y, feed_dict={x: grid})
probs = probs.reshape(xx.shape)
plt.scatter(data[:,0],data[:,1],c=label,cmap="RdBu",vmin=-.2,vmax=1.2,edgecolors="white")
plt.contour(xx,yy,probs,levels=[.5],cmap="Greys",vmin=0,vmax=.1)
plt.show()
"""
結果:可視化數據:
這時我們可以看到出現裏過擬合現象,這時候我們就需要用正則化來防止過擬合。。
正則化後結果:
代碼所涉及到的知識點補充:
tensorflow中的激活函數:
tf.nn.relu()
tf.nn.relu6()
tf.nn.sigmoid()
tf.nn.tanh()
tf.nn.elu()
tf.nn.bias_add()
tf.nn.crelu()
tf.nn.relu6()
tf.nn.softplus()
tf.nn.softsign()
tf.nn.dropout()
注意:所有激活函數 輸入 和 輸出 的維度是一樣的
relu()函數:
leaky relu函數:
reLU 中當 x<0 時,函數值爲 0。而 Leaky ReLU 則是給出一個很小的負數梯度值,比如 0.01。
sigmod函數:
tanh函數:
tensorflow中的正則化方法:
tensorflow
中對參數使用正則項分爲兩步:
1. 創建一個正則方法(函數/對象)
2. 將這個正則方法(函數/對象),應用到參數上
創建正則化方法:
tf.contrib.layers.l1_regularizer(scale, scope=None)
返回一個用來執行L1
正則化的函數,函數的簽名是func(weights)
.
參數:
- scale: 正則項的係數.
- scope: 可選的
scope name
tf.contrib.layers.l2_regularizer(scale, scope=None)
返回一個執行L2
正則化的函數.
tf.contrib.layers.sum_regularizer(regularizer_list, scope=None)
返回一個可以執行多種(個)正則化的函數.意思是,創建一個正則化方法,這個方法是多個正則化方法的混合體.
參數:
regularizer_list: regulizer的列表
可以看到上面把正則化分成裏L1正則化和L2正則化:那兩者有何區別呢?
使用L1正則化的模型建叫做Lasso迴歸,使用L2正則化的模型叫做Ridge迴歸(嶺迴歸)
下圖是Python中Lasso迴歸的損失函數,式中加號後面一項α||w||1即爲L1正則化項:
下圖是Python中Ridge迴歸的損失函數,式中加號後面一項α||w||22即爲L2正則化項:
可以看到區別如下:
- L1正則化是指權值向量w中各個元素的絕對值之和,通常表示爲||w||1
- L2正則化是指權值向量w中各個元素的平方和然後再求平方根(可以看到Ridge迴歸的L2正則化項有平方符號),通常表示爲||w||2
- L1正則化可以產生稀疏權值矩陣,即產生一個稀疏模型,可以用於特徵選擇
- L2正則化可以防止模型過擬合(overfitting);一定程度上,L1也可以防止過擬合
將正則化方法應用到參數上:
tf.contrib.layers.apply_regularization(regularizer, weights_list=None)
返回一個標量Tensor
,同時,這個標量Tensor
也會保存到GraphKeys.REGULARIZATION_LOSSES
中.這個Tensor
保存了計算正則項損失的方法.
參數:
- regularizer:就是我們上一步創建的正則化方法
- weights_list: 想要執行正則化方法的參數列表,如果爲
None
的話,就取GraphKeys.WEIGHTS
中的weights
.
tensorflow
中的Tensor
是保存了計算這個值的路徑(方法),當我們run的時候,tensorflow
後端就通過路徑計算出Tensor
對應的值注意:如果是自己手動定義weight
的話,需要手動將weight
保存到GraphKeys.WEIGHTS
中,但是如果使用layer
的話,就不用這麼麻煩了,別人已經幫你考慮好了.(最好自己驗證一下tf.GraphKeys.WEIGHTS
中是否包含了所有的weights
,防止被坑)。。還有在使用tf.get_variable()
和tf.variable_scope()
的時候,你會發現,它們倆中有regularizer
形參.如果傳入這個參數的話,那麼variable_scope
內的weights
的正則化損失,或者weights
的正則化損失就會被添加到GraphKeys.REGULARIZATION_LOSSES
中。。。。。。。