背景
很多同學想學習深度學習,但是無奈自己的機器老舊,要麼顯示卡老舊,要麼不是Nvidia的顯示卡,有的甚至沒有顯示卡。沒有GPU加速,深度學習還怎麼玩?乖乖,怎麼能夠抵擋我成為一名學霸呢。
學霸 vs 學渣
辦法總比困難多,來薅一下資本主義羊毛吧,那就是google的Colab notebooks。jupyter notebook想必大家不陌生,如果你不知道的話,還搞啥深度學習!!!而這個Colab notebooks就原生支援它。這個很久就知道了,一直也沒時間去整理,現在整理一下。話說,Colab notebooks的效果比以往好很多。
前提:這時需要能夠開啟google哦,否則就不用看了。
1 瞭解Colab notebooks1.1 建立notebooks首先,進入Google雲端網盤[1],如下圖:
雲端網盤
建立notebook
設定遠端執行程式,如下圖:
設定遠端執行程式
設定程式執行環境,預設是使用cpu執行的,
設定程式執行環境
可選裝置如下:
裝置選擇
看,除了GPU外,還有TPU。貧窮的我,還不知道TPU是如何使用的。
1.2 基本指令瞭解如果你懂一些linux指令那就更好了。首先,我們看看python的版本。
檢視python版本
在notebooks中使用英文的感嘆號加上linux命令,就可以執行linux命令了。從上面可以看出python版本是3.6。
檢視一下是否有numpy包,如下:
檢視python包
同理看看環境中是否安裝了其他包,例如:pytorch_lightning這個包就沒有安裝。
檢視python包
那麼,我們就來按照這個包,如下:
安裝python包
看看當前程式執行的路徑吧,因為可能要載入資料,那麼就需要用到路徑,如下:
程式路徑
當然,你還是不知道這個路徑在哪。其實你可以理解這就是和linux中與\opt,\home等目錄統計的目錄。帶你看看,按下面操作:
檢視目錄結構
那麼就會有:
目錄結構
系統目錄
瞭解linux系統目錄的同學是不是豁然開朗了呀。下面要操作的就是把我們google driver掛載過來,也就是把一個磁碟加進來,操作如下:
掛在網盤
檢視當前notebook檔案所處路徑如下:
當前notebook檔案路徑
下面就可以愉快地使用自己的訓練資料咯。上傳檔案就相當簡單了,先看一下網盤目錄:
網盤目錄
那麼就資料拖上去就行了。
既然這個平臺支援GPU加速,我們看看到底是什麼GPU。如下:
檢視gpu資訊
可以看出GPU是Tesla T4。對我們苦逼一族,咋知道Tesla系列的GPU效果如何呀!我查閱了其計算效能和2080Ti是一樣的(別高興太早哦),如圖:
T4
2080Ti
查閱網址:https://developer.nvidia.com/zh-cn/cuda-gpus 。那麼到底加速如何,我們跑一個深度學習demo就知道了。
2 執行一個demo如何構建一個notebooks已經知曉了,現在來執行一個深度學習demo吧。這個demo是之前使用textcnn進行文字分類的案例【深度學習】textCNN論文與原理——短文字分類(基於pytorch和torchtext)[2]。程式碼和語料已經放在如下路徑了:
程式碼
為了減少你在原來專案的基礎上修改程式碼,修改後程式碼就粘過來了:
import torchimport matplotlib.pyplot as pltfrom torch import nn, optimfrom torchtext import dataimport randomfrom torch import nnimport osimport numpy as npimport timeif os.getcwd() != '/content/drive/My Drive/Colab Notebooks': os.chdir('/content/drive/MyDrive/Colab Notebooks')device = torch.device("cuda" if torch.cuda.is_available() else "cpu")# device = torch.device("cpu")# 文字內容,使用自定義的分詞方法,將內容轉換為小寫,設定最大長度等TEXT = data.Field(tokenize=lambda x:x.split(), lower=True, fix_length=50, batch_first=True)# 文字對應的標籤LABEL = data.LabelField(dtype=torch.float)def get_dataset(corpus_path, text_field, label_field, datatype): """ 構建torchtext資料集 :param corpus_path: 資料路徑 :param text_field: torchtext設定的文字域 :param label_field: torchtext設定的文字標籤域 :param datatype: 文字的類別 :return: torchtext格式的資料集以及設定的域 """ fields = [('text', text_field), ('label', label_field)] examples = [] with open(corpus_path, encoding='utf8') as reader: for line in reader: content = line.rstrip() if datatype == 'pos': label = 1 else: label = 0 # content[:-2]是由於原始文字最後的兩個內容是空格和.,這裡直接去掉,並將資料與設定的域對應起來 examples.append(data.Example.fromlist([content[:-2], label], fields)) return examples, fields# 構建data資料pos_examples, pos_fields = get_dataset('./corpus/pos.txt', TEXT, LABEL, 'pos')neg_examples, neg_fields = get_dataset('./corpus/neg.txt', TEXT, LABEL, 'neg')all_examples, all_fields = pos_examples + neg_examples, pos_fields + neg_fields# 構建torchtext型別的資料集total_data = data.Dataset(all_examples, all_fields)# 資料集切分train_data, test_data = total_data.split(random_state=random.seed(1000), split_ratio=0.8)# 為該樣本資料構建字典,並將子每個單詞對映到對應數字TEXT.build_vocab(train_data)LABEL.build_vocab(train_data).# 構建迭代(iterator)型別的資料train_iterator, test_iterator = data.BucketIterator.splits((train_data, test_data),batch_size=128,sort=False)class TextCNN(nn.Module): # output_size為輸出類別(2個類別,0和1),三種kernel,size分別是3,4,5,每種kernel有100個 def __init__(self, vocab_size, embedding_dim, output_size, filter_num=100, kernel_list=(3, 4, 5), dropout=0.5): super(TextCNN, self).__init__() self.embedding = nn.Embedding(vocab_size, embedding_dim) # 1表示channel_num,filter_num即輸出資料通道數,卷積核大小為(kernel, embedding_dim) self.convs = nn.ModuleList([ nn.Sequential(nn.Conv2d(1, filter_num, (kernel, embedding_dim)), nn.LeakyReLU(), nn.MaxPool2d((50 - kernel + 1, 1))) for kernel in kernel_list ]) self.fc = nn.Linear(filter_num * len(kernel_list), output_size) self.dropout = nn.Dropout(dropout) def forward(self, x): x = self.embedding(x) # [128, 50, 200] (batch, seq_len, embedding_dim) x = x.unsqueeze(1) # [128, 1, 50, 200] 即(batch, channel_num, seq_len, embedding_dim) out = [conv(x) for conv in self.convs] out = torch.cat(out, dim=1) # [128, 300, 1, 1],各通道的資料拼接在一起 out = out.view(x.size(0), -1) # 展平 out = self.dropout(out) # 構建dropout層 logits = self.fc(out) # 結果輸出[128, 2] return logits# 建立模型text_cnn =TextCNN(len(TEXT.vocab), 128, len(LABEL.vocab)).to(device)print('device:', device)# 選取最佳化器optimizer = optim.Adam(text_cnn.parameters(), lr=1e-3)# 選取損失函式criterion = nn.CrossEntropyLoss()# 繪製結果model_train_acc, model_test_acc = [], []def binary_acc(pred, y): """ 計算模型的準確率 :param pred: 預測值 :param y: 實際真實值 :return: 返回準確率 """ correct = torch.eq(pred, y).float() acc = correct.sum() / len(correct) return accdef train(model, train_data, optimizer, criterion): """ 模型訓練 :param model: 訓練的模型 :param train_data: 訓練資料 :param optimizer: 最佳化器 :param criterion: 損失函式 :return: 該論訓練各批次正確率平均值 """ avg_acc = [] model.train() # 進入訓練模式 for i, batch in enumerate(train_data): pred = model(batch.text.to(device)).cpu() loss = criterion(pred, batch.label.long()) acc = binary_acc(torch.max(pred, dim=1)[1], batch.label) avg_acc.append(acc) optimizer.zero_grad() loss.backward() optimizer.step() # 計算所有批次資料的結果 avg_acc = np.array(avg_acc).mean() return avg_accdef evaluate(model, test_data): """ 使用測試資料評估模型 :param model: 模型 :param test_data: 測試資料 :return: 該論訓練好的模型預測測試資料,檢視預測情況 """ avg_acc = [] model.eval() # 進入測試模式 with torch.no_grad(): for i, batch in enumerate(test_data): pred = model(batch.text.to(device)).cpu() acc = binary_acc(torch.max(pred, dim=1)[1], batch.label) avg_acc.append(acc) return np.array(avg_acc).mean()# 模型訓練start = time.time()for epoch in range(10): train_acc = train(text_cnn, train_iterator, optimizer, criterion) print("epoch = {}, 訓練準確率={}".format(epoch + 1, train_acc)) test_acc = evaluate(text_cnn, test_iterator) print("epoch = {}, 測試準確率={}".format(epoch + 1, test_acc)) model_train_acc.append(train_acc) model_test_acc.append(test_acc)print('total train time:', time.time() - start)# 繪製訓練過程plt.plot(model_train_acc)plt.plot(model_test_acc)plt.ylim(ymin=0.5, ymax=1.01)plt.title("The accuracy of textCNN model")plt.legend(['train', 'dev test'])plt.show()
使用GPU執行時間如下:
程式執行
不使用GPU執行如下:
CPU執行
確實使用GPU會快一點,但是我本機使用GTX 950M執行時間如下:
本地執行
反而更快,還是快了不少,但是比本地CPU去跑還是快了不少。資本主義羊毛不好薅呀。
參考資料[1] Google雲端網盤: https://drive.google.com/drive/my-drive
[2] 【深度學習】textCNN論文與原理——短文字分類(基於pytorch和torchtext): https://piqiandong.blog.csdn.net/article/details/111824774