量子+AI應用:量子計算與神經網絡

概述

神經網絡是當下計算應用中發展最快,使用最廣的機器學習算法。然而,由于傳統的神經網絡只能使用單個網絡來存儲許多算法模式,隨著應用不斷復雜化導致網絡結構不斷擴大,存儲性能瓶頸已逐漸凸顯。

而量子神經網絡是根據量子計算機的特性設計的神經網絡。研究者們根據量子計算機所提供的基本計算單元(即量子邏輯門)進行量子線路設計,以實現神經網絡的計算。通過在量子計算機或量子器件的基礎上構造神經網絡,利用量子計算超高速、超并行、指數級容量的特點,來改進神經網絡的結構和性能,可以使用許多網絡來存儲許多算法模式。

1. 神經網絡

1.1 什么是神經網絡

神經網絡,也稱為人工神經網絡 (ANN) ,是機器學習的子集,并且是深度學習算法的核心。其名稱和結構是受人類大腦的啟發,模仿了生物神經元信號相互傳遞的方式,以數學和物理方法及從信息處理的角度對人腦生物神經網絡進行抽象并建立起來的某種簡化模型。

人工神經網絡 (ANN) 由節點層組成,包含一個輸入層、一個或多個隱藏層和一個輸出層。每個節點也稱為一個人工神經元,人工神經元是神經網絡的基本元素,它們連接到另一個節點,具有相關的權重和閾值。如果任何單個節點的輸出高于指定的閾值,那么該節點將被激活,并將數據發送到網絡的下一層。否則,不會將數據傳遞到網絡的下一層。下圖是一個人工神經網絡的構造圖,每一個圓代表著一個神經元,他們連接起來構成了一個網絡。

圖片

神經網絡反映人類大腦的行為,允許計算機程序識別模式,以及解決人工智能、機器學習和深度學習領域的常見問題。其依賴于訓練數據隨時間的推移不斷學習并提高其準確性。然而,一旦這些學習算法的準確性經過調優,它們便是計算科學和人工智能中的強大工具,我們可以快速地對數據進行分類。與由人類專家進行的人工識別相比,語音識別或圖像識別任務可能僅需要幾分鐘而不是數小時。最著名的神經網絡之一是 Google 的搜索算法。

1.2 人工神經元

人工神經元的工作原理,如下圖所示

圖片

上面的x是神經元的輸入,相當于樹突接收的多個外部刺激。w是每個輸入對應的權重,代表了每個特征的重要程度,它對應于每個輸入特征,影響著每個輸入x的刺激強度。假設只有3個特征,那么x就可以用

。b表示閾值,用來影響預測結果。z就是預測結果。

所以有:

上面這個式子在業內我們稱之為邏輯回歸。在實際的神經網絡中,我們不能直接用邏輯回歸,必須要在邏輯回歸外面再套上一個函數,這個函數我們就稱它為激活函數。

如在1943年,McCulloch和Pitts將上圖的神經元結構用一種簡單的模型進行了表示,構成了一種人工神經元模型,也就是現在經常用到的“M-P神經元模型”,如下圖所示:

圖片

從上圖M-P神經元模型可以看出,神經元的輸出為

其中θ為神經元的激活閾值,函數f(?)也被稱為是激活函數。

1.3 神經網絡的類型

1.3.1 感知器

感知器是最古老的神經網絡,由 Frank Rosenblatt 于 1958 年創建。它有一個神經元,是神經網絡最簡單的形式:

上圖中,x是神經元的輸入,代表著輸入特征向量, Output是預測結果。

1.3.2 前饋神經網絡(FNN)

前饋神經網絡(Feedforward Neural Network,FNN)是最早發明的簡單人工神經網絡,由輸入層、一個或多個隱藏層以及輸出層組成。在前饋神經網絡中,各神經元分別屬于不同的層。每一層的神經元可以接收前一層神經元的信號,并產生信號輸出到下一層。第0層叫輸入層,最后一層叫輸出層,其它中間層叫做隱藏層。整個網絡中無反饋,信號從輸入層向輸出層單向傳播,可用一個有向無環圖表示。

1.3.3 卷積神經網絡 (CNN)

卷積神經網絡(CNN)是一類包含卷積計算且具有深度結構的前饋神經網絡,是深度學習的代表算法之一。卷積神經網絡具有表征學習能力,能夠按其階層結構對輸入信息進行平移不變分類,通常用于圖像識別、模式識別和/或計算機視覺。這些網絡利用線性代數的原理(特別是矩陣乘法)來識別圖像中的模式。卷積神經網絡的構成分為:輸入層、卷積層、池化層和全連接層,其結構如下圖所示。

(1)輸入層

整個網絡的輸入,一般代表了一張圖片的像素矩陣。上圖中最左側三維矩陣代表一張輸入的圖片,三維矩陣的長、寬代表了圖像的大小,而三維矩陣的深度代表了圖像的色彩通道(channel)。

(2)卷積層

卷積層是卷積神經網絡(CNN) 中最為重要的部分。卷積層中每一個節點的輸入只是上一層神經網絡中的一小塊,一般來說,通過卷積層處理過的節點矩陣會變的更深。

(3)池化層

池化層不改變三維矩陣的深度,但是可以縮小矩陣的大小。池化操作可以認為是將一張分辨率高的圖片轉化為分辨率較低的圖片。通過池化層,可以進一步縮小最后全連接層中節點的個數,從而到達減少整個神經網絡參數的目的。池化層本身沒有可以訓練的參數。

(4)全連接層

卷積神經網絡中的全連接層等價于傳統前饋神經網絡中的隱含層。全連接層位于卷積神經網絡隱含層的最后部分,并只向其它全連接層傳遞信號。特征圖在全連接層中會失去空間拓撲結構,被展開為向量并通過激勵函數。

1.3.4 循環神經網絡 (RNN)

循環神經網絡 (RNN) 是一種使用順序數據或時間序列數據的人工神經網絡。這些深度學習算法通常用于順序或時間問題,例如語言翻譯、自然語言處理 (nlp)、語音識別和圖像字幕;它們被整合到流行的應用程序中,例如 Siri、語音搜索和谷歌翻譯。與前饋和卷積神經網絡 (CNN) 一樣,循環神經網絡利用訓練數據進行學習。

(循環神經網絡(左側)和前饋神經網絡(右側)的比較)

循環網絡的另一個顯著特征是它們在網絡的每一層共享參數。雖然前饋網絡在每個節點上具有不同的權重,但循環神經網絡在網絡的每一層內共享相同的權重參數。也就是說,這些權重仍然在通過反向傳播和梯度下降的過程中進行調整,以促進強化學習。

1.4 神經網絡與深度學習

訓練深度神經網絡的過程就叫做深度學習。網絡構建好了后,我們只需要負責不停地將訓練數據輸入到神經網絡中,它內部就會自己不停地發生變化不停地學習。打比方說我們想要訓練一個深度神經網絡來識別貓。我們只需要不停地將貓的圖片輸入到神經網絡中去。訓練成功后,我們任意拿來一張新的圖片,它都能判斷出里面是否有貓。

2 量子神經網絡

量子神經網絡(QNN)是前饋神經網絡的一種,是基于量子力學原理的神經網絡模型。通過將量子態的疊加思想引入到傳統的前饋神經網絡中,將神經網絡的隱含層激勵函數采用多個sigmoid函數進行疊加。

一個sigmoid函數僅可以表示兩個量級和狀態,而線性疊加的sigmoid函數相鄰之間有著不同的量子間隔。一個隱層的神經單元就能表示更多的量級和狀態,這樣通過對量子間隔的訓練,訓練樣本輸入數據的不確定性就能得到量化,不同數據將映射到不同的量級之上,利用多層的激勵函數增加網絡的模糊性,提高網絡模式識別的準確性和確定性。

與經典神經網絡相比,量子神經網絡(QNN)具有以下幾個優點:

(1)更快的計算速度;

(2)更高的記憶容量;

(3)更小的網絡規模;

(4)可消除災變性失憶現象。因此其十分適合于未來數據海量、計算要求高的任務。

2.1 量子神經網絡的工作原理

人工神經網絡 (ANN)的許多功能源于其并行分布式信息處理能力和神經元變換的非線性。然而,量子理論的態疊加原理使 QNN具有比ANN更強的并行處理能力并能處理更大型數據集。

根據量子計算原理,一個n位量子寄存器可以同時保存 2^n個n位二進制數 (0到 2^n一1),它們各以一定的概率存在。量子計算系統以這種方式指數地增加存儲能力并能并行處理一個 n位量子寄存器的所有 2^n個數,它的一次運算可產生 2^n個運算結果,相當于常規計算 2^n次操作。

但在讀出量子計算的輸出結果即測量量子寄存器的態時,其疊加態將坍縮 (或消相干)到其中之一個基態上,因而測量時只能測得一個結果。例如在量子神經元模型中,感知器的權矢被一個波函數0(w, t)所取代,0(W, t)是所有可能的經典權矢的量子相干疊加,當疊加權矢與環境作用時(如受到實際輸入的激勵),它必定會消相干到其中之一的基態上,即坍縮到經典權矢上。

接下來我們將嘗試構建一個量子神經網絡,以下是量子神經網絡的工作原理。

首先向網絡提供一些數據x,構建輸入量子態:


將一個二維向量x變換成一個角。


當x被編碼為量子態,我們應用一系列量子門。


網絡的輸出設為π(x,0)。是最后一個量子比特被測量為 |1〉狀態的概率(Z_n-1代表將Z門應用到最后的量子比特),加上一個經典的偏置項。


最后,在輸出的數據中取出和 x 有關聯的標簽,用來計算樣本上的損失——我們將使用二次損失,如下:


從輸出的數據中可以得到網絡 p 的預測:


計算損失函數的梯度。


2.2 如何在量子計算機上計算梯度

先求損失函數對θ_i的微分:


展開最后一項:


通過求導可以去掉常數項。


使用乘積法則進一步展開:


通過 Hermitian 共軛,可以轉化為下面這個簡單的公式:


U(θ) 由多個門組成,每一個門又由不同的參數控制,求U的偏導數只需要求門


我們把

定義為相同的形式,稱為G門,當然形式不是唯一的。


定義了


的形式后,就能找到它的導數:


可以用G門來表示導數:


構造出一個電路來得到所需的內積形式:


Hadamard測試是最簡單的方法——首先,準備好輸入的量子態,并將輔助態制備為疊加態:


現在對|ψ>應用Z_n-1B,約束輔助態是|1>:


然后翻轉輔助態,用A做同樣的操作:


最后,對輔助態使用另一個Hadamard門:


現在輔助態等于0的概率是:


因此如果我們用U(θ)代替B,用U(θ)的共軛對


的導數來代替A,然后輔助量子比特為0的概率將會給我們π(x,θ)對


的梯度。

2.3 建立量子神經網絡

導入所有需要啟動的模塊:

from qiskit import QuantumRegister, ClassicalRegister  
from qiskit import Aer, execute, QuantumCircuit  
from qiskit.extensions import UnitaryGate  
import numpy as np  

將功能(前四列)與標簽分開:

data = np.genfromtxt("processedIRISData.csv", delimiter=",")  
X = data[:, 0:4]  
features = np.array([convertDataToAngles(i) for i in X])  
Y = data[:, -1]  

構建一個為我們進行功能映射的函數。由于輸入向量是歸一化的和4維的,因此映射有一個超級簡單的選擇-使用2個量子位來保存編碼數據,并使用僅將輸入向量重新創建為量子態的映射。為此,我們需要兩個函數-一個從向量中提取角度:

def convertDataToAngles(data):  
      """ 
      Takes in a normalised 4 dimensional vector and returns  
      three angles such that the encodeData function returns  
      a quantum state with the same amplitudes as the  
      vector passed in.  
      """  
      prob1 = data[2] ** 2 + data[3] ** 2  
      prob0 = 1 - prob1  
      angle1 = 2 * np.arcsin(np.sqrt(prob1))  
      prob1 = data[3] ** 2 / prob1  
      angle2 = 2 * np.arcsin(np.sqrt(prob1))  
      prob1 = data[1] ** 2 / prob0  
      angle3 = 2 * np.arcsin(np.sqrt(prob1))  
      return np.array([angle1, angle2, angle3]) 

另一種將角度轉換為量子態的方法:

def encodeData(qc, qreg, angles):  
      """ 
      Given a quantum register belonging to a quantum 
      circuit, performs a series of rotations and controlled 
      rotations characterized by the angles parameter. 
      """      
      qc.ry(angles[0], qreg[1])  
      qc.cry(angles[1], qreg[1], qreg[0])  
      qc.x(qreg[1])  
      qc.cry(angles[2], qreg[1], qreg[0])  
      qc.x(qreg[1])  

編寫實現U (θ)所需的函數,該函數將采用RY和CX交替層的形式。從G門開始:

def GGate(qc, qreg, params):  
      """ 
      Given a parameter α, return a single 
      qubit gate of the form 
      [cos(α), sin(α)] 
      [-sin(α), cos(α)] 
      """      
      u00 = np.cos(params[0])  
      u01 = np.sin(params[0])  
      gateLabel = "G({})".format(  
          params[0]  
      )  
      GGate = UnitaryGate(np.array(  
          [[u00, u01], [-u01, u00]]  
      ), label=gateLabel)  
      return GGate  
     
     
  def GLayer(qc, qreg, params):  
      """ 
      Applies a layer of GGates onto the qubits of register 
      qreg in circuit qc, parametrized by angles params. 
      """      
      for i in range(2):  
          qc.append(GGate(qc, qreg, params[i]), [qreg[i]])  

接下來進行CX門操作:

def CXLayer(qc, qreg, order):  
      """ 
      Applies a layer of CX gates onto the qubits of register 
      qreg in circuit qc, with the order of application 
      determined by the value of the order parameter. 
      """      
      if order:  
          qc.cx(qreg[0], qreg[1])  
      else:  
          qc.cx(qreg[1], qreg[0]) 

將它們放在一起以獲得U (θ):

def generateU(qc, qreg, params):  
      """ 
      Applies the unitary U(θ) to qreg by composing multiple  
      G layers and CX layers. The unitary is parametrized by 
      the array passed into params. 
      """      
      for i in range(params.shape[0]):  
          GLayer(qc, qreg, params[i])  
          CXLayer(qc, qreg, i % 2) 

接下來創建一個函數獲取網絡的輸出,而另一個函數會將這些輸出轉換為類預測:

def getPrediction(qc, qreg, creg, backend):  
      """ 
      Returns the probability of measuring the last qubit 
      in register qreg as in the |1? state. 
      """      
      qc.measure(qreg[0], creg[0])  
      job = execute(qc, backend=backend, shots=10000)  
      results = job.result().get_counts()  
      if '1' in results.keys():  
          return results['1'] / 100000  
      else:  
          return 0  
        
  def convertToClass(predictions):  
      """ 
      Given a set of network outputs, returns class predictions 
      by thresholding them. 
      """      
      return (predictions >= 0.5) * 1  

構建一個在網絡上執行前向傳遞的功能-向其提供一些數據,對其進行處理,并提供網絡輸出:

def forwardPass(params, bias, angles, backend):  
      """ 
      Given a parameter set params, input data in the form 
      of angles, a bias, and a backend, performs a full  
      forward pass on the network and returns the network 
      output. 
      """  
      qreg = QuantumRegister(2)  
      anc = QuantumRegister(1)  
      creg = ClassicalRegister(1)  
      qc = QuantumCircuit(qreg, anc, creg)  
      encodeData(qc, qreg, angles)  
      generateU(qc, qreg, params)  
      pred = getPrediction(qc, qreg, creg, backend) + bias  
      return pred  

編寫測量梯度所需的所有功能,需要能夠應用U (θ)的受控版本:

def CGLayer(qc, qreg, anc, params):  
      """ 
      Applies a controlled layer of GGates, all conditioned 
      on the first qubit of the anc register. 
      """  
      for i in range(2):  
          qc.append(GGate(  
              qc, qreg, params[i]  
          ).control(1), [anc[0], qreg[i]])  
            
  def CCXLayer(qc, qreg, anc, order):  
      """ 
      Applies a layer of Toffoli gates with the first 
      control qubit always being the first qubit of the anc 
      register, and the second depending on the value 
      passed into the order parameter. 
      """  
      if order:  
          qc.ccx(anc[0], qreg[0], qreg[1])  
      else:  
          qc.ccx(anc[0], qreg[1], qreg[0])  
            
  def generateCU(qc, qreg, anc, params):  
      """ 
      Applies a controlled version of the unitary U(θ), 
      conditioned on the first qubit of register anc. 
      """  
      for i in range(params.shape[0]):  
          CGLayer(qc, qreg, anc, params[i])  
          CCXLayer(qc, qreg, anc, i % 2)  

創建一個計算期望值的函數:

def computeRealExpectation(params1, params2, angles, backend):  
      """ 
      Computes the real part of the inner product of the 
      quantum states produced by acting with U(θ) 
      characterised by two sets of parameters, params1 and 
      params2. 
      """  
      qreg = QuantumRegister(2)  
      anc = QuantumRegister(1)  
      creg = ClassicalRegister(1)  
      qc = QuantumCircuit(qreg, anc, creg)  
      encodeData(qc, qreg, angles)  
      qc.h(anc[0])  
      generateCU(qc, qreg, anc, params1)  
      qc.cz(anc[0], qreg[0])  
      qc.x(anc[0])  
      generateCU(qc, qreg, anc, params2)  
      qc.x(anc[0])  
      qc.h(anc[0])  
      prob = getPrediction(qc, anc, creg, backend)  
      return 2 * (prob - 0.5) 

計算出損失函數的梯度-最后做乘法解決梯度中的π ( x ,θ)-y( x )項:

def computeGradient(params, angles, label, bias, backend):  
      """ 
      Given network parameters params, a bias bias, input data 
      angles, and a backend, returns a gradient array holding 
      partials with respect to every parameter in the array 
      params. 
      """  
      prob = forwardPass(params, bias, angles, backend)  
      gradients = np.zeros_like(params)  
      for i in range(params.shape[0]):  
          for j in range(params.shape[1]):  
              newParams = np.copy(params)  
              newParams[i, j, 0] += np.pi / 2  
              gradients[i, j, 0] = computeRealExpectation(  
                  params, newParams, angles, backend  
              )  
              newParams[i, j, 0] -= np.pi / 2  
      biasGrad = (prob + bias - label)  
      return gradients * biasGrad, biasGrad 

一旦有了梯度,就可以使用梯度下降以及稱為動量的技巧來更新網絡參數,這有助于加快訓練時間:

def updateParams(params, prevParams, grads, learningRate, momentum):  
      """ 
      Updates the network parameters using gradient descent  
      and momentum. 
      """  
      delta = params - prevParams  
      paramsNew = np.copy(params)  
      paramsNew = params - grads * learningRate + momentum * delta  
      return paramsNew, params  

構建成本和準確性功能,了解網絡如何響應培訓:

def cost(labels, predictions):  
      """ 
      Returns the sum of quadratic losses over the set 
      (labels, predictions). 
      """  
      loss = 0  
      for label, pred in zip(labels, predictions):  
          loss += (pred - label) ** 2  
      return loss / 2  
    
  def accuracy(labels, predictions):  
      """ 
      Returns the percentage of correct predictions in the 
      set (labels, predictions). 
      """  
      acc = 0  
      for label, pred in zip(labels, predictions):  
          if label == pred:  
              acc += 1  
     
      return acc / labels.shape[0]  

最后創建訓練網絡的函數,并調用它:

def trainNetwork(data, labels, backend):  
      """ 
      Train a quantum neural network on inputs data and 
      labels, using backend backend. Returns the parameters 
      learned. 
      """  
      np.random.seed(1)  
      numSamples = labels.shape[0]  
      numTrain = int(numSamples * 0.75)  
      ordering = np.random.permutation(range(numSamples))  
      trainingData = data[ordering[:numTrain]]  
      validationData = data[ordering[numTrain:]]  
      trainingLabels = labels[ordering[:numTrain]]  
      validationLabels = labels[ordering[numTrain:]]  
      params = np.random.sample((5, 2, 1))  
      bias = 0.01  
      prevParams = np.copy(params)  
      prevBias = bias  
      batchSize = 5  
      momentum = 0.9  
      learningRate = 0.02  
        
      for iteration in range(15):  
          samplePos = iteration * batchSize  
          batchTrainingData = trainingData[samplePos:samplePos + 5]  
          batchLabels = trainingLabels[samplePos:samplePos + 5]  
          batchGrads = np.zeros_like(params)  
          batchBiasGrad = 0  
          for i in range(batchSize):  
              grads, biasGrad = computeGradient(  
                  params, batchTrainingData[i], batchLabels[i], bias, backend  
              )  
              batchGrads += grads / batchSize  
              batchBiasGrad += biasGrad / batchSize  
     
     
          params, prevParams = updateParams(  
              params, prevParams, batchGrads, learningRate, momentum  
          )  
     
     
          temp = bias  
          bias += -learningRate * batchBiasGrad + momentum * (bias - prevBias)  
          prevBias = temp  
     
     
          trainingPreds = np.array([forwardPass(  
              params, bias, angles, backend  
          ) for angles in trainingData])  
          print('Iteration {} | Loss: {}'.format(  
              iteration + 1, cost(trainingLabels, trainingPreds)  
          ))  
     
     
      validationProbs = np.array(  
          [forwardPass(  
              params, bias, angles, backend  
          ) for angles in validationData]  
      )  
      validationClasses = convertToClass(validationProbs)  
      validationAcc = accuracy(validationLabels, validationClasses)  
      print('Validation accuracy:', validationAcc)  
     
     
      return params  
      
  backend = Aer.get_backend('qasm_simulator')  
  learnedParams = trainNetwork(features, Y, backend)

參考資料:

1.https://zhuanlan.zhihu.com/p/215839390

2.https://www.ibm.com/cn-zh/cloud/learn/neural-networks#toc--bS0t361U

3.https://www.ibm.com/cn-zh/cloud/learn/neural-networks

4.https://max.book118.com/html/2019/0803/7024013124002044.shtm

5.https://towardsdatascience.com/quantum-machine-learning-learning-on-neural-networks-fdc03681aed3

6.https://cloud.tencent.com/developer/article/1781109

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內容