Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
者:Pulkit Sharma
翻譯:王威力
校對(duì):丁楠雅
本文約3400字,建議閱讀10分鐘。
本文介紹了圖像識(shí)別的深度學(xué)習(xí)模型的建立過(guò)程,通過(guò)陳述實(shí)際比賽的問(wèn)題、介紹模型框架和展示解決方案代碼,為初學(xué)者提供了解決圖像識(shí)別問(wèn)題的基礎(chǔ)框架。
序言
“幾分鐘就可以建立一個(gè)深度學(xué)習(xí)模型?訓(xùn)練就要花幾個(gè)小時(shí)好嗎!我甚至沒(méi)有一臺(tái)足夠好的機(jī)器。”我聽(tīng)過(guò)無(wú)數(shù)次有抱負(fù)的數(shù)據(jù)科學(xué)家這樣說(shuō),他們害怕在自己的機(jī)器上構(gòu)建深度學(xué)習(xí)模型。
其實(shí),你不必在谷歌或其他大型科技公司工作,就可以訓(xùn)練深度學(xué)習(xí)數(shù)據(jù)集。你完全可以用幾分鐘的時(shí)間從頭搭建起你自己的神經(jīng)網(wǎng)絡(luò),而不需要租谷歌的服務(wù)器。Fast.ai的學(xué)生花了18分鐘設(shè)計(jì)出了用于ImageNet數(shù)據(jù)集的一個(gè)模型,接下來(lái)我將在本文中展示類似的方法。
深度學(xué)習(xí)是一個(gè)廣泛的領(lǐng)域,所以我們會(huì)縮小我們的關(guān)注點(diǎn)在圖像分類問(wèn)題上。而且,我們將使用一個(gè)非常簡(jiǎn)單的深度學(xué)習(xí)架構(gòu)來(lái)達(dá)到一個(gè)很好的準(zhǔn)確率。
你可以將本文中的Python代碼作為構(gòu)建圖像分類模型的基礎(chǔ),一旦你對(duì)這些概念有了很好的理解,可以繼續(xù)編程,參加比賽、登上排行榜。
如果你剛開(kāi)始深入學(xué)習(xí),并且對(duì)計(jì)算機(jī)視覺(jué)領(lǐng)域著迷(誰(shuí)不是呢?!)一定要看一看Computer Vision using Deep Learning的課程,它對(duì)這個(gè)酷炫的領(lǐng)域進(jìn)行了全面的介紹,將為你未來(lái)進(jìn)入這個(gè)巨大的就業(yè)市場(chǎng)奠定基礎(chǔ)。
課程鏈接:https://trainings.analyticsvidhya.com/courses/course-v1:AnalyticsVidhya+CVDL101+CVDL101_T1/ about?utm_source=imageclassarticle&utm_ medium=blog
目錄
一、什么是圖像分類以及它的應(yīng)用案例
二、設(shè)置圖像數(shù)據(jù)結(jié)構(gòu)
三、分解模型建立過(guò)程
四、設(shè)置問(wèn)題定義并認(rèn)識(shí)數(shù)據(jù)
五、建立圖像分類模型的步驟
六、開(kāi)始其他挑戰(zhàn)
一、什么是圖像分類以及它的應(yīng)用案例
觀察以下圖片:
你應(yīng)該可以馬上就認(rèn)出它——是一倆豪華車。退一步來(lái)分析一下你是如何得到這個(gè)結(jié)論的——你被展示了一張圖片,然后你將它劃分為“車”這個(gè)類別(在這個(gè)例子中)。簡(jiǎn)單來(lái)說(shuō),這個(gè)過(guò)程就是圖像分類。
很多時(shí)候,圖像會(huì)有許多個(gè)類別。手動(dòng)檢查并分類圖像是一個(gè)非常繁瑣的過(guò)程。尤其當(dāng)問(wèn)題變?yōu)閷?duì)10000張甚至1000000張圖片的時(shí)候,這個(gè)任務(wù)幾乎不可能完成。所以如果我們可以將這個(gè)過(guò)程自動(dòng)化的實(shí)現(xiàn)并快速的標(biāo)記圖像類別,這該有多大的用處啊。
自動(dòng)駕駛汽車是一個(gè)圖像分類在現(xiàn)實(shí)世界應(yīng)用的很好的例子。為了實(shí)現(xiàn)自動(dòng)駕駛,我們可以建立一個(gè)圖像分類模型來(lái)識(shí)別道路上的各種物體,如車輛、人、移動(dòng)物體等。我們將在接下來(lái)的部分中看到更多的應(yīng)用,甚至在我們的身邊就有許多的應(yīng)用。
既然我們已經(jīng)掌握了主題,那么讓我們來(lái)深入研究一下如何構(gòu)建圖像分類模型,它的先決條件是什么,以及如何在Python中實(shí)現(xiàn)它。
二、設(shè)置圖像數(shù)據(jù)結(jié)構(gòu)
我們的數(shù)據(jù)集需要特殊的結(jié)構(gòu)來(lái)解決圖像分類問(wèn)題。我們將在幾個(gè)部分中看到這一點(diǎn),但在往下走之前,請(qǐng)記住這些建議。
你應(yīng)該建立兩個(gè)文件夾,一個(gè)放訓(xùn)練集,另一個(gè)放測(cè)試集。訓(xùn)練集的文件夾里放一個(gè)csv文件和一個(gè)圖像文件夾:
測(cè)試集文件夾中的csv文件和訓(xùn)練集文件夾中的csv文件不同,測(cè)試集文件夾中的csv文件只包含測(cè)試圖像的圖片名,不包括它們的真實(shí)標(biāo)簽。因?yàn)槲覀円ㄟ^(guò)訓(xùn)練訓(xùn)練集中的圖片來(lái)對(duì)測(cè)試集中的圖片進(jìn)行預(yù)測(cè)。
如果你的數(shù)據(jù)集不是這樣的格式,你需要進(jìn)行轉(zhuǎn)換,否則的話預(yù)測(cè)結(jié)果可能有錯(cuò)誤。
三、分解模型搭建的過(guò)程
在我們研究Python代碼之前,讓我們先理解圖像分類模型通常是如何設(shè)計(jì)的。可以將過(guò)程分為4個(gè)部分。每個(gè)步驟需要一定時(shí)間來(lái)執(zhí)行:
第一步:加載和預(yù)處理數(shù)據(jù)——30%時(shí)間
第二步:定義模型架構(gòu)——10%時(shí)間
第三步:訓(xùn)練模型——50%時(shí)間
第四步:評(píng)價(jià)模型表現(xiàn)——10%時(shí)間
接下來(lái)我會(huì)更詳細(xì)地解釋一下上面的每一個(gè)步驟。這一部分非常重要,因?yàn)椴⒎撬心P投际窃诘谝徊綐?gòu)建的。你需要在每次迭代之后返回,對(duì)步驟進(jìn)行微調(diào),然后再次運(yùn)行它。對(duì)基礎(chǔ)概念有一個(gè)扎實(shí)的理解,對(duì)于加速整個(gè)過(guò)程將有很大的幫助。
就深度學(xué)習(xí)模型而言,數(shù)據(jù)非常關(guān)鍵。如果訓(xùn)練集中有大量的圖像,你的圖像分類模型也會(huì)有更大的可能實(shí)現(xiàn)更好的分類效果。此外,根據(jù)所用的框架不同,數(shù)據(jù)的維度不同,效果也不一樣。
因此,對(duì)于關(guān)鍵的數(shù)據(jù)預(yù)處理這一步,我推薦大家瀏覽下面這篇文章,來(lái)對(duì)圖像數(shù)據(jù)的預(yù)處理有一個(gè)更好的理解:
Basics of Image Processing in Pythonhttps://www.analyticsvidhya.com/blog/2014/12/image-processing-python-basics/)
但我們還沒(méi)完全到數(shù)據(jù)預(yù)處理這一步,為了了解我們的數(shù)據(jù)在新的之前沒(méi)見(jiàn)過(guò)的數(shù)據(jù)集中的表現(xiàn)(在預(yù)測(cè)測(cè)試集之前),我們需要先從訓(xùn)練集中劃分出一部分為驗(yàn)證集。
簡(jiǎn)而言之,我們?cè)谟?xùn)練集上訓(xùn)練模型然后在驗(yàn)證集上進(jìn)行驗(yàn)證。如果我們對(duì)在驗(yàn)證集上的結(jié)果滿意,就可以用來(lái)預(yù)測(cè)測(cè)試集的數(shù)據(jù)。
所需時(shí)間:大約2-3分鐘。
這是深度學(xué)習(xí)模型建立過(guò)程中的另一個(gè)重要的步驟。在這個(gè)過(guò)程中,需要思考這樣幾個(gè)問(wèn)題:
還有其他一些問(wèn)題。但這些基本上是模型的超參數(shù),它們對(duì)預(yù)測(cè)結(jié)果起著重要作用。
如何確定這些超參的值?好問(wèn)題!一個(gè)方法是根據(jù)現(xiàn)有的研究選擇這些值。另一個(gè)想法是不斷嘗試這些值,直到找到最好的,但這可能是一個(gè)非常耗時(shí)的過(guò)程。
所需時(shí)間:大約1分鐘定義這個(gè)框架。
對(duì)模型訓(xùn)練,我們需要:
我們還需要定義迭代次數(shù)(epoch)。開(kāi)始階段,我們訓(xùn)練10次(你可以再更改)。
所需時(shí)間:大概5分鐘,來(lái)進(jìn)行模型的結(jié)構(gòu)的學(xué)習(xí)。
最后,我們加載測(cè)試數(shù)據(jù)(圖像)并完成預(yù)處理步驟。然后我們使用訓(xùn)練模型預(yù)測(cè)這些圖像的類別。
所需時(shí)間:1分鐘
四、設(shè)置問(wèn)題定義并認(rèn)識(shí)數(shù)據(jù)
我們將嘗試一個(gè)非常酷的挑戰(zhàn)來(lái)理解圖像分類。我們需要建立一個(gè)模型,可以對(duì)給定的圖像進(jìn)行分類(襯衫、褲子、鞋子、襪子等)。這實(shí)際上是許多電子商務(wù)零售商面臨的一個(gè)問(wèn)題,這使得它成為一個(gè)更有趣的計(jì)算機(jī)視覺(jué)問(wèn)題。
這個(gè)挑戰(zhàn)被稱為“識(shí)別服裝”,是我們?cè)跀?shù)據(jù)黑客平臺(tái)上遇到的實(shí)踐問(wèn)題之一。你必須注冊(cè)并從上面的鏈接下載數(shù)據(jù)集。
“識(shí)別服裝”比賽鏈接:https://datahack.analyticsvidhya.com/contest/practice-problem-identify-the-apparels/)數(shù)據(jù)黑客平臺(tái):https://datahack.analyticsvidhya.com/
一共有70000圖像(28x28維),其中60000來(lái)自訓(xùn)練集,10000來(lái)自測(cè)試集。訓(xùn)練圖像已經(jīng)預(yù)先被打上了衣服類別的標(biāo)簽,一共10個(gè)類別。測(cè)試集沒(méi)有標(biāo)簽。這個(gè)比賽是對(duì)測(cè)試集的圖像進(jìn)行識(shí)別。
我們將在Google Colab搭建模型,因?yàn)樗峁┟赓M(fèi)的GPU。
Google Colab:https://colab.research.google.com/
五、建立圖像分類模型的步驟
接下來(lái)是時(shí)候展示你的Python技巧啦,最終我們到了執(zhí)行階段!
主要步驟如下:
下面詳細(xì)介紹以上步驟。
因?yàn)槲覀儗腉oogle Drive link導(dǎo)入數(shù)據(jù),我們需要在Google Colab notebook上增加幾條代碼。新建Python3 notebook,寫(xiě)下下面的代碼:
!pip install PyDrive
這一步是安裝PyDrive。下面導(dǎo)入需要的庫(kù):
import os from pydrive.auth import GoogleAuth from pydrive.drive import GoogleDrive from google.colab import auth from oauth2client.client import GoogleCredentials
下面創(chuàng)建drive變量訪問(wèn)Google Drive:
auth.authenticate_user() gauth=GoogleAuth() gauth.credentials=GoogleCredentials.get_application_default() drive=GoogleDrive(gauth)
需要用Google Drive上傳文件的ID來(lái)下載數(shù)據(jù)集:
download=drive.CreateFile({'id': '1BZOv422XJvxFUnGh-0xVeSvgFgqVY45q'})
把id的部分替換為你的文件夾的ID。接下來(lái)將下載文件夾并解壓。
download.GetContentFile('train_LbELtWX.zip') !unzip train_LbELtWX.zip
每次啟動(dòng)notebook都需要運(yùn)行以上代碼。
import keras from keras.models import Sequential from keras.layers import Dense, Dropout, Flatten from keras.layers import Conv2D, MaxPooling2D from keras.utils import to_categorical from keras.preprocessing import image import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split from keras.utils import to_categorical from tqdm import tqdm
train=pd.read_csv('train.csv')
接下來(lái),我們將讀入訓(xùn)練集,存儲(chǔ)為list,最終轉(zhuǎn)換為numpy array。
# We have grayscale images, so while loading the images we will keep grayscale=True, if you have RGB images, you should set grayscale as False train_image=[] for i in tqdm(range(train.shape[0])): img=image.load_img('train/'+train['id'][i].astype('str')+'.png', target_size=(28,28,1), grayscale=True) img=image.img_to_array(img) img=img/255 train_image.append(img) X=np.array(train_image)
這是一個(gè)多分類問(wèn)題(10個(gè)類別),需要對(duì)標(biāo)簽變量進(jìn)行one-hot編碼。
y=train['label'].values y=to_categorical(y)
X_train, X_test, y_train, y_test=train_test_split(X, y, random_state=42, test_size=0.2)
我們將建立一個(gè)簡(jiǎn)單的結(jié)構(gòu),有2個(gè)卷積層,一個(gè)隱藏層一個(gè)輸出層。
model=Sequential() model.add(Conv2D(32, kernel_size=(3, 3),activation='relu',input_shape=(28,28,1))) model.add(Conv2D(64, (3, 3), activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(128, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(10, activation='softmax'))
接下來(lái)編譯模型。
model.compile(loss='categorical_crossentropy',optimizer='Adam',metrics=['accuracy'])
在這一步,我們將訓(xùn)練訓(xùn)練集的數(shù)據(jù),在驗(yàn)證集上進(jìn)行驗(yàn)證。
model.fit(X_train, y_train, epochs=10, validation_data=(X_test, y_test))
我們將首先遵循處理訓(xùn)練數(shù)據(jù)集時(shí)執(zhí)行的步驟。加載測(cè)試圖像并預(yù)測(cè)分類結(jié)果,用model.predict_classes()函數(shù)預(yù)測(cè)它們的類。
download=drive.CreateFile({'id': '1KuyWGFEpj7Fr2DgBsW8qsWvjqEzfoJBY'}) download.GetContentFile('test_ScVgIM0.zip') !unzip test_ScVgIM0.zip
首先導(dǎo)入測(cè)試集:
test=pd.read_csv('test.csv')
接下來(lái),讀于數(shù)據(jù)并存儲(chǔ)測(cè)試集:
test_image=[] for i in tqdm(range(test.shape[0])): img=image.load_img('test/'+test['id'][i].astype('str')+'.png', target_size=(28,28,1), grayscale=True) img=image.img_to_array(img) img=img/255 test_image.append(img) test=np.array(test_image) # making predictions prediction=model.predict_classes(test)
還需要新建一個(gè)提交文件夾,用來(lái)上傳DataHack平臺(tái)。
download=drive.CreateFile({'id': '1z4QXy7WravpSj-S4Cs9Fk8ZNaX-qh5HF'}) download.GetContentFile('sample_submission_I5njJSF.csv') # creating submission file sample=pd.read_csv('sample_submission_I5njJSF.csv') sample['label']=prediction sample.to_csv('sample_cnn.csv', header=True, index=False)
下載sample_cnn.csv文件并上傳到比賽的頁(yè)面,生成你的排名。這提供了一個(gè)幫助你開(kāi)始解決圖像分類問(wèn)題的基礎(chǔ)方案。
你可以嘗試調(diào)整超參數(shù)和正則化來(lái)提高模型效果。也可以通過(guò)閱讀下面這篇文章來(lái)理解調(diào)參的細(xì)節(jié)。
A Comprehensive Tutorial to learn Convolutional Neural Networks from Scratchhttps://www.analyticsvidhya.com/blog/2018/12/guide-convolutional-neural-network-cnn/
六、開(kāi)啟一個(gè)新的挑戰(zhàn)
讓我們嘗試在其他的數(shù)據(jù)集進(jìn)行測(cè)試。這部分,我們將解決Identify the Digits上的這個(gè)問(wèn)題。
Identify the Digits比賽鏈接:https://datahack.analyticsvidhya.com/contest/practice-problem-identify-the-digits/
在你往下看之前,請(qǐng)嘗試自己來(lái)解決這個(gè)挑戰(zhàn)。你已經(jīng)收獲了解決問(wèn)題的工具,只需要使用它們。當(dāng)你遇到困難的時(shí)候可以再回來(lái)檢查你的過(guò)程和結(jié)果。
在這個(gè)挑戰(zhàn)中,我們需要識(shí)別給定圖像中的數(shù)字。一共有70000張圖片,49000張訓(xùn)練圖像有標(biāo)簽,剩下的21000張為測(cè)試圖片無(wú)標(biāo)簽。
準(zhǔn)備好了嗎?好!打開(kāi)新的Python3 notebook,運(yùn)行下面的代碼:
# Setting up Colab !pip install PyDrive import os from pydrive.auth import GoogleAuth from pydrive.drive import GoogleDrive from google.colab import auth from oauth2client.client import GoogleCredentials auth.authenticate_user() gauth=GoogleAuth() gauth.credentials=GoogleCredentials.get_application_default() drive=GoogleDrive(gauth) # Replace the id and filename in the below codes download=drive.CreateFile({'id': '1ZCzHDAfwgLdQke_GNnHp_4OheRRtNPs-'}) download.GetContentFile('Train_UQcUa52.zip') !unzip Train_UQcUa52.zip # Importing libraries import keras from keras.models import Sequential from keras.layers import Dense, Dropout, Flatten from keras.layers import Conv2D, MaxPooling2D from keras.utils import to_categorical from keras.preprocessing import image import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split from keras.utils import to_categorical from tqdm import tqdm train=pd.read_csv('train.csv') # Reading the training images train_image=[] for i in tqdm(range(train.shape[0])): img=image.load_img('Images/train/'+train['filename'][i], target_size=(28,28,1), grayscale=True) img=image.img_to_array(img) img=img/255 train_image.append(img) X=np.array(train_image) # Creating the target variable y=train['label'].values y=to_categorical(y) # Creating validation set X_train, X_test, y_train, y_test=train_test_split(X, y, random_state=42, test_size=0.2) # Define the model structure model=Sequential() model.add(Conv2D(32, kernel_size=(3, 3),activation='relu',input_shape=(28,28,1))) model.add(Conv2D(64, (3, 3), activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(128, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(10, activation='softmax')) # Compile the model model.compile(loss='categorical_crossentropy',optimizer='Adam',metrics=['accuracy']) # Training the model model.fit(X_train, y_train, epochs=10, validation_data=(X_test, y_test)) download=drive.CreateFile({'id': '1zHJR6yiI06ao-UAh_LXZQRIOzBO3sNDq'}) download.GetContentFile('Test_fCbTej3.csv') test_file=pd.read_csv('Test_fCbTej3.csv') test_image=[] for i in tqdm(range(test_file.shape[0])): img=image.load_img('Images/test/'+test_file['filename'][i], target_size=(28,28,1), grayscale=True) img=image.img_to_array(img) img=img/255 test_image.append(img) test=np.array(test_image) prediction=model.predict_classes(test) download=drive.CreateFile({'id': '1nRz5bD7ReGrdinpdFcHVIEyjqtPGPyHx'}) download.GetContentFile('Sample_Submission_lxuyBuB.csv') sample=pd.read_csv('Sample_Submission_lxuyBuB.csv') sample['filename']=test_file['filename'] sample['label']=prediction sample.to_csv('sample.csv', header=True, index=False)
在練習(xí)題頁(yè)面上提交這個(gè)文件,你會(huì)得到一個(gè)相當(dāng)不錯(cuò)的準(zhǔn)確率。這是一個(gè)好的開(kāi)端,但總有改進(jìn)的余地。繼續(xù)肝,看看你是否可以改進(jìn)我們的基本模型。
尾聲
誰(shuí)說(shuō)深度學(xué)習(xí)模型需要數(shù)小時(shí)或數(shù)天的訓(xùn)練。我的目的是展示你可以在雙倍快速的時(shí)間內(nèi)想出一個(gè)相當(dāng)不錯(cuò)的深度學(xué)習(xí)模式。你應(yīng)該接受類似的挑戰(zhàn),并嘗試從你的終端編碼它們。什么都比不上通過(guò)實(shí)踐來(lái)學(xué)習(xí)!
頂尖的數(shù)據(jù)科學(xué)家和分析師甚至在黑客比賽開(kāi)始之前就已經(jīng)準(zhǔn)備好了這些代碼。他們使用這些代碼在深入詳細(xì)分析之前提前提交。先給出基準(zhǔn)解決方案,然后使用不同的技術(shù)改進(jìn)模型。
你覺(jué)得這篇文章有用嗎?請(qǐng)?jiān)谙旅娴脑u(píng)論部分分享你的反饋。
原文標(biāo)題:
Build your First Image Classification Model in just 10 Minutes!
原文鏈接:
https://www.analyticsvidhya.com/blog/2019/01/build-image-classification-model-10-minutes/
編輯:黃繼彥
譯者簡(jiǎn)介
王威力,求職狗,在香港科技大學(xué)學(xué)習(xí)大數(shù)據(jù)科技。感覺(jué)數(shù)據(jù)科學(xué)很有難度,也很有意思,還在學(xué)(tu)習(xí)(tou)中。一個(gè)人肝不動(dòng)的文獻(xiàn),來(lái)數(shù)據(jù)派follow大佬一起肝。
— 完 —
關(guān)注清華-青島數(shù)據(jù)科學(xué)研究院官方微信公眾平臺(tái)“THU數(shù)據(jù)派”及姊妹號(hào)“數(shù)據(jù)派THU”獲取更多講座福利及優(yōu)質(zhì)內(nèi)容。
Yii2數(shù)據(jù)庫(kù)讀寫(xiě)分離使用流程分享】
大家好,今天我要來(lái)分享一下我在使用Yii2框架進(jìn)行數(shù)據(jù)庫(kù)的讀寫(xiě)分離時(shí)的一些經(jīng)驗(yàn)和心得體會(huì)。希望能幫助到大家。
我們要明確什么是讀寫(xiě)分離。簡(jiǎn)單來(lái)說(shuō),就是將數(shù)據(jù)庫(kù)的讀操作和寫(xiě)操作分開(kāi)處理,以提高系統(tǒng)的并發(fā)能力和性能。在Yii2中,我們可以通過(guò)配置實(shí)現(xiàn)這一功能。
第一步:安裝Yii2并創(chuàng)建新的項(xiàng)目。如果你還沒(méi)有安裝Yii2框架,可以訪問(wèn)官方網(wǎng)站下載并按照指引進(jìn)行安裝。創(chuàng)建新項(xiàng)目后,進(jìn)入項(xiàng)目目錄。
第二步:配置數(shù)據(jù)庫(kù)連接。打開(kāi)配置文件`config/web.php`,在`components`部分添加以下代碼:
```
這是一款現(xiàn)代化、快速、高效、便捷、靈活、方便擴(kuò)展的應(yīng)用開(kāi)發(fā)骨架。基于Yii2高級(jí)框架的快速開(kāi)發(fā)應(yīng)用引擎。它是一個(gè)重量級(jí)全棲框架,為二次開(kāi)發(fā)而生!
https://github.com/jianyan74/rageframe2
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。