TensorFlow_Python搭建神經(jīng)網(wǎng)絡 (譯)

原文地址:http://adventuresinmachinelearning.com/python-tensorflow-tutorial/


正文:

谷歌的TensorFlow框架是近期深度學習領域的熱門話題饲嗽。這個基于高性能數(shù)據(jù)流計算圖的開源項目十分適合于深度學習。TensorFlow支持單個或多個的CPU并行計算(并且支持GPU加速),為深度學習任務提供了一個很好的方案雾消。
最新的1.0版添加了對移動端的支持荸恕,這篇TensorFlow教程將會對TensorFlow(Python版)的一些基本概念進行概述性地講解哮笆,為了能夠幫助讀者們搭建更加復雜的神經(jīng)網(wǎng)絡模型凛膏,比如說卷積神經(jīng)網(wǎng)絡神僵,自然語言模型和復發(fā)神經(jīng)網(wǎng)絡等腿宰。我們會搭建一個簡單的三層神經(jīng)網(wǎng)絡用于識別MNIST手寫數(shù)字集(這個數(shù)據(jù)可以很容易地在網(wǎng)上找到)呕诉。

注意:在閱讀此教程前請先自行了解神經(jīng)網(wǎng)絡基本知識

1.0 TensorFlow計算圖

計算圖是一種TensorFlow中的表現(xiàn)計算概念的方式,比如說一個表達式a = (b + c) * (c + 2)可以分解為如下三個式子

d = b + c
e = c + 2 
a = d * e

繪制成計算圖結果如下


簡單的計算圖

這種分解方式看起來很詭異吃度,為什么要做這樣的處理呢甩挫?因為分解之后的式子可以做并行預算(比如說d = b + c 放在cpu1里面運算,而e = c + 2 放在cpu2(或者gpu)里面運算)椿每,然后再通過a = d * e合并起來伊者,能夠大大縮短運算時間英遭。在大數(shù)據(jù)和深度學習中效果尤為明顯。通過這個方法能夠在并行運算中獲得顯著的效率提升亦渗。
我們可以從下圖中看到一個三層神經(jīng)網(wǎng)絡的運行方式(讀者們可以參看文章原地址挖诸,原圖是gif動圖):


TesnsorFlow數(shù)據(jù)流圖

在結點之間傳輸?shù)臄?shù)據(jù)流成為張量(tensors),是一種多維數(shù)組法精。這個輸入如張量的尺寸是5000×64×1多律,代表這是一個64節(jié)點的輸入層,其中包含了5000個訓練樣本搂蜓。在輸入層之后是一個隱藏層狼荞,使用relu函數(shù)作為激活函數(shù)。最后是輸出層(在上面的圖中這個也叫邏輯層)使用交叉熵作為損失函數(shù)帮碰。在每個點中都可以看到每個張量都流入Gradients模塊相味,最后通過梯度下降優(yōu)化器對模型進行反饋調(diào)整。
從圖中可以看到計算圖是如何表述神經(jīng)網(wǎng)絡中的運算的收毫。下面介紹如何用TensorFlow表示一些基本的數(shù)學運算攻走。

2.0 一個簡單的TensorFlow的例子

讓我們從這個上面那個簡單的例子開始吧。
首先介紹一下TensorFlow的變量和常量此再,代碼如下:

import tensorflow as tf
#創(chuàng)建常量
const = tf.constant(2.0,name="const")
#創(chuàng)建變量
b = tf.Variable(2.0,name="b")
c = tf.Variable(1.0,name="c")

如上所述昔搂,TensorFlow中的常量需要使用tf.constant()函數(shù)聲明,變量使用tf.Variable()函數(shù)聲明输拇。兩個函數(shù)中第一個參數(shù)是在初始化過程中會賦給常量/變量的值摘符,第二個參數(shù)是可選參數(shù),用于標記常量/變量(如果你想進行可視化能夠用到這個功能策吠,將在以后的文章中介紹)逛裤。就像在Python中一樣,TensorFlow能根據(jù)初始變量推測變量的數(shù)據(jù)類型猴抹,不過也可以自己指定數(shù)據(jù)類型带族,TensorFlow中包含了多種專屬數(shù)據(jù)類型,如tf.float32,tf.int32等等

值得注意的是蟀给,與Python中常用的變量聲明不同蝙砌,我們上面的代碼中的變量和常量(以及后面的運算、計算圖等)并沒有真正地初始化跋理,而是會在將來的初始化過程中進行初始化择克。

接下來我們將創(chuàng)建一些運算操作:

#創(chuàng)建運算
d = tf.add(b,c,name="d")
e = tf.add(c,const,name="e")
a = tf.multiply(d,e,name="a")

TensorFlow中包含了很多種類的運算,我們將在后面介紹一部分前普。上述代碼是將add和multiply運算進行了實例化肚邢。

下一步是對代碼中的所有變量和計算圖結構進行初始化(當然也可以分別初始化):

#初始化
init_op = tf.global_variables_initializer()

接下來,為了進行變量常量之間的運算拭卿,我們需要建立一個TensorFlow會話——tf.session骡湖,所有的運算都會在tf.session中運行贱纠,為了免去關閉會話的麻煩,我們可以在with語句中進行:

#創(chuàng)建會話
with tf.Session() as sess:
  #初始化
  sess.run(init_op)
  #計算
  a_out = sess.run(a)
  print("Variable a is {}".format(a_out))

注意响蕴,上述代碼中的a是什么并巍?
a = tf.multiply(d,e,name='a')
a是一個運算,不是一個變量换途,所以可以“run”懊渡。我們使用sess.run()命令對其進行運算,然后將結果復制給a_out军拟,并打印出來剃执。
注意,雖然我們在a之前定義了運算d和e懈息,但是并不需要對d和e進行運算肾档,TensorFlow會自動計算a所依賴的運算,可以使用TensorBoard功能查看這段代碼中產(chǎn)生的計算圖:


簡單的計算圖

2.1 TensorFlow的占位符

如果我們在聲明數(shù)組b的時候不知道數(shù)組b的值辫继,可以使用占位符對數(shù)組b進行聲明:

#創(chuàng)建TensorFlow變量
b = tf.placeholder(tf.float32,[None,1],name='b')

在這個聲明中怒见,我們沒有給數(shù)組b賦值,不過我們需要告訴TensorFlow數(shù)組b中包含的數(shù)據(jù)類型姑宽,這個例子中b包含的數(shù)據(jù)類型為tf.float32遣耍。第二個參數(shù)是將要傳入這個變量的數(shù)據(jù)的維度(shape),這里只指定了第二個維度炮车,第一個維度可以為任意值舵变,可以向b中傳入任意數(shù)量的一維數(shù)據(jù)。
在使用占位符之后瘦穆,調(diào)用sess.run()的代碼有所變化:

a_out = sess.run(a,feed_dict={b:np.arrange(0,10)[:,np.newaxis]})
print("Variable a is {}".format(a_out))

這里我們傳入了一個名為feed_dict的Python數(shù)組纪隙,數(shù)組的鍵是占位符的名稱,值為占位符的值扛或。

運行之后得到結果如下:

Variable a is [[  3.]
 [  6.]
 [  9.]
 [ 12.]
 [ 15.]
 [ 18.]
 [ 21.]
 [ 24.]
 [ 27.]
 [ 30.]]

下文中將利用上述知識搭建一個簡單的神經(jīng)網(wǎng)絡來識別MNIST手寫數(shù)字绵咱。

3.0 搭建簡單的神經(jīng)網(wǎng)絡模型

接下來本文將介紹如何使用TensorFlow創(chuàng)建一個簡單的三層神經(jīng)網(wǎng)絡,在以后的文章中我們將演示如何搭建卷積神經(jīng)網(wǎng)絡等結構更加復雜的神經(jīng)網(wǎng)絡模型熙兔。如果你對神經(jīng)網(wǎng)絡還不夠了解悲伶,請看作者關于神經(jīng)網(wǎng)絡的教程[http://adventuresinmachinelearning.com/neural-networks-tutorial/]
在本例中黔姜,我們將使用TensorFlow庫中自帶的MNIST數(shù)據(jù)集拢切,MNIST是一系列的28×28像素的灰階手寫數(shù)字圖像蒂萎,其中包含了55000條訓練數(shù)據(jù)秆吵、10000條測試數(shù)據(jù)以及5000條驗證數(shù)據(jù)。
首先五慈、導入數(shù)據(jù):

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./MNIST_data",one_hot=True)

one_hot參數(shù)為True代表數(shù)據(jù)集中數(shù)字的label并不是使用阿拉伯數(shù)字12345……而是使用一個向量纳寂,比如使用[0,0,0,0,1,0,0,0,0,0]表示數(shù)字4主穗,這樣能更好地用于神經(jīng)網(wǎng)絡的output層。

注意毙芜,以國內(nèi)的網(wǎng)絡是很難自動下載MNIST數(shù)據(jù)集的忽媒,所以建議自行下載MNIST數(shù)據(jù)集,放在與代碼同目錄的MNIST文件夾中腋粥,程序會自動搜索晦雨。附下載地址:http://wiki.jikexueyuan.com/project/tensorflow-zh/tutorials/mnist_download.html

3.1 初始化

使用占位符先聲明訓練數(shù)據(jù)集

learning_rate = 0.5
epochs = 10
batch_size = 100
x = tf.placeholder(tf.float32,[None,784])
y = tf.placeholder(tf.float32,[None,10])

注意輸入數(shù)據(jù)x的784個節(jié)點代表了28×28(=784)像素,而輸出數(shù)據(jù)y的10個節(jié)點代表了十個數(shù)字隘冲。

接下來設置權重w和偏置項b:

#輸入層到隱藏層
W1 = tf.Variable(tf.random_normal([784, 300], stddev=0.03), name='W1')
b1 = tf.Variable(tf.random_normal([300]), name='b1')
#隱藏層到輸出層
W2 = tf.Variable(tf.random_normal([300, 10], stddev=0.03), name='W2')
b2 = tf.Variable(tf.random_normal([10]), name='b2')

上述代碼中闹瞧,我們聲明了隱藏層和輸出層的權重,隱藏層中將會有300個節(jié)點展辞,所以W1的大小為[784,300]奥邮。我們使用均值為0,方差為0.03的正態(tài)分布的隨機數(shù)來初始化權重罗珍,b1洽腺、W2、b2也是以同樣的方式進行了初始化覆旱。

注意初始值設定可能會影響最終的結果

然后根據(jù)前面聲明的變量以及我們即將使用的激活函數(shù)(relu)來計算神經(jīng)網(wǎng)絡的輸出:

hidden_out = tf.add(tf.matmul(x, W1), b1)
hidden_out = tf.nn.relu(hidden_out)

上述代碼中蘸朋,我們首先使用tf.matmul()函數(shù)計算了矩陣x和W1的乘積,然后再加上偏置項b1扣唱,然后將計算結果使用激活函數(shù)進行非線性轉(zhuǎn)換度液,得到隱藏層的節(jié)點值。
接下來處理輸出層y:

y_ = tf.nn.softmax(tf.add(tf.matmul(hidden_out, W2), b2))

與之前的隱藏層處理不同的是画舌,這里對輸出層數(shù)據(jù)進行了SoftMax函數(shù)處理堕担,這個函數(shù)能夠?qū)㈩A測結果轉(zhuǎn)化為概率分布,方便后面進行交叉熵的計算曲聂。

接下來我們將設定用于優(yōu)化器的損失函數(shù)霹购,在這個實例中我們將選擇交叉熵作為損失函數(shù),公式如下:

交叉熵函數(shù)

在公式中朋腋,yj(i)是第j個輸出層節(jié)點的第i個訓練標簽齐疙,而yj-(i)是第j個輸出層節(jié)點的第i個預測標簽,m是每次提取的樣本數(shù)量旭咽,n是輸出的節(jié)點數(shù)贞奋,實現(xiàn)代碼如下:

y_clipped = tf.clip_by_value(y_, 1e-10, 0.9999999)
cross_entropy = -tf.reduce_mean(tf.reduce_sum(y * tf.log(y_clipped)
                         + (1 - y) * tf.log(1 - y_clipped), axis=1))

上述代碼中首先對y_進行了處理,將y_值限制在1e-10到0.99999之間穷绵,避免出現(xiàn)log(0)轿塔。
為了計算交叉熵,首先使用了TensorFlow中的tf.reduce_sum()函數(shù)計算張量的和,這里的張量指的是一個樣本中的一個節(jié)點的交叉熵:
y(i)j*log(yj_(i))+(1–y(i)j)log(1–yj_(i))
上面的y和y_clipped都是(m×10)維張量勾缭,我們首先要計算各個節(jié)點的交叉熵和揍障,即對axis=1方向求和,得到(m×1)維張量俩由,然后利用tf.reduce_mean()函數(shù)對這些張量取均值毒嫡,

接下來需要設置優(yōu)化器:

optimiser = tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimize(cross_entropy)

這里直接使用TensorFlow提供的梯度下降優(yōu)化器,優(yōu)化器中需要設置學習率(可以理解為優(yōu)化過程中的一次調(diào)整的步長)和損失函數(shù)(這里設置為交叉熵幻梯,即每次調(diào)整都向能獲取更小的交叉熵的方向進行調(diào)整)兜畸。TensorFlow中有眾多的可選優(yōu)化器,參見(https://www.tensorflow.org/api_guides/python/train

在正式開始訓練之前碘梢,還需要設置初始化函數(shù)和準確度函數(shù):

init_op = tf.global_variables_initializer()
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

上述的correct_prediction中膳叨,使用tf.equal()True對y和y_進行了對比,返回了True或者False痘系。tf.argmax()返回的是張量中最大數(shù)字的位置(在本例中其實就是1的位置菲嘴,即標簽y和y_對應的數(shù)字)。這樣correct_prediction是一個(m×1)維布爾類型張量汰翠。
可以借助此張量計算平均準確率龄坪,首先使用tf.cast()函數(shù)將布爾值轉(zhuǎn)換為tf.float32變量,然后進行平均复唤,得到準確率健田。

3.2 開始訓練

如今萬事俱備,可以開始訓練了佛纫,訓練代碼如下:

with tf.Session() as sess:
   sess.run(init_op)
   total_batch = int(len(mnist.train.labels) / batch_size)
   for epoch in range(epochs):
        avg_cost = 0
        for i in range(total_batch):
            batch_x, batch_y = mnist.train.next_batch(batch_size=batch_size)
             _, c = sess.run([optimiser, cross_entropy], 
                         feed_dict={x: batch_x, y: batch_y})
            avg_cost += c / total_batch
        print("Epoch:", (epoch + 1), "cost =", "{:.3f}".format(avg_cost))
   print(sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels}))

上述代碼的實現(xiàn)步驟如下:

  1. 初始化各運算及變量
  2. 將數(shù)據(jù)隨機分為多個小樣本(next_batch函數(shù)用于提取樣本)
  3. 對小樣本進行訓練妓局,訓練過程中輸出每一步訓練得到的交叉熵和最終的準確率。
    訓練中呈宇,我們運行了兩個操作好爬,第一個是[optimiser,cross_entropy],列表中每個操作都會運行甥啄,得到兩個操作結果存炮,但是我們并不關心優(yōu)化器返回什么結果,只想知道cross_entropy(變量c)的變化蜈漓。

最后訓練結束之后穆桂,打印出最終的準確率。
完整代碼如下融虽,有興趣的讀者可以運行一下(記住要自己下載MNIST數(shù)據(jù)集):

from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf

#導入數(shù)據(jù)
mnist = input_data.read_data_sets("./MNIST_data",one_hot=True)

#設置參數(shù)
learning_rate = 0.5#學習率
epochs = 10#訓練次數(shù)
batch_size = 100#每次取的樣本數(shù)量

#使用占位符聲明x和y
x = tf.placeholder(tf.float32,[None,784])
y = tf.placeholder(tf.float32,[None,10])

#聲明權重和偏置項

W1 = tf.Variable(tf.random_normal([784,300],stddev = 0.03),name="W1")
b1 = tf.Variable(tf.random_normal([300]),name='b1')
W2 = tf.Variable(tf.random_normal([300,10],stddev=0.03),name="W2")
b2 = tf.Variable(tf.random_normal([10]),name="b2")

#計算隱藏層
hidden_out = tf.add(tf.matmul(x,W1),b1)
hidden_out = tf.nn.relu(hidden_out)

#計算輸出值
y_ = tf.nn.softmax(tf.add(tf.matmul(hidden_out,W2),b2))

#計算交叉熵
y_clipped = tf.clip_by_value(y_,1e-10,0.9999999)
cross_entropy = -tf.reduce_mean(tf.reduce_sum(y*tf.log(y_clipped) + (1 - y)*tf.log(1-y_clipped),axis=1))

#定義優(yōu)化器
optimiser = tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimize(cross_entropy)

#設置初始化函數(shù)
init_op = tf.global_variables_initializer()

#設置準確率函數(shù)
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

#開始訓練
with tf.Session() as sess:
    sess.run(init_op)
    total_batch = int(len(mnist.train.labels)/batch_size)
    for epoch in range(epochs):#epochs=10,訓練10次
        avg_cost = 0
        for i in range(total_batch):
            batch_x ,batch_y = mnist.train.next_batch(batch_size=batch_size)
            _,c = sess.run([optimiser,cross_entropy],feed_dict={x:batch_x,
                                                                y:batch_y})
            avg_cost += c/total_batch
        print("Epoch:",(epoch+1),"cost=","{:.3f}".format(avg_cost))
    print(sess.run(accuracy,feed_dict={x:mnist.test.images,
                                       y:mnist.test.labels}))
#訓練過程中享完,優(yōu)化器會對權重和偏置項進行調(diào)整,計算accuracy時有额,TensorFlow會根據(jù)最新的w和b對x進行預測般又,得到的預測值y_再與y進行對比

運行結果:

H:\ProgramData\Anaconda3\python.exe H:/kaggle/houseprice/analysis/DeepCNN.py
Extracting ./MNIST_data\train-images-idx3-ubyte.gz
Extracting ./MNIST_data\train-labels-idx1-ubyte.gz
Extracting ./MNIST_data\t10k-images-idx3-ubyte.gz
Extracting ./MNIST_data\t10k-labels-idx1-ubyte.gz
2017-12-16 14:37:58.355471: W c:\l\tensorflow_1501918863922\work\tensorflow-1.2.1\tensorflow\core\platform\cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE instructions, but these are available on your machine and could speed up CPU computations.
2017-12-16 14:37:58.355471: W c:\l\tensorflow_1501918863922\work\tensorflow-1.2.1\tensorflow\core\platform\cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE2 instructions, but these are available on your machine and could speed up CPU computations.
2017-12-16 14:37:58.355471: W c:\l\tensorflow_1501918863922\work\tensorflow-1.2.1\tensorflow\core\platform\cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE3 instructions, but these are available on your machine and could speed up CPU computations.
2017-12-16 14:37:58.355471: W c:\l\tensorflow_1501918863922\work\tensorflow-1.2.1\tensorflow\core\platform\cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.1 instructions, but these are available on your machine and could speed up CPU computations.
2017-12-16 14:37:58.355471: W c:\l\tensorflow_1501918863922\work\tensorflow-1.2.1\tensorflow\core\platform\cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.2 instructions, but these are available on your machine and could speed up CPU computations.
2017-12-16 14:37:58.356471: W c:\l\tensorflow_1501918863922\work\tensorflow-1.2.1\tensorflow\core\platform\cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use AVX instructions, but these are available on your machine and could speed up CPU computations.
Epoch: 1 cost= 0.554
Epoch: 2 cost= 0.207
Epoch: 3 cost= 0.143
Epoch: 4 cost= 0.114
Epoch: 5 cost= 0.091
Epoch: 6 cost= 0.073
Epoch: 7 cost= 0.058
Epoch: 8 cost= 0.047
Epoch: 9 cost= 0.038
Epoch: 10 cost= 0.029
0.9776

Process finished with exit code 0

可以利用TensorBoard可視化工具查看到準確率的變化:


準確率提升過程

tensorboard內(nèi)容將在以后的文章中介紹彼绷。

文章中有些網(wǎng)址是國外網(wǎng)址,不一定打得開~~~~~~~

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末倒源,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子句狼,更是在濱河造成了極大的恐慌笋熬,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腻菇,死亡現(xiàn)場離奇詭異胳螟,居然都是意外死亡,警方通過查閱死者的電腦和手機筹吐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門糖耸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人丘薛,你說我怎么就攤上這事嘉竟。” “怎么了洋侨?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵舍扰,是天一觀的道長。 經(jīng)常有香客問我希坚,道長边苹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任裁僧,我火速辦了婚禮个束,結果婚禮上,老公的妹妹穿的比我還像新娘聊疲。我一直安慰自己茬底,他們只是感情好,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布获洲。 她就那樣靜靜地躺著桩警,像睡著了一般。 火紅的嫁衣襯著肌膚如雪昌妹。 梳的紋絲不亂的頭發(fā)上捶枢,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天,我揣著相機與錄音飞崖,去河邊找鬼烂叔。 笑死,一個胖子當著我的面吹牛固歪,可吹牛的內(nèi)容都是我干的蒜鸡。 我是一名探鬼主播胯努,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼逢防!你這毒婦竟也來了叶沛?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤忘朝,失蹤者是張志新(化名)和其女友劉穎灰署,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體局嘁,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡溉箕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了悦昵。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肴茄。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖但指,靈堂內(nèi)的尸體忽然破棺而出寡痰,到底是詐尸還是另有隱情,我是刑警寧澤棋凳,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布氓癌,位于F島的核電站,受9級特大地震影響贫橙,放射性物質(zhì)發(fā)生泄漏贪婉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一卢肃、第九天 我趴在偏房一處隱蔽的房頂上張望疲迂。 院中可真熱鬧,春花似錦莫湘、人聲如沸尤蒿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽腰池。三九已至,卻和暖如春忙芒,著一層夾襖步出監(jiān)牢的瞬間示弓,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工呵萨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留奏属,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓潮峦,卻偏偏與公主長得像囱皿,于是被迫代替她去往敵國和親勇婴。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容