- 之前由於在本機mac中訓練驗證碼識別,導致mac後來的使用有點卡,另外囊中羞澀,所以考慮用google的colab進行訓練
- 關於google的colab的使用,一般包含兩個方面:
- 關於使用,我們只要把數據上傳到雲磁盤,然後可以在colab頁面上新建一個筆記本(jupyter風格),就可以開始操作代碼了。
- 值得注意的是,如果需要使用GPU,則在筆記本的菜單欄裏選擇 - 代碼執行程序 - 更改運行時的類型- 選擇GPU即可。
- 數據存儲的路徑怎麼看?一般是存儲在/content/gdrive/My Drive/ 路徑下; 下面是我讀取文件夾下的圖片數據
from google.colab import drive
def get_train(path):
X=[]
files=os.listdir(path)
cnt=0
for ele in files:
cnt=cnt+1
if cnt % 100==0:
print(cnt)
img=Image.open(path+ele)
img_array=np.array(img)
X.append(img_array)
return X
# 掛在google的磁盤
drive.mount('/content/gdrive/')
# 要看下該磁盤下的目錄
# for ele in os.listdir("/content/gdrive/My Drive/data/Images"):
# print(ele)
#找到圖片所在目錄
trainx=get_train("/content/gdrive/My Drive/data/Images/")
# 獲取圖片並且轉換
print(len(trainx))
- 數據集是對酒店的中文評論數據,只有0,1兩類; 實際上有些評論是比較中性的,對於這種情況,模型可能會存在一定的誤殺
- 模型採用雙向的LSTM,當訓練集上(train)的準確率達到0.9之後,我們就開始在驗證集(val)上計算準確率,如果在驗證集上的準確率達到0.82,那麼我就終止訓練了,並將模型進行保存。
- 先看下結果
epoch=7的時候,訓練集上的準確率達到96.2%, 驗證集上的準確率達到82.5%
看了幾條,紅款部分是誤殺的;實際上像第一條,也不能定義爲好,數據集的質量有待提升;
- 下面我就丟代碼了,因爲寫的時間比較短,所以代碼的結構不是很好,將就看看吧;
import torchtext import torch from torchtext.vocab import Vectors from torchtext import data import jieba import torch.nn as nn from torchtext.data import BucketIterator import torch.optim as optim import torch.nn.functional as F from google.colab import drive import os drive.mount('/content/gdrive/') # 定義分詞器,爲列處理器服務 def cut_words(text): return list(jieba.cut(text)) # 定義列的處理器 TEXT=torchtext.data.Field(sequential=True,tokenize=cut_words,batch_first=True) LABEL=torchtext.data.Field(sequential=False,use_vocab=False) tv_datafields = [("label", LABEL),("review", TEXT)] test_datafields=[("label", None),("review", TEXT)] # 觀察下數據存儲的位置 for ele in os.listdir("/content/gdrive/"): print(ele) # 讀取訓練和驗證集數據 train,val=torchtext.data.TabularDataset.splits(path="/content/gdrive/My Drive/data/",train="train.csv",validation="val.csv",format="csv",skip_header=True,fields=tv_datafields) train_len=len(train) #vectors = Vectors(name='/content/gdrive/My Drive/data/glove.6B.300d.txt') # 構建字典 TEXT.build_vocab(train) LABEL.build_vocab() vocab_len=TEXT.vocab.__len__() # 構建迭代器 train_iter,val_iter=BucketIterator.splits( (train,val), batch_size=64, sort_key=lambda x: len(x.review), sort_within_batch=False, repeat=False ) # 定義lstm模型 class rnn(nn.Module): def __init__(self, vocab_size, embedding_dim, hidden_dim, output_dim): super(rnn, self).__init__() self.embedding = nn.Embedding(vocab_size, embedding_dim) # 這次沒有采用預訓練的詞向量,發現我自己找的是英文glove預訓練詞向量 #self.embedding.weight.data.copy_(TEXT.vocab.vectors) #self.embedding.weight.requires_grad=True self.rnn= nn.LSTM(embedding_dim, hidden_dim,num_layers=2,batch_first=True,bidirectional=True) #self.fc = nn.Linear(hidden_dim, output_dim) self.fc=nn.Sequential( nn.Linear(hidden_dim*2, output_dim), nn.Sigmoid() ) def forward(self, text): embedded = self.embedding(text) output,(hidden,cell)=self.rnn(embedded) hidden = torch.cat((hidden[-2,:,:], hidden[-1,:,:]), dim = 1) y=self.fc(hidden) return y model=rnn(vocab_size=vocab_len,embedding_dim=300,hidden_dim=128,output_dim=1) model.cuda() lr=0.001 optimizer = optim.Adam(model.parameters(), lr=lr) criterion = nn.BCELoss() for i in range(20): model.train() total_loss=0 total_accurate=0 for batch_idx, batch in enumerate(train_iter): data, target = batch.review.cuda(), batch.label.cuda() optimizer.zero_grad() pred= model(data).squeeze() loss = criterion(pred, target.float()) loss.backward() optimizer.step() total_loss+=loss.item() accurate=((pred>0.5)==target).sum().item() total_accurate+=accurate if batch_idx % 10 ==0: print("EPOCH:{epoch},Batch:{batch},Loss:{loss},Acc:{acc}".format(loss=loss,epoch=i,acc=accurate/64,batch=batch_idx)) avg_acc=total_accurate/train_len avg_loss=total_loss/train_len print("\n"*3) print("avg_acc:{avg_acc},avg_loss:{avg_loss}".format(avg_acc=avg_acc,avg_loss=avg_loss)) # 如果訓練集上的準確率達到95%,那麼就看下模型在驗證集上的準確率 if avg_acc>0.95 : model.eval() val_acc=0.0 for batch_idx, batch in enumerate(val_iter): data, target = batch.review.cuda(), batch.label.cuda() pred= model(data).squeeze() accurate=((pred>0.5)==target).sum().item() val_acc+=accurate print("val_avg_acc:{val_avg_acc}".format(val_avg_acc=val_acc/len(val))) # 如果驗證集上的準確率達到82%,那麼就看下驗證集上的預測結果,並保存模型到final.pkl中,終止循環了 if val_acc/len(val)>0.82: for batch_idx, batch in enumerate(val_iter): data, target = batch.review.cuda(), batch.label.cuda() pred= model(data).squeeze() for i in range(len(data)): source=[TEXT.vocab.itos[ele] for ele in data[i] if TEXT.vocab.itos[ele]!='<pad>' and TEXT.vocab.itos[ele]!='<unk>'] print("真實標籤:{real_tag},預測標籤:{pred_tag},真實評論:{real_review}".format(real_tag=target[i],real_review="".join(source),pred_tag=int((pred>0.5)[i]))) torch.save(model,"final.pkl") break