衡阳派盒市场营销有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

PyTorch教程-8.7. 密集連接網絡 (DenseNet)

jf_pJlTbmA9 ? 來源:PyTorch ? 作者:PyTorch ? 2023-06-05 15:44 ? 次閱讀

ResNet 顯著改變了如何在深度網絡中參數化函數的觀點。DenseNet(密集卷積網絡)在某種程度上是對此的邏輯延伸 (Huang et al. , 2017)。DenseNet 的特點是每一層都連接到所有前面的層的連接模式和連接操作(而不是 ResNet 中的加法運算符)以保留和重用早期層的特征。要了解如何得出它,讓我們稍微繞道數學。

import torch
from torch import nn
from d2l import torch as d2l

from mxnet import init, np, npx
from mxnet.gluon import nn
from d2l import mxnet as d2l

npx.set_np()

import jax
from flax import linen as nn
from jax import numpy as jnp
from d2l import jax as d2l

import tensorflow as tf
from d2l import tensorflow as d2l

8.7.1. 從 ResNet 到 DenseNet

回憶一下函數的泰勒展開式。對于這一點x=0 它可以寫成

(8.7.1)f(x)=f(0)+x?[f′(0)+x?[f″(0)2!+x?[f?(0)3!+…]]].

關鍵是它將函數分解為越來越高階的項。同樣,ResNet 將函數分解為

(8.7.2)f(x)=x+g(x).

也就是說,ResNet分解f分為一個簡單的線性項和一個更復雜的非線性項。如果我們想捕獲(不一定要添加)兩個術語以外的信息怎么辦?一種這樣的解決方案是 DenseNet (Huang等人,2017 年)。

poYBAGR9Ne2AS2zdAAAtlyxWZMM335.svg

圖 8.7.1 ResNet(左)和 DenseNet(右)在跨層連接中的主要區別:加法的使用和連接的使用。

如圖 8.7.1所示,ResNet 和 DenseNet 的主要區別在于后者的輸出是 連接的(表示為[,]) 而不是添加。結果,我們從x在應用越來越復雜的函數序列后,它的值:

(8.7.3)x→[x,f1(x),f2([x,f1(x)]),f3([x,f1(x),f2([x,f1(x)])]),…].

最后,將所有這些功能組合在 MLP 中,再次減少特征數量。就實現而言,這非常簡單:我們不是添加術語,而是將它們連接起來。DenseNet 這個名字源于變量之間的依賴圖變得非常密集這一事實。這種鏈的最后一層與前面的所有層緊密相連。密集連接如圖 8.7.2所示 。

pYYBAGR9Ne-AInwAAABmDzH7OvY343.svg

圖 8.7.2 DenseNet 中的密集連接。注意維度如何隨著深度增加。

構成 DenseNet 的主要組件是密集塊和 過渡層。前者定義輸入和輸出如何連接,而后者控制通道的數量,使其不會太大,因為擴展 x→[x,f1(x),f2([x,f1(x)]),…] 可以是相當高維的。

8.7.2. 密集塊

DenseNet 使用改進的 ResNet 的“批量歸一化、激活和卷積”結構(參見第 8.6 節中的練習 )。首先,我們實現這個卷積塊結構。

def conv_block(num_channels):
  return nn.Sequential(
    nn.LazyBatchNorm2d(), nn.ReLU(),
    nn.LazyConv2d(num_channels, kernel_size=3, padding=1))

def conv_block(num_channels):
  blk = nn.Sequential()
  blk.add(nn.BatchNorm(),
      nn.Activation('relu'),
      nn.Conv2D(num_channels, kernel_size=3, padding=1))
  return blk

class ConvBlock(nn.Module):
  num_channels: int
  training: bool = True

  @nn.compact
  def __call__(self, X):
    Y = nn.relu(nn.BatchNorm(not self.training)(X))
    Y = nn.Conv(self.num_channels, kernel_size=(3, 3), padding=(1, 1))(Y)
    Y = jnp.concatenate((X, Y), axis=-1)
    return Y

class ConvBlock(tf.keras.layers.Layer):
  def __init__(self, num_channels):
    super(ConvBlock, self).__init__()
    self.bn = tf.keras.layers.BatchNormalization()
    self.relu = tf.keras.layers.ReLU()
    self.conv = tf.keras.layers.Conv2D(
      filters=num_channels, kernel_size=(3, 3), padding='same')

    self.listLayers = [self.bn, self.relu, self.conv]

  def call(self, x):
    y = x
    for layer in self.listLayers.layers:
      y = layer(y)
    y = tf.keras.layers.concatenate([x,y], axis=-1)
    return y

密集塊由多個卷積塊組成,每個卷積塊使用相同數量的輸出通道。然而,在前向傳播中,我們在通道維度上連接每個卷積塊的輸入和輸出。惰性評估允許我們自動調整維度。

class DenseBlock(nn.Module):
  def __init__(self, num_convs, num_channels):
    super(DenseBlock, self).__init__()
    layer = []
    for i in range(num_convs):
      layer.append(conv_block(num_channels))
    self.net = nn.Sequential(*layer)

  def forward(self, X):
    for blk in self.net:
      Y = blk(X)
      # Concatenate input and output of each block along the channels
      X = torch.cat((X, Y), dim=1)
    return X

class DenseBlock(nn.Block):
  def __init__(self, num_convs, num_channels):
    super().__init__()
    self.net = nn.Sequential()
    for _ in range(num_convs):
      self.net.add(conv_block(num_channels))

  def forward(self, X):
    for blk in self.net:
      Y = blk(X)
      # Concatenate input and output of each block along the channels
      X = np.concatenate((X, Y), axis=1)
    return X

class DenseBlock(nn.Module):
  num_convs: int
  num_channels: int
  training: bool = True

  def setup(self):
    layer = []
    for i in range(self.num_convs):
      layer.append(ConvBlock(self.num_channels, self.training))
    self.net = nn.Sequential(layer)

  def __call__(self, X):
    return self.net(X)

class DenseBlock(tf.keras.layers.Layer):
  def __init__(self, num_convs, num_channels):
    super(DenseBlock, self).__init__()
    self.listLayers = []
    for _ in range(num_convs):
      self.listLayers.append(ConvBlock(num_channels))

  def call(self, x):
    for layer in self.listLayers.layers:
      x = layer(x)
    return x

在下面的示例中,我們定義了一個DenseBlock具有 10 個輸出通道的 2 個卷積塊的實例。當使用 3 個通道的輸入時,我們將得到一個輸出3+10+10=23渠道。卷積塊通道數控制輸出通道數相對于輸入通道數的增長。這也稱為增長率。

blk = DenseBlock(2, 10)
X = torch.randn(4, 3, 8, 8)
Y = blk(X)
Y.shape

torch.Size([4, 23, 8, 8])

blk = DenseBlock(2, 10)
X = np.random.uniform(size=(4, 3, 8, 8))
blk.initialize()
Y = blk(X)
Y.shape

(4, 23, 8, 8)

blk = DenseBlock(2, 10)
X = jnp.zeros((4, 8, 8, 3))
Y = blk.init_with_output(d2l.get_key(), X)[0]
Y.shape

(4, 8, 8, 23)

blk = DenseBlock(2, 10)
X = tf.random.uniform((4, 8, 8, 3))
Y = blk(X)
Y.shape

TensorShape([4, 8, 8, 23])

8.7.3. 過渡層

由于每個密集塊都會增加通道的數量,因此添加太多通道會導致模型過于復雜。過渡層用于控制模型的復雜性。它通過使用一個減少通道的數量1×1卷積。此外,它通過步幅為 2 的平均池將高度和寬度減半。

def transition_block(num_channels):
  return nn.Sequential(
    nn.LazyBatchNorm2d(), nn.ReLU(),
    nn.LazyConv2d(num_channels, kernel_size=1),
    nn.AvgPool2d(kernel_size=2, stride=2))

def transition_block(num_channels):
  blk = nn.Sequential()
  blk.add(nn.BatchNorm(), nn.Activation('relu'),
      nn.Conv2D(num_channels, kernel_size=1),
      nn.AvgPool2D(pool_size=2, strides=2))
  return blk

class TransitionBlock(nn.Module):
  num_channels: int
  training: bool = True

  @nn.compact
  def __call__(self, X):
    X = nn.BatchNorm(not self.training)(X)
    X = nn.relu(X)
    X = nn.Conv(self.num_channels, kernel_size=(1, 1))(X)
    X = nn.avg_pool(X, window_shape=(2, 2), strides=(2, 2))
    return X

class TransitionBlock(tf.keras.layers.Layer):
  def __init__(self, num_channels, **kwargs):
    super(TransitionBlock, self).__init__(**kwargs)
    self.batch_norm = tf.keras.layers.BatchNormalization()
    self.relu = tf.keras.layers.ReLU()
    self.conv = tf.keras.layers.Conv2D(num_channels, kernel_size=1)
    self.avg_pool = tf.keras.layers.AvgPool2D(pool_size=2, strides=2)

  def call(self, x):
    x = self.batch_norm(x)
    x = self.relu(x)
    x = self.conv(x)
    return self.avg_pool(x)

將具有 10 個通道的過渡層應用于前面示例中的密集塊的輸出。這將輸出通道的數量減少到 10,并將高度和寬度減半。

blk = transition_block(10)
blk(Y).shape

torch.Size([4, 10, 4, 4])

blk = transition_block(10)
blk.initialize()
blk(Y).shape

(4, 10, 4, 4)

blk = TransitionBlock(10)
blk.init_with_output(d2l.get_key(), Y)[0].shape

(4, 4, 4, 10)

blk = TransitionBlock(10)
blk(Y).shape

TensorShape([4, 4, 4, 10])

8.7.4. DenseNet 模型

接下來,我們將構建一個 DenseNet 模型。DenseNet 首先使用與 ResNet 中相同的單卷積層和最大池化層。

class DenseNet(d2l.Classifier):
  def b1(self):
    return nn.Sequential(
      nn.LazyConv2d(64, kernel_size=7, stride=2, padding=3),
      nn.LazyBatchNorm2d(), nn.ReLU(),
      nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

class DenseNet(d2l.Classifier):
  def b1(self):
    net = nn.Sequential()
    net.add(nn.Conv2D(64, kernel_size=7, strides=2, padding=3),
      nn.BatchNorm(), nn.Activation('relu'),
      nn.MaxPool2D(pool_size=3, strides=2, padding=1))
    return net

class DenseNet(d2l.Classifier):
  num_channels: int = 64
  growth_rate: int = 32
  arch: tuple = (4, 4, 4, 4)
  lr: float = 0.1
  num_classes: int = 10
  training: bool = True

  def setup(self):
    self.net = self.create_net()

  def b1(self):
    return nn.Sequential([
      nn.Conv(64, kernel_size=(7, 7), strides=(2, 2), padding='same'),
      nn.BatchNorm(not self.training),
      nn.relu,
      lambda x: nn.max_pool(x, window_shape=(3, 3),
                 strides=(2, 2), padding='same')
    ])

class DenseNet(d2l.Classifier):
  def b1(self):
    return tf.keras.models.Sequential([
      tf.keras.layers.Conv2D(
        64, kernel_size=7, strides=2, padding='same'),
      tf.keras.layers.BatchNormalization(),
      tf.keras.layers.ReLU(),
      tf.keras.layers.MaxPool2D(
        pool_size=3, strides=2, padding='same')])

然后,類似于 ResNet 使用的由殘差塊組成的四個模塊,DenseNet 使用四個密集塊。與 ResNet 類似,我們可以設置每個密集塊中使用的卷積層數。這里,我們設置為4,與8.6節中的ResNet-18模型一致。此外,我們將密集塊中卷積層的通道數(即增長率)設置為 32,因此每個密集塊將添加 128 個通道。

在 ResNet 中,每個模塊之間的高度和寬度通過步長為 2 的殘差塊減少。這里,我們使用過渡層將高度和寬度減半,并將通道數減半。與 ResNet 類似,在最后連接一個全局池化層和一個全連接層以產生輸出。

@d2l.add_to_class(DenseNet)
def __init__(self, num_channels=64, growth_rate=32, arch=(4, 4, 4, 4),
       lr=0.1, num_classes=10):
  super(DenseNet, self).__init__()
  self.save_hyperparameters()
  self.net = nn.Sequential(self.b1())
  for i, num_convs in enumerate(arch):
    self.net.add_module(f'dense_blk{i+1}', DenseBlock(num_convs,
                             growth_rate))
    # The number of output channels in the previous dense block
    num_channels += num_convs * growth_rate
    # A transition layer that halves the number of channels is added
    # between the dense blocks
    if i != len(arch) - 1:
      num_channels //= 2
      self.net.add_module(f'tran_blk{i+1}', transition_block(
        num_channels))
  self.net.add_module('last', nn.Sequential(
    nn.LazyBatchNorm2d(), nn.ReLU(),
    nn.AdaptiveAvgPool2d((1, 1)), nn.Flatten(),
    nn.LazyLinear(num_classes)))
  self.net.apply(d2l.init_cnn)

@d2l.add_to_class(DenseNet)
def __init__(self, num_channels=64, growth_rate=32, arch=(4, 4, 4, 4),
       lr=0.1, num_classes=10):
  super(DenseNet, self).__init__()
  self.save_hyperparameters()
  self.net = nn.Sequential()
  self.net.add(self.b1())
  for i, num_convs in enumerate(arch):
    self.net.add(DenseBlock(num_convs, growth_rate))
    # The number of output channels in the previous dense block
    num_channels += num_convs * growth_rate
    # A transition layer that halves the number of channels is added
    # between the dense blocks
    if i != len(arch) - 1:
      num_channels //= 2
      self.net.add(transition_block(num_channels))
  self.net.add(nn.BatchNorm(), nn.Activation('relu'),
         nn.GlobalAvgPool2D(), nn.Dense(num_classes))
  self.net.initialize(init.Xavier())

@d2l.add_to_class(DenseNet)
def create_net(self):
  net = self.b1()
  for i, num_convs in enumerate(self.arch):
    net.layers.extend([DenseBlock(num_convs, self.growth_rate,
                   training=self.training)])
    # The number of output channels in the previous dense block
    num_channels = self.num_channels + (num_convs * self.growth_rate)
    # A transition layer that halves the number of channels is added
    # between the dense blocks
    if i != len(self.arch) - 1:
      num_channels //= 2
      net.layers.extend([TransitionBlock(num_channels,
                        training=self.training)])
  net.layers.extend([
    nn.BatchNorm(not self.training),
    nn.relu,
    lambda x: nn.avg_pool(x, window_shape=x.shape[1:3],
               strides=x.shape[1:3], padding='valid'),
    lambda x: x.reshape((x.shape[0], -1)),
    nn.Dense(self.num_classes)
  ])
  return net

@d2l.add_to_class(DenseNet)
def __init__(self, num_channels=64, growth_rate=32, arch=(4, 4, 4, 4),
       lr=0.1, num_classes=10):
  super(DenseNet, self).__init__()
  self.save_hyperparameters()
  self.net = tf.keras.models.Sequential(self.b1())
  for i, num_convs in enumerate(arch):
    self.net.add(DenseBlock(num_convs, growth_rate))
    # The number of output channels in the previous dense block
    num_channels += num_convs * growth_rate
    # A transition layer that halves the number of channels is added
    # between the dense blocks
    if i != len(arch) - 1:
      num_channels //= 2
      self.net.add(TransitionBlock(num_channels))
  self.net.add(tf.keras.models.Sequential([
    tf.keras.layers.BatchNormalization(),
    tf.keras.layers.ReLU(),
    tf.keras.layers.GlobalAvgPool2D(),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(num_classes)]))

8.7.5. 訓練

由于我們在這里使用更深的網絡,在本節中,我們將輸入的高度和寬度從 224 減少到 96 以簡化計算。

model = DenseNet(lr=0.01)
trainer = d2l.Trainer(max_epochs=10, num_gpus=1)
data = d2l.FashionMNIST(batch_size=128, resize=(96, 96))
trainer.fit(model, data)

poYBAGR9NfGAZbvmAAGACD91fnk292.svg

model = DenseNet(lr=0.01)
trainer = d2l.Trainer(max_epochs=10, num_gpus=1)
data = d2l.FashionMNIST(batch_size=128, resize=(96, 96))
trainer.fit(model, data)

pYYBAGR9NfSAPb7eAAF-EuBmwRM257.svg

model = DenseNet(lr=0.01)
trainer = d2l.Trainer(max_epochs=10, num_gpus=1)
data = d2l.FashionMNIST(batch_size=128, resize=(96, 96))
trainer.fit(model, data)

pYYBAGR9NfaAKu4tAAF9G6eVzq4572.svg

trainer = d2l.Trainer(max_epochs=10)
data = d2l.FashionMNIST(batch_size=128, resize=(96, 96))
with d2l.try_gpu():
  model = DenseNet(lr=0.01)
  trainer.fit(model, data)

poYBAGR9NfiAVfvuAAF1jb_MRPQ814.svg

8.7.6. 總結與討論

構成 DenseNet 的主要組件是密集塊和過渡層。對于后者,我們需要在組成網絡時通過添加再次縮小通道數量的過渡層來控制維數。在跨層連接方面,不同于ResNet將輸入和輸出相加,DenseNet是在通道維度上拼接輸入和輸出。雖然這些連接操作重用特征來實現計算效率,但不幸的是它們會導致大量的 GPU 內存消耗。因此,應用 DenseNet 可能需要更高效的內存實現,這可能會增加訓練時間 (Pleiss等人,2017 年)。

8.7.7. 練習

為什么我們在過渡層使用平均池而不是最大池?

DenseNet 論文中提到的優點之一是其模型參數比 ResNet 小。為什么會這樣?

DenseNet 被詬病的一個問題是它的高內存消耗。

真的是這樣嗎?嘗試將輸入形狀更改為 224×224憑經驗查看實際的 GPU 內存消耗。

你能想到減少內存消耗的替代方法嗎?您需要如何更改框架?

實施 DenseNet 論文(Huang等人,2017 年)表 1 中提供的各種 DenseNet 版本。

應用 DenseNet 思想設計基于 MLP 的模型。將其應用于第 5.7 節中的房價預測任務。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 連接網絡
    +關注

    關注

    0

    文章

    2

    瀏覽量

    805
收藏 人收藏

    評論

    相關推薦

    【Milk-V Duo 開發板免費體驗】學習:基于Duo開發板的Densenet圖像分類

    densenet121 //網絡不佳可能導致densenet-12.tar.gz下載失敗,可使用下方的離線附件 $ wget https://github.com/onnx/models/raw/main
    發表于 08-19 22:44

    使用加權密集連接卷積網絡的深度強化學習方法說明

    針對深度強化學習中卷積神經網絡(CNN)層數過深導致的梯度消失問題,提出一種將密集連接卷積網絡應用于強化學習的方法。首先,利用密集
    發表于 01-23 10:41 ?3次下載
    使用加權<b class='flag-5'>密集</b><b class='flag-5'>連接</b>卷積<b class='flag-5'>網絡</b>的深度強化學習方法說明

    基于PyTorch的深度學習入門教程之使用PyTorch構建一個神經網絡

    PyTorch的自動梯度計算 Part3:使用PyTorch構建一個神經網絡 Part4:訓練一個神經網絡分類器 Part5:數據并行化 本文是關于Part3的內容。 Part3:使
    的頭像 發表于 02-15 09:40 ?2153次閱讀

    基于PyTorch的深度學習入門教程之PyTorch重點綜合實踐

    前言 PyTorch提供了兩個主要特性: (1) 一個n維的Tensor,與numpy相似但是支持GPU運算。 (2) 搭建和訓練神經網絡的自動微分功能。 我們將會使用一個全連接的ReLU網絡
    的頭像 發表于 02-15 10:01 ?1840次閱讀

    PyTorch教程8.2之使用塊的網絡(VGG)

    電子發燒友網站提供《PyTorch教程8.2之使用塊的網絡(VGG).pdf》資料免費下載
    發表于 06-05 10:11 ?0次下載
    <b class='flag-5'>PyTorch</b>教程8.2之使用塊的<b class='flag-5'>網絡</b>(VGG)

    PyTorch教程8.7密集連接網絡(DenseNet)

    電子發燒友網站提供《PyTorch教程8.7密集連接網絡(DenseNet).pdf》資料免費
    發表于 06-05 10:01 ?0次下載
    <b class='flag-5'>PyTorch</b>教程<b class='flag-5'>8.7</b>之<b class='flag-5'>密集</b><b class='flag-5'>連接</b><b class='flag-5'>網絡</b>(<b class='flag-5'>DenseNet</b>)

    PyTorch教程8.8之設計卷積網絡架構

    電子發燒友網站提供《PyTorch教程8.8之設計卷積網絡架構.pdf》資料免費下載
    發表于 06-05 10:02 ?0次下載
    <b class='flag-5'>PyTorch</b>教程8.8之設計卷積<b class='flag-5'>網絡</b>架構

    PyTorch教程之循環神經網絡

    電子發燒友網站提供《PyTorch教程之循環神經網絡.pdf》資料免費下載
    發表于 06-05 09:52 ?0次下載
    <b class='flag-5'>PyTorch</b>教程之循環神經<b class='flag-5'>網絡</b>

    PyTorch教程14.11之全卷積網絡

    電子發燒友網站提供《PyTorch教程14.11之全卷積網絡.pdf》資料免費下載
    發表于 06-05 11:19 ?0次下載
    <b class='flag-5'>PyTorch</b>教程14.11之全卷積<b class='flag-5'>網絡</b>

    pytorch如何構建網絡模型

      利用 pytorch 來構建網絡模型有很多種方法,以下簡單列出其中的四種?! 〖僭O構建一個網絡模型如下:  卷積層--》Relu 層--》池化層--》全連接層--》Relu 層--
    發表于 07-20 11:51 ?0次下載

    使用PyTorch構建神經網絡

    PyTorch是一個流行的深度學習框架,它以其簡潔的API和強大的靈活性在學術界和工業界得到了廣泛應用。在本文中,我們將深入探討如何使用PyTorch構建神經網絡,包括從基礎概念到高級特性的全面解析。本文旨在為讀者提供一個完整的
    的頭像 發表于 07-02 11:31 ?768次閱讀

    如何使用PyTorch建立網絡模型

    PyTorch是一個基于Python的開源機器學習庫,因其易用性、靈活性和強大的動態圖特性,在深度學習領域得到了廣泛應用。本文將從PyTorch的基本概念、網絡模型構建、優化方法、實際應用等多個方面,深入探討使用
    的頭像 發表于 07-02 14:08 ?470次閱讀

    PyTorch神經網絡模型構建過程

    PyTorch,作為一個廣泛使用的開源深度學習庫,提供了豐富的工具和模塊,幫助開發者構建、訓練和部署神經網絡模型。在神經網絡模型中,輸出層是尤為關鍵的部分,它負責將模型的預測結果以合適的形式輸出。以下將詳細解析
    的頭像 發表于 07-10 14:57 ?566次閱讀

    pytorch中有神經網絡模型嗎

    當然,PyTorch是一個廣泛使用的深度學習框架,它提供了許多預訓練的神經網絡模型。 PyTorch中的神經網絡模型 1. 引言 深度學習是一種基于人工神經
    的頭像 發表于 07-11 09:59 ?815次閱讀

    PyTorch如何實現多層全連接神經網絡

    PyTorch中實現多層全連接神經網絡(也稱為密集連接神經網絡或DNN)是一個相對直接的過程,涉及定義網絡結構、初始化參數、前向傳播、損失
    的頭像 發表于 07-11 16:07 ?1330次閱讀
    大家旺百家乐的玩法技巧和规则 | 新加坡百家乐规则| 亚洲顶级赌场 网投领导者| 汾西县| 百家乐官网奥| 八大胜百家乐娱乐城| 大发888信誉最新娱乐| 百家乐官网怎么玩高手| 百家乐官网策略网络游戏信誉怎么样 | 百家乐四式正反路| 水果机技术打法| 赌百家乐官网的下场| 百家乐官网几点不用补| 百家乐桌子黑色| 百家乐官网真人游戏网| 百家乐软件官方| 大发888官方 hdlsj| 广州百家乐官网赌博机| 在线百家乐博彩| 阿坝县| 足球百家乐官网系统| 全讯网3344111| 百家乐官网博彩平台| 百家乐桌蓝盾在线| 最新皇冠网| 百家乐官网娱乐网77scs| 天博百家乐的玩法技巧和规则| 网上百家乐官网博彩正网| 网上百家乐赌场| 打牌网| 2402 房号 风水| 足彩大赢家| 属虎和属鼠合伙做生意| 飞七棋牌游戏下载| 百家乐官网有诈吗| 大发888casino下载| 太阳城百家乐官网试玩优惠| 百家乐vshow| 百家乐官网怎么样投注| 百家乐光纤冼牌机| 现金百家乐官网下载|