Caffe概覽及mnist數(shù)據(jù)集訓(xùn)練

Caffe GitHub頁(yè)面

1. Caffe目錄結(jié)構(gòu)

data/用于存放下載的訓(xùn)練數(shù)據(jù)
docs/ 幫助文檔
examples/ 代碼樣例
matlab/ MATLAB接口文件
python/ PYTHON接口文件
models/ 一些配置好的模型參數(shù)
scripts/ 一些文檔和數(shù)據(jù)會(huì)用到的腳本
核心代碼
tools/ 保存的源碼是用于生成二進(jìn)制處理程序的婆咸,caffe在訓(xùn)練時(shí)實(shí)際是直接調(diào)用這些二進(jìn)制文件
include/ caffe的實(shí)現(xiàn)代碼的頭文件
src/ 實(shí)現(xiàn)caffe的源文件

src/文件結(jié)構(gòu)

gtest/ google test一個(gè)用于測(cè)試的庫(kù)你make runtest時(shí)看見(jiàn)的很多綠色RUN OK就是它,這個(gè)與caffe的學(xué)習(xí)無(wú)關(guān)奈泪,不過(guò)是個(gè)有用的庫(kù)

caffe/ 關(guān)鍵代碼

test/ 用gtest測(cè)試caffe的代碼
util/ 數(shù)據(jù)轉(zhuǎn)換時(shí)用的一些代碼。caffe速度快戈钢,很大程度得益于內(nèi)存設(shè)計(jì)上的優(yōu)化(blob數(shù)據(jù)結(jié)構(gòu)采用proto)和對(duì)卷積的優(yōu)化(部分與im2col相關(guān))
proto/ 即所謂的“Protobuf”,全稱“Google Protocol Buffer”是尔,是一種數(shù)據(jù)存儲(chǔ)格式殉了,幫助caffe提速
layers/ 深度神經(jīng)網(wǎng)絡(luò)中的基本結(jié)構(gòu)就是一層層互不相同的網(wǎng)絡(luò)了,這個(gè)文件夾下的源文件以及目前位置src/caffe中包含所有.cpp文件就是caffe的核心目錄下的核心代碼了拟枚。

2. Caffe核心代碼

核心代碼:
blob.cpp.h 基本的數(shù)據(jù)結(jié)構(gòu)Blob類
commo.cpp.h 定義Caffe類
internal_thread.cpp .h 使用boost::thread線程庫(kù)
net.cpp.h 網(wǎng)絡(luò)結(jié)構(gòu)類Net
solver.cpp.h 優(yōu)化方法類Solver
data_transformer.cpp.h 輸入數(shù)據(jù)的基本操作類DataTransformer
syncedmem.cpp.h 分配內(nèi)存和釋放內(nèi)存類CaffeMallocHost薪铜,用于同步GPU,CPU數(shù)據(jù)
layer.cpp.h 層類Layer
layers/ 此文件夾下面的代碼全部至少繼承了類Layer, 從layer_factory中注冊(cè)繼承

3. Caffe三層結(jié)構(gòu)(Blob恩溅,Layers隔箍,Nets)

Blob:用于數(shù)據(jù)的保存、交換和操作脚乡,Caffe基礎(chǔ)存儲(chǔ)結(jié)構(gòu)
Layer:用于模型和計(jì)算的基礎(chǔ)
Net:整合連接Layers

Blob

在內(nèi)存中表示4維數(shù)組蜒滩,在caffe/blob.hpp中,維度包括(width_,height_,channels_,num_
num_用于存儲(chǔ)數(shù)據(jù)或權(quán)值(data)和權(quán)值增量(diff)
blob.hpp
Blob 在caffe源碼blob.hpp中是一個(gè)模板類奶稠。
protected 的成員變量有:data_ , diff_ , shape_ , count_ , capacity_俯艰,其中data_diff_是共享SyncedMemory 類(在syncedmem的源碼中定義)的智能指針,shape_是int型的vector锌订,count_capacity_是整型變量竹握。
其成員函數(shù)主要有:Reshape, ReshapeLike, SharedData, Updata 等等。
blob.hpp包含了caffe.pb.h瀑志,說(shuō)明caffe protobuf 會(huì)向blob 傳遞參數(shù)涩搓。
#include "caffe/proto/caffe.pb.h"
caffe.pb.h是google protocol buffer根據(jù)caffe.proto自動(dòng)生成的,可以到src/caffe/proto/caffe.proto里看下caffe里面用到的各個(gè)數(shù)據(jù)的定義劈猪,比如BlobProto昧甘,Datum,NetParameter等战得。使用這個(gè)protocol buffer看起來(lái)確實(shí)方便充边,一方面可以用文本文件定義結(jié)構(gòu)化的數(shù)據(jù)類型,另一方面可以生成查詢效率更高常侦、占空間更小的二進(jìn)制文件
#include "caffe/common.hpp"
主要singleton化Caffe類浇冰,并封裝了boost和CUDA隨機(jī)數(shù)生成的函數(shù),提供了統(tǒng)一的接口聋亡。
#include "caffe/syncedmem.hpp"
定義了以下的接口:

inline void CaffeMallocHost(void** ptr, size_t size)
inline void CaffeFreeHost(void* ptr)

主要是分配內(nèi)存和釋放內(nèi)存的肘习。而class SyncedMemory定義了內(nèi)存分配管理和CPU與GPU之間同步的函數(shù)
#include "caffe/util/math_functions.hpp"
封裝了很多cblas矩陣運(yùn)算。
caffe.proto里面BlobProto的定義:
對(duì)于BlobProto坡倔,可以看到定義了四個(gè)optional的int32類型的名字(name)num漂佩、channels脖含、height和width,optional意味著B(niǎo)lob可以有一個(gè)或者沒(méi)有這個(gè)參數(shù)投蝉,每個(gè)名字(name)后面都有一個(gè)數(shù)字养葵,這個(gè)數(shù)字是其名字的一個(gè)標(biāo)簽。這個(gè)數(shù)字就是用來(lái)在生成的二進(jìn)制文件中搜索查詢的標(biāo)簽瘩缆。關(guān)于這個(gè)數(shù)字关拒,1到15會(huì)花費(fèi)1byte的編碼空間,16到2047花費(fèi)2byte庸娱。所以一般建議把那些頻繁使用的名字的標(biāo)簽設(shè)為1到15之間的值着绊。而后面的repeated意味著float類型的data和diff可以重復(fù)任意次,而加上[packed = true]是為了更高效的編碼涌韩。
主要數(shù)據(jù)有兩個(gè)data和diff畔柔,用num、channels臣樱、height和width這四個(gè)維度來(lái)確定數(shù)據(jù)的具體位置,做一些數(shù)據(jù)查詢和Blob reshape的操作腮考。

message BlobProto {
  optional BlobShape shape = 7;
  repeated float data = 5 [packed = true];
  repeated float diff = 6 [packed = true];
  repeated double double_data = 8 [packed = true];
  repeated double double_diff = 9 [packed = true];

  // 4D dimensions -- deprecated.  Use "shape" instead.
  optional int32 num = 1 [default = 0];
  optional int32 channels = 2 [default = 0];
  optional int32 height = 3 [default = 0];
  optional int32 width = 4 [default = 0];
}

Blob主要變量

shared_ptr<SyncedMemory> data_;
shared_ptr<SyncedMemory> diff_;
shared_ptr<SyncedMemory> shape_data_;
vector<int> shape_;
int count_;
int capacity_;

BLob只是一個(gè)基本的數(shù)據(jù)結(jié)構(gòu)雇毫,因此內(nèi)部的變量相對(duì)較少,首先是data_指針踩蔚,指針類型是shared_ptr棚放,屬于boost庫(kù)的一個(gè)智能指針,這一部分主要用來(lái)申請(qǐng)內(nèi)存存儲(chǔ)data馅闽,data主要是正向傳播的時(shí)候用的飘蚯。同理,diff_主要用來(lái)存儲(chǔ)偏差福也,update data局骤,shape_datashape_都是存儲(chǔ)Blob的形狀,一個(gè)是老版本一個(gè)是新版本暴凑。count_表示Blob中的元素個(gè)數(shù)峦甩,也就是個(gè)數(shù)*通道數(shù)*高度*寬度,capacity_表示當(dāng)前的元素個(gè)數(shù),因?yàn)锽lob可能會(huì)reshape现喳。

主要函數(shù)

1. 構(gòu)造函數(shù) & 2. reshape函數(shù)

構(gòu)造函數(shù)開(kāi)辟一個(gè)內(nèi)存空間來(lái)存儲(chǔ)數(shù)據(jù)凯傲,Reshape函數(shù)在Layer中的reshape或者forward操作中來(lái)adjust dimension。同時(shí)在改變Blob大小時(shí)嗦篱,內(nèi)存將會(huì)被重新分配如果內(nèi)存大小不夠了冰单,并且額外的內(nèi)存將不會(huì)被釋放。對(duì)input的blob進(jìn)行reshape,如果立馬調(diào)用Net::Backward是會(huì)出錯(cuò)的灸促,因?yàn)閞eshape之后诫欠,要么Net::forward或者Net::Reshape就會(huì)被調(diào)用來(lái)將新的input shape傳播到高層涵卵。

3. count函數(shù)

重載很多個(gè)count()函數(shù),主要還是為了統(tǒng)計(jì)Blob的容量(volume)呕诉,或者是某一片(slice)缘厢,從某個(gè)axis到具體某個(gè)axis的shape乘積(如 inline int count(int start_axis, int end_axis))。

4. data_數(shù)據(jù)操作函數(shù) & 5. 反向傳播導(dǎo)數(shù)diff_操作函數(shù)

inline Dtype data_at(const int n, const int c, const int h, const int w)
inline Dtype diff_at(const int n, const int c, const int h, const int w)
inline Dtype data_at(const vector<int>& index)
inline Dtype diff_at(const vector<int>& index)
inline const shared_ptr<SyncedMemory>& data()
inline const shared_ptr<SyncedMemory>& diff()

這一部分函數(shù)主要通過(guò)給定的位置訪問(wèn)數(shù)據(jù)甩挫,根據(jù)位置計(jì)算與數(shù)據(jù)起始的偏差offset贴硫,在通過(guò)cpu_data*指針獲得地址

6. FromProto/ToProto 數(shù)據(jù)序列化

將數(shù)據(jù)序列化,存儲(chǔ)到BlobProto伊者,這里說(shuō)到Proto是谷歌的一個(gè)數(shù)據(jù)序列化的存儲(chǔ)格式英遭,可以實(shí)現(xiàn)語(yǔ)言、平臺(tái)無(wú)關(guān)亦渗、可擴(kuò)展的序列化結(jié)構(gòu)數(shù)據(jù)格式挖诸。

7. Update函數(shù)

該函數(shù)用于參數(shù)blob的更新(weight,bias 等減去對(duì)應(yīng)的導(dǎo)數(shù))

8.其他運(yùn)算函數(shù)

Dtype asum_data() const;//計(jì)算data的L1范數(shù)(所有元素絕對(duì)值之和)
Dtype asum_diff() const;//計(jì)算diff的L1范數(shù)
Dtype sumsq_data() const;//計(jì)算data的L2范數(shù)(所有元素平方和)
Dtype sumsq_diff() const;//計(jì)算diff的L2范數(shù)
void scale_data(Dtype scale_factor);//將data部分乘以一個(gè)因子
void scale_diff(Dtype scale_factor);//將diff部分乘一個(gè)因子

Blob編程操作

cd ~
ls
cd caffe
cd build

之前安裝caffe法精,裝在/usr/local下或~/caffe/build/install
~/caffe/build/install下多律,重裝一下

~/caffe/build$ sudo cmake -D CPU_ONLY=ON -D CMAKE_INSTALL_PREFIX=/usr/local ..
~/caffe/build$ sudo make install

export LD_LIBRARY_PATH=/usr/local/lib:${LD_LIBRARY_PATH}

cd ~/teach_samples/caffe/
ls
vim test_blob.cpp

test_blob.cpp
gcc -o test_blob test_blob.cpp -D CPU_ONLY -lcaffe -lstdc++ -lglog

/*
 *
 * 功能:
 * 1. 測(cè)試使用Blob
 * 2. 給blob賦值
 * 3. 獲取blob指定位置的值
 * 4. 輸出通過(guò)L1范式和L2范式得到的結(jié)果
 *
 */

#include <iostream>
#include "caffe/blob.hpp"

int main(int argc,char* argv[]){
    //構(gòu)造一個(gè)Blob
    caffe::Blob<float> b;
    std::cout<<"Size : "<<b.shape_string()<<std::endl;
    b.Reshape(1,2,3,4);
    std::cout<<"Size : "<<b.shape_string()<<std::endl;

    //使用mutable_cpu_data函數(shù)修改Blob內(nèi)部數(shù)值
    float* p = b.mutable_cpu_data();
    for(int i=0;i<b.count();i++){
        p[i] = i;
    }


    //打印指定位置的每一個(gè)數(shù)值
    for(int u=0; u<b.num() ;u++){
        for(int v=0;v<b.channels();v++){
            for(int w=0;w<b.height();w++){
                for(int x=0; x<b.width();x++){
                    std::cout<<"b["<<u<<"] ["<<v<<"] ["<<w<<"] ["<<x<<"] ="<<b.data_at(u,v,w,x)<<std::endl;
                }
            }
        }
    }

    //求L1,L2范式及其輸出結(jié)果
    std::cout<<"ASUM : "<<b.asum_data()<<std::endl;
    std::cout<<"SUMSQ : "<<b.sumsq_data()<<std::endl;

    return 0;
}

測(cè)試
~/teach_samples/caffe$ ./test_blob

Layer

所有的Pooling,Convolve搂蜓,apply nonlinearities等操作都在這里實(shí)現(xiàn)狼荞。在Layer中input data用bottom表示output data用top表示。每一層定義了三種操作setup(Layer初始化), forward(正向傳導(dǎo)帮碰,根據(jù)input計(jì)算output), backward(反向傳導(dǎo)計(jì)算相味,根據(jù)output計(jì)算input的梯度)。forward和backward有GPU和CPU兩個(gè)版本的實(shí)現(xiàn)殉挽。
5種衍生Layers:
data_layer
neuron_layer
loss_layer
common_layer
vision_layer

data_layer

data_layer主要包含與數(shù)據(jù)有關(guān)的文件丰涉。在官方文檔中指出data是caffe數(shù)據(jù)的入口是網(wǎng)絡(luò)的最低層,并且支持多種格式斯碌,在這之中又有5種LayerType:
DATA 用于LevelDB或LMDB數(shù)據(jù)格式的輸入的類型一死,輸入?yún)?shù)有source, batch_size, (rand_skip), (backend)。后兩個(gè)是可選输拇。
MEMORY_DATA 這種類型可以直接從內(nèi)存讀取數(shù)據(jù)使用時(shí)需要調(diào)用MemoryDataLayer::Reset摘符,輸入?yún)?shù)有batch_size, channels, height, width。
HDF5_DATA HDF5數(shù)據(jù)格式輸入的類型策吠,輸入?yún)?shù)有source, batch_size逛裤。
HDF5_OUTPUT HDF5數(shù)據(jù)格式輸出的類型,輸入?yún)?shù)有file_name猴抹。
IMAGE_DATA 圖像格式數(shù)據(jù)輸入的類型带族,輸入?yún)?shù)有source, batch_size, (rand_skip), (shuffle), (new_height), (new_width)。
其實(shí)還有兩種WINDOW_DATA, DUMMY_DATA用于測(cè)試和預(yù)留的接口,不重要蟀给。

neuron_layer

同樣是數(shù)據(jù)的操作層蝙砌,neuron_layer實(shí)現(xiàn)里大量激活函數(shù)阳堕,主要是元素級(jí)別的操作,具有相同的bottom,top size择克。
Caffe中實(shí)現(xiàn)了大量激活函數(shù)GPU和CPU的都有很多恬总。它們的父類都是NeuronLayer
template <typename Dtype>
class NeuronLayer : public Layer<Dtype>
一般的參數(shù)設(shè)置格式如下(以ReLU為例):

layers {
  name: "relu1"
  type: RELU
  bottom: "conv1"
  top: "conv1"
}

loss_layer

Loss層計(jì)算網(wǎng)絡(luò)誤差,loss_layer.hpp頭文件調(diào)用情況:

#include "caffe/blob.hpp"
#include "caffe/common.hpp"
#include "caffe/layer.hpp"
#include "caffe/neuron_layers.hpp"
#include "caffe/proto/caffe.pb.h"

可以看見(jiàn)調(diào)用了neuron_layers.hpp肚邢,估計(jì)是需要調(diào)用里面的函數(shù)計(jì)算Loss壹堰,一般來(lái)說(shuō)Loss放在最后一層。caffe實(shí)現(xiàn)了大量loss function骡湖,它們的父類都是LossLayer贱纠。
template <typename Dtype>
class LossLayer : public Layer<Dtype>

common_layer

這一層主要進(jìn)行的是vision_layer的連接
聲明了9個(gè)類型的common_layer,部分有GPU實(shí)現(xiàn):
InnerProductLayer 常常用來(lái)作為全連接層
SplitLayer 用于一輸入對(duì)多輸出的場(chǎng)合(對(duì)blob)
FlattenLayer 將n * c * h * w變成向量的格式n * ( c * h * w ) * 1 * 1
ConcatLayer 用于多輸入一輸出的場(chǎng)合
SilenceLayer 用于一輸入對(duì)多輸出的場(chǎng)合(對(duì)layer)
(Elementwise Operations) 這里面是我們常說(shuō)的激活函數(shù)層Activation Layers响蕴。
EltwiseLayer
SoftmaxLayer
ArgMaxLayer
MVNLayer

vision_layer

主要是實(shí)現(xiàn)Convolution和Pooling操作, 主要有以下幾個(gè)類:
ConvolutionLayer 最常用的卷積操作
Im2colLayer 與MATLAB里面的im2col類似谆焊,即image-to-column transformation,轉(zhuǎn)換后方便卷積計(jì)算
LRNLayer 全稱local response normalization layer浦夷,在Hinton論文中有詳細(xì)介紹ImageNet Classification with Deep Convolutional Neural Networks 辖试。
PoolingLayer Pooling操作

Net

Net由一系列的Layer組成(無(wú)回路有向圖DAG),Layer之間的連接由一個(gè)文本文件描述劈狐。模型初始化Net::Init()會(huì)產(chǎn)生blob和layer并調(diào)用Layer::SetUp剃执。在此過(guò)程中Net會(huì)報(bào)告初始化進(jìn)程。這里的初始化與設(shè)備無(wú)關(guān)懈息,在初始化之后通過(guò)Caffe::set_mode()設(shè)置Caffe::mode()來(lái)選擇運(yùn)行平臺(tái)CPU或GPU,結(jié)果是相同的摹恰。

4. ProtoBuf

Caffe中辫继,數(shù)據(jù)的讀取、運(yùn)算俗慈、存儲(chǔ)都是采用Google Protocol Buffer來(lái)進(jìn)行的姑宽。
Protocol Buffer(PB)是一種輕便、高效的結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)格式闺阱,可以用于結(jié)構(gòu)化數(shù)據(jù)串行化炮车,很適合做數(shù)據(jù)存儲(chǔ)或 RPC 數(shù)據(jù)交換格式。它可用于通訊協(xié)議酣溃、數(shù)據(jù)存儲(chǔ)等領(lǐng)域的語(yǔ)言無(wú)關(guān)瘦穆、平臺(tái)無(wú)關(guān)、可擴(kuò)展的序列化結(jié)構(gòu)數(shù)據(jù)格式赊豌。是一種效率和兼容性都很優(yōu)秀的二進(jìn)制數(shù)據(jù)傳輸格式扛或,目前提供了 C++、Java碘饼、Python 三種語(yǔ)言的 API熙兔。Caffe采用的是C++和Python的API悲伶。
protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --java_out=DST_DIR --python_out=DST_DIR path/to/file.proto
這里將給出上述命令的參數(shù)解釋。

  1. protoc為Protocol Buffer提供的命令行編譯工具住涉。
  2. --proto_path等同于-I選項(xiàng)麸锉,主要用于指定待編譯的.proto消息定義文件所在的目錄,該選項(xiàng)可以被同時(shí)指定多個(gè)舆声。
  3. --cpp_out選項(xiàng)表示生成C++代碼花沉,--java_out表示生成Java代碼,--python_out則表示生成Python代碼纳寂,其后的目錄為生成后的代碼所存放的目錄主穗。
  4. path/to/file.proto表示待編譯的消息定義文件。

注:對(duì)于C++而言毙芜,通過(guò)Protocol Buffer編譯工具忽媒,可以將每個(gè).proto文件生成出一對(duì).h和.cc的C++代碼文件。生成后的文件可以直接加載到應(yīng)用程序所在的工程項(xiàng)目中腋粥。
代碼文件

ls
vim ly.helloworld.proto

:q!退出
C++編譯
protoc -I=. --cpp_out=. ly.helloworld.proto

ls
vim test_pb.cpp

:q!退出
編譯
gcc -o test_pb test_pb.cpp ly.helloworld.pb.cc -lprotobuf -lstdc++

ls
./test_pb
ls

看到log文件輸出成功

5. 訓(xùn)練mnist數(shù)據(jù)集

Training LeNet on MNIST with Caffe

  1. 獲取數(shù)據(jù)
    ./data/mnist/get_mnist.sh
  2. 將數(shù)據(jù)轉(zhuǎn)化為lmdb格式
    ./examples/mnist/create_mnist.sh
  3. 訓(xùn)練
    ./examples/mnist/train_lenet.sh

注意:

  • 腳本的運(yùn)行基于$Caffe_Root文件加下的路徑執(zhí)行
  • 訓(xùn)練的時(shí)候晦雨,如果安裝的時(shí)候選擇了CPU_ONLY的話,在*.prototxt文件中隘冲,把mode:GPU改成mode:CPU

下載數(shù)據(jù)

cd caffe
./data/mnist/get_mnist.sh

轉(zhuǎn)化數(shù)據(jù)

./examples/mnist/create_mnist.sh

./examples/mnist/create_mnist.sh
create_mnist.sh是利用caffe-master/build/examples/mnist/convert_mnist_data.bin工具闹瞧,將mnist date轉(zhuǎn)化為可用的lmdb格式的文件。并將新生成的2個(gè)文件mnist-train-lmdbmnist-test-lmdb放于create_mnist.sh同目錄下展辞。
訓(xùn)練

./examples/mnist/train_lenet.sh

如果沒(méi)有GPU,使用CPU模式,修改$CAFFE_ROOT/examples/mnist/lenet_solver.prototxt:

# solver mode: CPU or GPU
solver_mode: CPU
# The train/test net protocol buffer definition
net: "examples/mnist/lenet_train_test.prototxt" //網(wǎng)絡(luò)協(xié)議具體定義
# test_iter specifies how many forward passes the test should carry out.
# In the case of MNIST, we have test batch size 100 and 100 test iterations,
# covering the full 10,000 testing images.
test_iter: 100 //test迭代次數(shù),如果batch_size=100,則100張圖一批,訓(xùn)練100次,則可以覆蓋10000張圖的需求
# Carry out testing every 500 training iterations.
test_interval: 500 //訓(xùn)練迭代500次測(cè)試一次
# The base learning rate, momentum and the weight decay of the network.//網(wǎng)絡(luò)參數(shù):學(xué)習(xí)率,動(dòng)量,權(quán)重的衰減
base_lr: 0.01
momentum: 0.9
weight_decay: 0.0005
# The learning rate policy //學(xué)習(xí)策略:有固定學(xué)習(xí)率和每步遞減學(xué)習(xí)率
lr_policy: "inv"
gamma: 0.0001
power: 0.75
# Display every 100 iterations //每迭代100次顯示一次
display: 100
# The maximum number of iterations //最大迭代次數(shù)
max_iter: 10000
# snapshot intermediate results //每5000次迭代存儲(chǔ)一次數(shù)據(jù),路徑前綴如下
snapshot: 5000
snapshot_prefix: "examples/mnist/lenet"
# solver mode: CPU or GPU //使用CPU或者GPU
solver_mode: GPU

./examples/mnist/train_lenet.sh
調(diào)用工具:./build/tools/caffe train --solver=examples/mnist/lenet_solver.prototxt

看到optimization done訓(xùn)練結(jié)束奥邮,~/caffe/examples/mnist/多了caffemodel
CPU:i3-3240 CPU @ 3.40GHz 訓(xùn)練耗時(shí)15分鐘

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市罗珍,隨后出現(xiàn)的幾起案子洽腺,更是在濱河造成了極大的恐慌,老刑警劉巖覆旱,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蘸朋,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡扣唱,警方通過(guò)查閱死者的電腦和手機(jī)藕坯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)噪沙,“玉大人炼彪,你說(shuō)我怎么就攤上這事∏簦” “怎么了霹购?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)朋腋。 經(jīng)常有香客問(wèn)我齐疙,道長(zhǎng)膜楷,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任贞奋,我火速辦了婚禮赌厅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘轿塔。我一直安慰自己特愿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布勾缭。 她就那樣靜靜地躺著揍障,像睡著了一般。 火紅的嫁衣襯著肌膚如雪俩由。 梳的紋絲不亂的頭發(fā)上毒嫡,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音幻梯,去河邊找鬼兜畸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛碘梢,可吹牛的內(nèi)容都是我干的咬摇。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼煞躬,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼肛鹏!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起恩沛,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤龄坪,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后复唤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡烛卧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年佛纫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片总放。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡呈宇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出局雄,到底是詐尸還是另有隱情甥啄,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布炬搭,位于F島的核電站蜈漓,受9級(jí)特大地震影響穆桂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜融虽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一享完、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧有额,春花似錦般又、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至萤衰,卻和暖如春堕义,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背腻菇。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工胳螟, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人筹吐。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓糖耸,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親丘薛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嘉竟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

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