CS20si 第2課: TensorFlow運(yùn)算

第2課: TensorFlow運(yùn)算

CS20si課程資料和代碼Github地址

注意:運(yùn)算的介紹可能比較枯燥代兵,但是是基礎(chǔ)芭届,之后會(huì)更有趣颇玷。

1. TensorBoard

TensorFlow不僅僅是一個(gè)軟件包去件,它是一個(gè)包括TensorFlow坡椒,TensorBoard和Tensor Serving的套件。為了充分利用TensorFlow尤溜,我們應(yīng)該知道如何將它們結(jié)合起來使用倔叼,所以首先我們來了解TensorBoard。

Tensor是TensorFlow安裝程序自帶的圖形可視化工具宫莱,用Google自己的話說:

“你使用TensorFlow進(jìn)行的例如訓(xùn)練深度神經(jīng)網(wǎng)絡(luò)的計(jì)算可能會(huì)非常復(fù)雜和難懂丈攒。為了更簡單的理解,調(diào)試和優(yōu)化TensorFlow程序授霸,我們提供了一個(gè)名叫TensorBoard的可視化套件巡验。”

TensorBoard配置好后绝葡,大概是這個(gè)樣子:


image

當(dāng)用戶在一個(gè)激活了TensorBoard的TensorFlow程序上進(jìn)行運(yùn)算時(shí)深碱,這些運(yùn)算都會(huì)被導(dǎo)出到事件日志(event log)文件中。TensorBoard能夠?qū)⑦@些事件日志可視化以便可以深入了解模型的計(jì)算圖和它的運(yùn)行時(shí)行為藏畅。越早和越經(jīng)常的使用TensorBoard會(huì)使TensorFlow上的工作更有趣且更有成效敷硅。

接下來讓我們編寫第一個(gè)TensorFlow程序,然后使用TensorBoard可視化程序的計(jì)算圖愉阎。為了使用TensorBoard進(jìn)行可視化绞蹦,我們需要寫入程序的事件日志。

import tensorflow as tf
a = tf.constant(2)
b = tf.constant(3)
x = tf.add(a, b)
writer = tf.summary.FileWriter([logdir], [graph])
with tf.Session() as sess:
    print(sess.run(x))
writer.close()

[graph]是程序的計(jì)算圖榜旦,你可以用tf.get_default_graph()獲得程序默認(rèn)的計(jì)算圖幽七,也可以用sess.graph獲得Session處理的計(jì)算圖。(當(dāng)然你需要?jiǎng)?chuàng)建一個(gè)Session)不管怎樣溅呢,確定在創(chuàng)建writer之前你已經(jīng)定義了完整的計(jì)算圖澡屡,不然TensorBoard可視化的結(jié)果將會(huì)不完整。
[logdir]是你希望存儲(chǔ)事件日志的目錄咐旧。

接下來驶鹉,打開終端,先運(yùn)行剛才的Tensorflow程序铣墨,再以剛才寫入的日志目錄作為參數(shù)運(yùn)行TensorBoard室埋。

$ python3 [my_program.py] 
$ tensorboard --logdir [logdir] --port [port]

最后打開瀏覽器,輸入http://localhost:[port]/(端口號(hào)自己選擇),你將會(huì)看到TensorBoard頁面姚淆。點(diǎn)擊Graph標(biāo)簽?zāi)憧梢圆榭从?jì)算圖中有3個(gè)節(jié)點(diǎn):2個(gè)常量運(yùn)算和一個(gè)add運(yùn)算孕蝉。

image

“Const”和“Const_1"代表a和b,節(jié)點(diǎn)”Add“對(duì)應(yīng)x腌逢。我們可以在代碼中給a降淮,b和x命名讓TensorBoard了解這些運(yùn)算的名字。

a = tf.constant(2, name="a")
b = tf.constant(3, name="b")
x = tf.add(a, b, name="add")

現(xiàn)在如果你再次運(yùn)行程序和TensorBoard搏讶,你會(huì)看到:

image

計(jì)算圖自己定義了運(yùn)算和運(yùn)算間依賴關(guān)系骤肛,只要簡單的點(diǎn)擊節(jié)點(diǎn)就可以查看值和節(jié)點(diǎn)類型。

image

Note:如果你運(yùn)行了程序很多次窍蓝,在日志目錄會(huì)有多個(gè)事件日志文件。TensorBoard只會(huì)顯示最后一個(gè)計(jì)算圖并且警告有多個(gè)日志文件繁成,如果想避免警告就刪除不需要的日志文件吓笙。

當(dāng)然,TensorBoard能做的遠(yuǎn)遠(yuǎn)不止于可視化計(jì)算圖巾腕,這里我們將介紹它最重要的一些功能面睛。

2. 常量運(yùn)算(Constant op)

創(chuàng)建常量運(yùn)算很直接。

tf.constant(value, dtype=None, shape=None, name='Const', verify_shape=False)
# constant of 1d tensor (vector)
a = tf.constant([2, 2], name="vector")
# constant of 2x2 tensor (matrix)
b = tf.constant([[0, 1], [2, 3]], name="matrix")

你可以用指定值初始化一個(gè)特定維度的tensor尊搬,就像Numpy一樣叁鉴。

tf.zeros(shape, dtype=tf.float32, name=None)
# create a tensor of shape and all elements are zeros
tf.zeros([2, 3], tf.int32) ==> [[0, 0, 0], [0, 0, 0]]

tf.zeros_like(input_tensor, dtype=None, name=None, optimize=True)
# create a tensor of shape and type (unless type is specified) as the input_tensor but all elements are zeros.
# input_tensor [[0, 1], [2, 3], [4, 5]]
tf.zeros_like(input_tensor) ==> [[0, 0], [0, 0], [0, 0]]

tf.ones(shape, dtype=tf.float32, name=None)
# create a tensor of shape and all elements are ones
tf.ones([2, 3], tf.int32) ==> [[1, 1, 1], [1, 1, 1]]

tf.ones_like(input_tensor, dtype=None, name=None, optimize=True)
# create a tensor of shape and type (unless type is specified) as the input_tensor but all elements are ones.
# input_tensor is [[0, 1], [2, 3], [4, 5]]
tf.ones_like(input_tensor) ==> [[1, 1], [1, 1], [1, 1]]

tf.fill(dims, value, name=None) 
# create a tensor filled with a scalar value.
tf.fill([2, 3], 8) ==> [[8, 8, 8], [8, 8, 8]]

你可以創(chuàng)建一個(gè)常量序列

tf.lin_space(start, stop, num, name=None)
# create a sequence of num evenly-spaced values are generated beginning at start. If num > 1, the values in the sequence increase by (stop - start) / (num - 1), so that the last one is exactly stop.
# comparable to but slightly different from numpy.linspace
tf.lin_space(10.0, 13.0, 4, name="linspace") ==> [10.0 11.0 12.0 13.0]

tf.range([start], limit=None, delta=1, dtype=None, name='range')
# create a sequence of numbers that begins at start and extends by increments of delta up to but not including limit
# slight different from range in Python
tf.range(3, 18, 3) ==> [3, 6, 9, 12, 15]
tf.range(3, 1, -0.5) ==> [3, 2.5, 2, 1.5]
tf.range(5) ==> [0, 1, 2, 3, 4]

需要注意的是和Numpy的序列不同,TensorFlow的序列是不能迭代的佛寿。

for _ in np.linspace(0, 10, 4): # OK
for _ in tf.linspace(0.0, 10.0, 4): # TypeError: 'Tensor' object is not iterable.

for _ in range(4): # OK
for _ in tf.range(4): # TypeError: 'Tensor' object is not iterable.

你也可以創(chuàng)建服從指定分布的隨機(jī)常量幌墓。

tf.random_normal
tf.truncated_normal
tf.random_uniform
tf.random_shuffle
tf.random_crop
tf.multinomial
tf.random_gamma
tf.set_random_seed

3. 數(shù)學(xué)運(yùn)算

TensorFlow的數(shù)學(xué)運(yùn)算符很標(biāo)準(zhǔn),你可以在這里找到完整的列表冀泻。

  • TensorFlow大量的除法運(yùn)算

TensorFlow至少支持7種除法運(yùn)算常侣,做著或多或少一樣的事情:tf.div, tf.divide, tf.truediv, tf.floordiv, tf.realdiv, tf.truncateddiv, tf.floor_div。創(chuàng)建這些運(yùn)算的人一定非常喜歡除法弹渔。胳施。。

a = tf.constant([2, 2], name='a')
b = tf.constant([[0, 1], [2, 3]], name='b')
with tf.Session() as sess:
    print(sess.run(tf.div(b, a)))             ? [[0 0] [1 1]]
    print(sess.run(tf.divide(b, a)))          ? [[0. 0.5] [1. 1.5]]
    print(sess.run(tf.truediv(b, a)))         ? [[0. 0.5] [1. 1.5]]
    print(sess.run(tf.floordiv(b, a)))        ? [[0 0] [1 1]]
    print(sess.run(tf.realdiv(b, a)))         ? # Error: only works for real values
    print(sess.run(tf.truncatediv(b, a)))     ? [[0 0] [1 1]]
    print(sess.run(tf.floor_div(b, a)))       ? [[0 0] [1 1]]
  • tf.add_n

將多個(gè)tensor相加肢专。

tf.add_n([a, b, b])  => equivalent to a + b + b
  • 點(diǎn)積

注意tf.matmul不是點(diǎn)積舞肆,而是使用tf.tensordot

a = tf.constant([10, 20], name='a')
b = tf.constant([2, 3], name='b')
with tf.Session() as sess:
    print(sess.run(tf.multiply(a, b)))           ? [20 60] # element-wise multiplication
    print(sess.run(tf.tensordot(a, b, 1)))       ? 80

下面是Python中的運(yùn)算博杖,摘自Fundamentals of DeepLearning椿胯。

image

4. 數(shù)據(jù)類型

  • Python原生類型

TensorFlow兼容Python的原生數(shù)據(jù)類型,例如:boolean欧募,integer压状,float和string等。單獨(dú)的值轉(zhuǎn)換為0維tensor(標(biāo)量,scalar)种冬,列表轉(zhuǎn)換為1維tensor(向量镣丑,vector),列表的列表轉(zhuǎn)換為2維tensor(矩陣娱两,matrix)莺匠,以此類推。

t_0 = 19 # Treated as a 0-d tensor, or "scalar" 
tf.zeros_like(t_0)                   # ==> 0
tf.ones_like(t_0)                    # ==> 1

t_1 = [b"apple", b"peach", b"grape"] # treated as a 1-d tensor, or "vector"
tf.zeros_like(t_1)                   # ==> [b'' b'' b'']
tf.ones_like(t_1)                    # ==> TypeError

t_2 = [[True, False, False],
       [False, False, True],
       [False, True, False]]         # treated as a 2-d tensor, or "matrix"

tf.zeros_like(t_2)                   # ==> 3x3 tensor, all elements are False
tf.ones_like(t_2)                    # ==> 3x3 tensor, all elements are True
  • TensorFlow原生類型

TensorFlow也有自己的原生類型:tf.int32, tf.float32,還有更令人興奮的類型:tf.bfloat, tf.complex, tf.quint十兢,完整的類型列表在這里趣竣。

  • Numpy數(shù)據(jù)類型

到此為止,你可能已經(jīng)注意到Numpy和TensorFlow數(shù)據(jù)類型的相似性旱物。TensorFlow被設(shè)計(jì)為和Numpy無縫集成遥缕,這個(gè)軟件包已經(jīng)成為數(shù)據(jù)科學(xué)的通用語。

TensorFlow的數(shù)據(jù)類型是基于Numpy的宵呛,實(shí)際上np.int32 == tf.int32返回True单匣。你可以將Numpy類型傳給TensorFlow函數(shù)。

tf.ones([2, 2], np.float32) ==> [[1.0 1.0], [1.0 1.0]]

5. 變量

  • 創(chuàng)建變量

使用tf.Variable創(chuàng)建變量宝穗,應(yīng)該注意的是tf.constant是小寫的而tf.Variable是大寫的户秤,這是因?yàn)?strong>tf.constant是一個(gè)運(yùn)算而tf.Variable是一個(gè)含有多個(gè)運(yùn)算的類。

x = tf.Variable(...) 
x.initializer # init 
x.value() # read op 
x.assign(...) # write op 
x.assign_add(...) 
# and more

傳統(tǒng)的創(chuàng)建變量方式為

tf.Variable(<initial-value>, name=<optional-name>)
s = tf.Variable(2, name="scalar") 
m = tf.Variable([[0, 1], [2, 3]], name="matrix") 
W = tf.Variable(tf.zeros([784,10]))

TensorFlow推薦使用tf.get_variable來創(chuàng)建變量逮矛,這樣有利于變量的共享鸡号。

tf.get_variable(
    name,
    shape=None,
    dtype=None,
    initializer=None,
    regularizer=None,
    trainable=True,
    collections=None,
    caching_device=None,
    partitioner=None,
    validate_shape=True,
    use_resource=None,
    custom_getter=None,
    constraint=None
)

s = tf.get_variable("scalar", initializer=tf.constant(2)) 
m = tf.get_variable("matrix", initializer=tf.constant([[0, 1], [2, 3]]))
W = tf.get_variable("big_matrix", shape=(784, 10), initializer=tf.zeros_initializer())
  • 初始化變量

你必須在使用變量之前初始化它們,否則將會(huì)報(bào)FailedPreconditionError: Attempting to use uninitialized value的錯(cuò)誤须鼎。想查看所有沒初始化的變量鲸伴,你可以將它們打印出來:

print(session.run(tf.report_uninitialized_variables()))

簡單的將所有變量一次性初始化的方法為:

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

在這種情況下你用tf.Session.run()獲得的是一個(gè)initializer而不是之前的tensor運(yùn)算。

如果只初始化一部分變量莉兰,你可以使用tf.variables_initializer()

with tf.Session() as sess:
    sess.run(tf.variables_initializer([a, b]))

你也可以用tf.Variable.initializer()一個(gè)個(gè)的初始化變量:

with tf.Session() as sess:
    sess.run(W.initializer)

還有一種初始化變量方式是從一個(gè)文件讀取挑围,我們會(huì)在后面的課程提到。

  • 計(jì)算(Evaluate)變量的值

和tensor類似糖荒,可以用session獲取變量的值杉辙。

# V is a 784 x 10 variable of random values
V = tf.get_variable("normal_matrix", shape=(784, 10), 
                     initializer=tf.truncated_normal_initializer())

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print(sess.run(V))

也可以通過tf.Variable.eval()來獲取變量的值。

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print(V.eval())
  • 給變量賦值

我們可以通過tf.Variable.assign()來給變量賦值捶朵。

W = tf.Variable(10)
W.assign(100)
with tf.Session() as sess:
    sess.run(W.initializer)
    print(W.eval()) # >> 10

為什么輸出的10而不是100蜘矢?W.assign(100)并沒有給W賦值而是創(chuàng)建了一個(gè)assign運(yùn)算,要想使這個(gè)運(yùn)算生效我們可以在session中運(yùn)行這個(gè)運(yùn)算综看。

W = tf.Variable(10)

assign_op = W.assign(100)
with tf.Session() as sess:
    sess.run(assign_op)
    print(W.eval()) # >> 100

注意這次我們沒有初始化W品腹,因?yàn)閍ssign為我們做了。實(shí)際上initializer就是一個(gè)assign運(yùn)算红碑,它用初始值來初始化變量舞吭。

# in the source code
self._initializer_op = state_ops.assign(self._variable, self._initial_value, validate_shape=validate_shape).op

為了簡化變量的加減運(yùn)算泡垃,TensorFlow提供了tf.Variable.assign_add()tf.Variable.assign_sub()方法。不同于tf.Variable.assign()羡鸥,這兩個(gè)方法不會(huì)初始化變量蔑穴,因?yàn)樗鼈円蕾囎兞康某跏贾怠?/p>

W = tf.Variable(10)

with tf.Session() as sess:
    sess.run(W.initializer)
    print(sess.run(W.assign_add(10))) # >> 20
    print(sess.run(W.assign_sub(2)))  # >> 18

因?yàn)門ensorFlow的Session們維護(hù)著各自的值,每個(gè)Session擁有變量屬于Session自己的當(dāng)前值惧浴。

W = tf.Variable(10)
sess1 = tf.Session()
sess2 = tf.Session()
sess1.run(W.initializer)
sess2.run(W.initializer)
print(sess1.run(W.assign_add(10)))      # >> 20
print(sess2.run(W.assign_sub(2)))       # >> 8
print(sess1.run(W.assign_add(100)))     # >> 120
print(sess2.run(W.assign_sub(50)))      # >> -42
sess1.close()
sess2.close()

當(dāng)你有一個(gè)依賴其它變量的變量時(shí)存和,假設(shè)你聲明了U = W * 2

# W is a random 700 x 10 tensor
W = tf.Variable(tf.truncated_normal([700, 10]))
U = tf.Variable(W * 2)

在這種情況下,你應(yīng)該使用initialized_value()方法去保證在使用W的值去初始化U之前W已經(jīng)被初始化衷旅。

U = tf.Variable(W.initialized_value() * 2)

6. 交互Session(Interactive Session)

你有時(shí)候會(huì)看到InteractiveSession代替Session捐腿,它們之間唯一的不同是InteractiveSession會(huì)把自己設(shè)置為默認(rèn)的Session,這樣你就可以直接調(diào)用run()eval()方法柿顶。這樣方便了在Shell和IPython Notebook中使用茄袖,但是當(dāng)有多個(gè)Session時(shí)使問題變得復(fù)雜。

sess = tf.InteractiveSession()
a = tf.constant(5.0)
b = tf.constant(6.0)
c = a * b
print(c.eval()) # we can use 'c.eval()' without explicitly stating a session
sess.close()

tf.get_default_session()方法返回當(dāng)前線程的默認(rèn)Session嘁锯。

7. 控制依賴關(guān)系(Control Dependencies)

有時(shí)候绞佩,我們擁有兩個(gè)或者更多獨(dú)立的運(yùn)算,而我們希望指定哪些運(yùn)算應(yīng)該先運(yùn)行猪钮。這個(gè)情況下,我們可以使用tf.Graph.control_dependencies([control_inputs])胆建。

# your graph g have 5 ops: a, b, c, d, e
with g.control_dependencies([a, b, c]):
    # `d` and `e` will only run after `a`, `b`, and `c` have executed.
    d = ...
    e = …

8. 導(dǎo)入數(shù)據(jù)

8.1 傳統(tǒng)的方法: placehoderfeed_dict

TensorFlow 程序一般由兩個(gè)階段:

  1. 組裝一個(gè)計(jì)算圖
  2. 用Session在計(jì)算圖中執(zhí)行運(yùn)算和評(píng)估變量

我們可以在不管計(jì)算所需的數(shù)值的情況下組裝計(jì)算圖烤低,這個(gè)在不知道輸入數(shù)據(jù)的情況下定義函數(shù)是一樣的。

在計(jì)算圖組裝完成后笆载,我們可以用placeholder將自己的數(shù)據(jù)灌入計(jì)算圖中:

tf.placeholder(dtype, shape=None, name=None)
a = tf.placeholder(tf.float32, shape=[3]) # a is placeholder for a vector of 3 elements
b = tf.constant([5, 5, 5], tf.float32)
c = a + b # use the placeholder as you would any tensor
with tf.Session() as sess:
    print(sess.run(c)) 

當(dāng)我們嘗試通過Session計(jì)算c的值時(shí)扑馁,我們將會(huì)獲得一個(gè)錯(cuò)誤,因?yàn)槲覀冃枰@得a的值凉驻。我們可以通過feed_dict來向placeholder灌數(shù)據(jù)腻要,它是一個(gè)字典。

with tf.Session() as sess:
    # compute the value of c given the value of a is [1, 2, 3]
    print(sess.run(c, {a: [1, 2, 3]}))      # [6. 7. 8.]

這時(shí)我們?cè)俨榭碩ensorBoard涝登,計(jì)算圖如下:

image

我們可以向placeholder中多次灌入不同的值雄家。

with tf.Session() as sess:
    for a_value in list_of_a_values:
        print(sess.run(c, {a: a_value}))

你也可以向不是placeholder的tensor灌入數(shù)值,所有的tensor都是可以灌值的胀滚,可以用tf.Graph.is_feedable(tensor)方法查看一個(gè)tensor是否是可以灌值的趟济。

a = tf.add(2, 5)
b = tf.multiply(a, 3)

with tf.Session() as sess:
    print(sess.run(b))                      # >> 21
    # compute the value of b given the value of a is 15
    print(sess.run(b, feed_dict={a: 15}))           # >> 45

feed_dict對(duì)測(cè)試你的模型非常有用,當(dāng)你有一個(gè)很大的計(jì)算圖但只想測(cè)試其中某一塊時(shí)咽笼,你可以灌入假值來避免在不必要的運(yùn)算上浪費(fèi)時(shí)間顷编。

8.2 新的方法:tf.data

這個(gè)方法需要配合例子來講,所以我們會(huì)在下一課線性和邏輯回歸中涉及剑刑。

9.lazy loading的陷阱

現(xiàn)在TensorFlow中最常見的不是bug的bug叫做“l(fā)azy loading”媳纬。Lazy loading是一種設(shè)計(jì)模式,即在你要使用一個(gè)對(duì)象時(shí)才初始化對(duì)象。在TensorFlow的場(chǎng)景中钮惠,它的含義是在要執(zhí)行一個(gè)運(yùn)算時(shí)才創(chuàng)建這個(gè)運(yùn)算茅糜。例如:

x = tf.Variable(10, name='x')
y = tf.Variable(20, name='y')

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    writer = tf.summary.FileWriter('graphs/lazy_loading', sess.graph)
    for _ in range(10):
        sess.run(tf.add(x, y))
    print(tf.get_default_graph().as_graph_def()) 
    writer.close()

現(xiàn)在我們看看TensorBoard:

image

打印計(jì)算圖的定義:

print(tf.get_default_graph().as_graph_def())

得到如下結(jié)果:

node {
  name: "Add_1"
  op: "Add"
  input: "x_1/read"
  input: "y_1/read"
  attr {
    key: "T"
    value {
      type: DT_INT32
    }
  }
}
…
…
…
node {
  name: "Add_10"
  op: "Add"
  ...
}

你可能回想:“這很愚蠢,為什么我要在一個(gè)相同的值上計(jì)算兩次萌腿?”限匣,然后認(rèn)為這是一個(gè)bug。這種情況會(huì)經(jīng)常發(fā)生毁菱,比如在你想在訓(xùn)練集的每個(gè)batch上計(jì)算損失函數(shù)或做預(yù)測(cè)時(shí)米死,如果你不注意,可能會(huì)添加巨量的無用運(yùn)算贮庞。

Note在翻譯這篇文章時(shí)峦筒,譯者用TensorFlow 1.8版本做了實(shí)驗(yàn),這個(gè)bug應(yīng)該沒有了窗慎。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末物喷,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子遮斥,更是在濱河造成了極大的恐慌峦失,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件术吗,死亡現(xiàn)場(chǎng)離奇詭異尉辑,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)较屿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門隧魄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人隘蝎,你說我怎么就攤上這事购啄。” “怎么了嘱么?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵狮含,是天一觀的道長。 經(jīng)常有香客問我曼振,道長辉川,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任拴测,我火速辦了婚禮乓旗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘集索。我一直安慰自己屿愚,他們只是感情好汇跨,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著妆距,像睡著了一般穷遂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上娱据,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天蚪黑,我揣著相機(jī)與錄音,去河邊找鬼中剩。 笑死忌穿,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的结啼。 我是一名探鬼主播掠剑,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼郊愧!你這毒婦竟也來了朴译?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤属铁,失蹤者是張志新(化名)和其女友劉穎眠寿,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體焦蘑,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡澜公,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了喇肋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡迹辐,死狀恐怖蝶防,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情明吩,我是刑警寧澤间学,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站印荔,受9級(jí)特大地震影響低葫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜仍律,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一嘿悬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧水泉,春花似錦善涨、人聲如沸窒盐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蟹漓。三九已至,卻和暖如春源内,著一層夾襖步出監(jiān)牢的瞬間葡粒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來泰國打工膜钓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嗽交,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓呻此,卻偏偏與公主長得像轮纫,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子焚鲜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

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