
NLP任務樣本數(shù)據(jù)不均衡問題解決?案的總結(jié)和數(shù)據(jù)增強回譯
的實戰(zhàn)展?
?錄
在做NLP分類標注等任務的時候,避免不了會遇到樣本不均衡的情況,那么我們就需要處理這個問題,這樣才能使模型有良好的表
現(xiàn)。為此,在收集了?些資料以后,做了?個簡單總結(jié),?便以后回顧(怕跳槽?試的時候問道答不上來)。主要是從數(shù)據(jù)、算法和模型評
價標準這個三個??,來減少數(shù)據(jù)不平衡對模型性能的影響。
?、數(shù)據(jù)層?
當數(shù)據(jù)極度不平衡的時候,最容易相到的解決?案,就是從數(shù)據(jù)層?出發(fā),?類數(shù)據(jù)太少了,那么就增加?類數(shù)據(jù);?類樣本太多了就
刪除?些樣本。不管是2分類還是多分類,樣本不均衡的表現(xiàn)都是樣本數(shù)據(jù)數(shù)?之間存在著很?的差異。為了克服這個問題,實質(zhì)上就要把
數(shù)據(jù)經(jīng)過?定的處理,變得不那么不均衡,?例適當?些。有實驗表明,只要數(shù)據(jù)之間的?例超過了1:4,就會對算法造成偏差影響。針對
數(shù)據(jù)?重失調(diào),就可以對原始數(shù)據(jù)集進?采樣調(diào)整,這?主要是?采樣和過采樣。
1、?采樣(under-sampling)
對?類的數(shù)據(jù)樣本進?采樣來減少該類數(shù)據(jù)的樣本個數(shù)。使?的?般經(jīng)驗規(guī)則,?般??是對樣本數(shù)?超過1W,10W甚?更多,進
??采樣。?般簡單的做法,就是隨機的刪除部分樣本。注意的是,?般很少使??采樣,標注數(shù)據(jù)的成本?較?,?深度學習的?法是數(shù)
據(jù)量越?越好,所以?般都是使?過采樣。
2、過采樣
對?類數(shù)據(jù)的樣本進?采樣來增加?類樣本數(shù)據(jù)的個數(shù)。Smote算法(它就是在少數(shù)類樣本中?KNN?法合成了新樣本)?般?來進
?過采樣的操作,這?有?點不?便的地?就是NLP任務中,不好使?Smote算法,我們的樣本?般都是?本數(shù)據(jù),不是直接的數(shù)字數(shù)據(jù),
只有把?本數(shù)據(jù)轉(zhuǎn)化為數(shù)字數(shù)據(jù)才能進?smote操作。另外現(xiàn)在?般都是基于預訓練模型做微調(diào)的,?本的向量表?也是變化的,所有不能
進?smote算法來增加?類數(shù)據(jù)。那么針對NLP進?過采樣的?些?法有那些呢?
1.最簡單的就是直接復制?類樣本,從?達到增加?類樣本數(shù)據(jù)的?的。這樣的?法缺點也是很明顯的,實際上樣本中并沒有加?新的
特征,特征還是很少,那么就會出現(xiàn)過擬合的問題。
2.對?類樣本數(shù)據(jù)經(jīng)過?定的處理,做?些?的改變。例如隨機的打亂詞的順序,句?的順序;隨機的刪除?些詞,?些句?;裁剪?
本的開頭或者結(jié)尾等。我認為這些??法?合適對語序不是特別重要的任務,像?些對語序特征特別重要的序列任務這種操做就不太
恰當。
3.復述?成:這個就屬性q2q任務,根據(jù)原始問題成成格式更好的問題,然后把新問題替換到問答系統(tǒng)中。
:同義詞替換、隨機插?和隨機交換
5.回譯(backtranslation)把中?——英?(其他的語?)——中?
6.?成對抗?絡(luò)——GAN
個?認為使?復述?成和回譯以及?成對抗?絡(luò)應該是最有效的,因為它們在做數(shù)據(jù)增強的時候,對原始數(shù)據(jù)做的處理使得語義發(fā)?了變
化,但同時?保證了整個語義的完整性。隨機刪除的詞,打亂順序的?式,我認為對數(shù)據(jù)的整個語義破壞太?了。當然,這些技巧都值得在
具體的數(shù)據(jù)集下做對應的實驗,說不定它恰好就在這個數(shù)據(jù)集上起很重要的作?。
另外我??做過的?些實踐,回譯是?較不錯的,在百度翻譯API免費的前提下,?乎沒有成本。另外的復述?成和?成對抗?絡(luò)不知道,
聽說?成對抗?絡(luò)很難也很?煩。
?、算法層?
1、權(quán)重設(shè)置
在訓練的時候給損失函數(shù)直接設(shè)定?定的?例,使得算法能夠?qū)?類數(shù)據(jù)更多的注意?。例如在深度學習中,做?個3分類任務,標簽
a、b、c的樣本?例為1:1:8。在我們的交叉熵損失函數(shù)中就可以?類似這樣的權(quán)重設(shè)置:
ntropyLoss(weight=_numpy(([8,8,1])).float().to(device))
2、新的損失函數(shù)——FocalLoss
importtorch
fromtorchimportnn
rtfunctionalasF
importtime
classfocal_loss():
"""
需要保證每個batch的長度?樣,不然會報錯。
"""
def__init__(lf,alpha=0.25,gamma=2,num_class=2,size_average=True):
"""
focal_loss損失函數(shù),-α(1-yi)**γ*ce_loss(xi,yi)=-α(1-yi)**γ*log(yi)
:paramalpha:
:paramgamma:
:paramnum_class:
:paramsize_average:
"""
super(focal_loss,lf).__init__()
_average=size_average
ifisinstance(alpha,list):
#α可以以list?式輸?,size:[num_class]?于對不同類別精細地賦予權(quán)重
asrtlen(alpha)==num_class
print("Focal_lossalpha={},對每?類權(quán)重進?精細化賦值".format(alpha))
=(alpha)
el:
asrtalpha<1#如果α為?個常數(shù),則降低第?類的影響
print("---Focal_lossalpha={},將對背景類或者?類負樣本進?權(quán)重衰減".format(alpha))
=(num_class)
[0]+=alpha
[1:]+=(1-alpha)
=gamma
defforward(lf,preds,labels):
"""
focal_loss損失計算
:parampreds:預測類別.size:[B,N,C]or[B,C]B:batchN:檢測框數(shù)?C:類別數(shù)
:paramlabels:實際類別.size:[B,N]or[B]
:return:
"""
preds=(-1,(-1))
=()
#這?并沒有直接使?log_softmax,因為后?會?到softmax的結(jié)果(當然你也可以使?log_softmax,然后進?exp操作)
preds_softmax=x(preds,dim=1)
preds_logsoft=(preds_softmax)
#這部分實現(xiàn)nll_loss(crosmpty=log_softmax+nll)
preds_softmax=preds_(1,(-1,1))
preds_logsoft=preds_(1,(-1,1))
=(0,(-1))
loss=-(((1-preds_softmax),),preds_logsoft)
loss=(,loss.t())
_average:
loss=()
el:
loss=()
returnloss
有?個要注意的是
=(0,(-1))
當傳?的labels長度不?致,就會使得的長度不?樣,進?報錯。所有要保證訓練的時候每個bath傳?的數(shù)據(jù)長度要?致。
三、評價?式
在模型評價的時候,我們?般簡單的采?accuracy就可以了。但是在樣本數(shù)據(jù)極度不平衡,特別是那種重點關(guān)注?類識別準確率的時候,
就不能使?accuracy來評價模型了。要使?precision和recall來綜合考慮模型的性能,降低?類分錯的?率。在pytorch中,?般使?
tensor來計算,下?給出關(guān)于tensor計算precision和recall的代碼,主要是熟悉tensor的操作——孰能?巧。
correct+=(predict==label).sum().item()
total+=(0)
train_acc=correct/total
#精確率、recall和F1的計算
foriinrange(_of_class):
ifi==_label:
continue
#TP和FP
lf._true_positives+=((predictions==i)*(gold_labels==i)*()).sum()
lf._fal_positives+=((predictions==i)*(gold_labels!=i)*()).sum()
#TN和FN
lf._true_negatives+=((predictions!=i)*(gold_labels!=i)*()).sum()
lf._fal_negatives+=((predictions!=i)*(gold_labels==i)*()).sum()
#精確率、
precision=float(lf._true_positives)/(float(lf._true_positives+lf._fal_positives)+1e-13)
#recall
recall=float(lf._true_positives)/(float(lf._true_positives+lf._fal_negatives)+1e-13)
#F1
f1_measure=2.*((precision*recall)/(precision+recall+1e-13))
四、數(shù)據(jù)增強實戰(zhàn)——回譯(backtranslate)
嘗試過的庫或者API分別是Translator、TextBlob和百度翻譯的API。其實這些?法都是在?上都有,這?我做?個總結(jié)吧。
1、Translator
?選看看Translator,這個翻譯的庫?的是MyMeory的API,免費的限制是每天1000words。安裝Translator
fromtranslateimportTranslator
直接看?例:
fromtranslateimportTranslator
deftranslation_translate(text):
print(text)
translator=Translator(from_lang="chine",to_lang="english")
translation=ate(text)
print(translation)
print(len(translation))
iflen(translation)>500:
translation=translation[0:500]
print(translation)
translator=Translator(from_lang="english",to_lang="chine")
translation=ate(translation)
print(len(translation))
print(translation)
returntranslation
if__name__=='__main__':
text='國家“?五”重?專項“創(chuàng)新藥物和中藥現(xiàn)代化”(863計劃2004AA2Z3380)。基因?程藥物注射給藥存在著:?漿半衰期較短,?物利?度不?;抗原性較強,易
translation_translate(text)
注意的是text的長度不能超過500。所以這個做回譯還是有?定的限制的,要是text翻譯到中間語?,中間語?的長度超過了500,要做
截取處理,語義就會丟失很多。?且每天的字數(shù)也有限制,?天1000字太少了。但是翻譯效果還不錯,如下:
國家“?五”重?專項“創(chuàng)新藥物和中藥現(xiàn)代化”(863計劃2004AA2Z3380)。基因?程藥物注射給藥存在著:?漿半衰期較短,?物利?度不?;抗原性較強,易引起過敏
Thenational"FifthFive-YearPlan"majorspecial"innovativedrugsandmodernizationofChinemedicine"(863plan2004A2Z380).Theinjectionofgeneticallye
320
Thenational"FifthFive-YearPlan"majorspecial"innovativedrugsandmodernizationofChinemedicine"(863plan2004A2Z380).Theinjectionofgeneticallye
85
國家"?五"重?專項"創(chuàng)新藥物與中藥現(xiàn)代化"(863計劃2004A2Z380)。基因?程藥物的注射存在:?漿半壽命短,?物利?度不?,抗原強,容易引起過敏反應等不
2、TextBlob
類似Translator的使?,但是這個是調(diào)?Google翻譯的API,內(nèi)??不了。
3、百度翻譯API
使?這個來做翻譯的話,需要使?模塊?來實現(xiàn),百度也給出了詳細的教程。我這?的?個需求是需要做數(shù)據(jù)增
強,每條數(shù)據(jù)需要,使?6種語?來做回譯,才能配平樣本?例。直接上代碼:
核?函數(shù):
defbaidu_translate(content,from_lang,to_lang):
appid='×××××××××'
cretKey='××××××××××××××'
httpClient=None
myurl='/api/trans/vip/translate'
q=content
fromLang=from_lang#源語?
toLang=to_lang#翻譯后的語?
salt=t(32768,65536)
sign=appid+q+str(salt)+cretKey
sign=5(()).hexdigest()
myurl=myurl+'?appid='+appid+'&q='+(
q)+'&from='+fromLang+'&to='+toLang+'&salt='+str(
salt)+'&sign='+sign
try:
httpClient=nnection('')
t('GET',myurl)
#respon是HTTPRespon對象
respon=pon()
jsonRespon=().decode("utf-8")#獲得返回的結(jié)果,結(jié)果為json格式
js=(jsonRespon)#將json格式的結(jié)果轉(zhuǎn)換字典結(jié)構(gòu)
dst=str(js["trans_result"][0]["dst"])#取得翻譯后的?本結(jié)果
#print(dst)#打印結(jié)果
returndst
exceptExceptiona:
print('err:',e)
finally:
ifhttpClient:
()
defdo_translate(content,from_lang,to_lang):
iflen(content)>=260:
content=content[0:260]
temp=baidu_translate(content,from_lang,to_lang)
(1)#百度API免費調(diào)?的QPS=1,所以要1s以后才能調(diào)?
iftempisNone:
temp=0
iflen(temp)>=1500:
temp=temp[0:1500]
res=baidu_translate(temp,to_lang,from_lang)
returnres
遇到的?些坑:
注意到,這?使?的是標準版,沒有收費,?前是免費的,但是以后說不定就不會開放免費的版本了。另外QPS=1,也就是1秒內(nèi)并發(fā)能?
只有1,所有這個在代碼中,?了(1),保證API被及時調(diào)?,?不會報錯。最后由于我的中?預料長度很長?都在100-500之
間,翻譯成其他語?,字符數(shù)就有1500-2000多,雖然百度API對字符數(shù)長度放寬了,但是不做長度處理還是會報錯,這個就需要??有
針對性的調(diào)整了。
看?看下?的回譯的結(jié)果,原始的中?就沒有展?出來,這個6種不同語?,回譯的?本。信息都有缺失,但是整體都還在,做數(shù)據(jù)增強就
很不錯了。
本項?屬于有??屬材料制備加?技術(shù)領(lǐng)域。通過系統(tǒng)研究,證明了銅合?納?強化相的形核、長?機理和強化機理,突破了引?納?強化相、控制彌散分布等
這個項?屬于有??屬材料的調(diào)制加?技術(shù)領(lǐng)域。通過系統(tǒng)研究,明確了在銅合?中納?強化相核增長機構(gòu)和強化機構(gòu),突破了納?強化相的引進和擴散分布控制的共
該項?屬于有??屬材料制品加?技術(shù)領(lǐng)域。通過系統(tǒng)研究,通過聯(lián)合合?中納?通過象形核成長機制和加強機制的引進納?強化獎和分布控制的共同技術(shù)難題,開發(fā)
該項?是有??屬材料制造技術(shù)領(lǐng)域的?部分。通過系統(tǒng)研究,確定了在銅合?中?長和加強強化納?芯的機制。1.克服引?和控制增強納?散射的共同技術(shù)困難;開
該項?是有??屬制備和加?技術(shù)領(lǐng)域的?部分。通過引?納?增強相、控制分散分布等常見技術(shù)問題,突破了銅合?中納?增強相的核與?長機理和強化機理,發(fā)展
本項?屬于有??屬的加?和加?技術(shù)領(lǐng)域。通過系統(tǒng)的研究,已經(jīng)確定了納?熱的增長和加強機制。(a)在銅合?中強化核,克服了采?納?熱相和控制彌散分布的
完整代碼:
importpandasaspd
importhashlib
importjson
importurllib
importrandom
importtime
fromtqdmimporttqdm
importcsv
defbaidu_translate(content,from_lang,to_lang):
appid='××××××××××××××
cretKey='××××××××××××××××××××'
httpClient=None
myurl='/api/trans/vip/translate'
q=content
fromLang=from_lang#源語?
toLang=to_lang#翻譯后的語?
salt=t(32768,65536)
sign=appid+q+str(salt)+cretKey
sign=5(()).hexdigest()
myurl=myurl+'?appid='+appid+'&q='+(
q)+'&from='+fromLang+'&to='+toLang+'&salt='+str(
salt)+'&sign='+sign
try:
httpClient=nnection('')
t('GET',myurl)
#respon是HTTPRespon對象
respon=pon()
jsonRespon=().decode("utf-8")#獲得返回的結(jié)果,結(jié)果為json格式
js=(jsonRespon)#將json格式的結(jié)果轉(zhuǎn)換字典結(jié)構(gòu)
dst=str(js["trans_result"][0]["dst"])#取得翻譯后的?本結(jié)果
#print(dst)#打印結(jié)果
returndst
exceptExceptiona:
print('err:',e)
finally:
ifhttpClient:
()
defdo_translate(content,from_lang,to_lang):
iflen(content)>=260:
content=content[0:260]
temp=baidu_translate(content,from_lang,to_lang)
(1)#百度API免費調(diào)?的QPS=1,所以要1s以后才能調(diào)?
(1)#百度API免費調(diào)?的QPS=1,所以要1s以后才能調(diào)?
iftempisNone:
temp=0
iflen(temp)>=1500:
temp=temp[0:1500]
res=baidu_translate(temp,to_lang,from_lang)
returnres
defback_translate(A_title,R_title,A_content,R_content,level,writer):
new_A_titles=[]
new_R_titles=[]
new_A_contents=[]
new_R_contents=[]
new_levels=[]
fromlang_tolangs=[
('zh','en'),
('zh','jp'),
('zh','kor'),
('zh','fra'),
('zh','de'),
('zh','ru')
]
foreleinfromlang_tolangs:
from_lang=ele[0]
to_lang=ele[1]
A_content_new=do_translate(A_content,from_lang,to_lang)
(1)#百度API免費調(diào)?的QPS=1,所以要1s以后才能調(diào)?
R_content_new=do_translate(R_content,from_lang,to_lang)
(1)#百度API免費調(diào)?的QPS=1,所以要1s以后才能調(diào)?
new_A_(A_title)
new_R_(R_title)
new_A_(A_content_new)
new_R_(R_content_new)
new_(level)
ow([A_title,A_content_new,R_title,R_content_new,level])
returnnew_A_titles,new_R_titles,new_A_contents,new_R_contents,new_levels
if__name__=='__main__':
orginal_data=_csv('data/interrelation_',p='t')
print(orginal_y(['Level']).size())
A_titles=orginal_data[(orginal_data['Level']==3)|(orginal_data['Level']==4)]['A_title'].()
R_titles=orginal_data[(orginal_data['Level']==3)|(orginal_data['Level']==4)]['R_title'].()
A_contents=orginal_data[(orginal_data['Level']==3)|(orginal_data['Level']==4)]['A_content'].()
R_contents=orginal_data[(orginal_data['Level']==3)|(orginal_data['Level']==4)]['R_content'].()
levels=orginal_data[(orginal_data['Level']==3)|(orginal_data['Level']==4)]['Level'].()
A_title_new=[]
R_title_new=[]
A_content_new=[]
R_content_new=[]
levels_new=[]
count=0
csv_header=['A_title','A_content','R_title','R_content','Level']
withopen('data/final_augment_data_','w')asf:
writer=(f)
ow(csv_header)
forA_title,R_title,A_content,R_content,levelintqdm(list(zip(A_titles,R_titles,A_contents,R_contents,levels)),desc='回譯執(zhí)?:'):
ifcount>=311:
new_A_titles,new_R_titles,new_A_contents,new_R_contents,new_levels=back_translate(A_title,R_title,A_content,R_content,level,writer)
A_title_(new_A_titles)
R_title_(new_R_titles)
R_title_(new_R_titles)
A_content_(new_A_contents)
R_content_(new_R_contents)
levels_(new_levels)
count+=1
參考?章:
本文發(fā)布于:2023-03-12 09:01:32,感謝您對本站的認可!
本文鏈接:http://www.newhan.cn/zhishi/a/16785828928684.html
版權(quán)聲明:本站內(nèi)容均來自互聯(lián)網(wǎng),僅供演示用,請勿用于商業(yè)和其他非法用途。如果侵犯了您的權(quán)益請與我們聯(lián)系,我們將在24小時內(nèi)刪除。
本文word下載地址:回譯.doc
本文 PDF 下載地址:回譯.pdf
| 留言與評論(共有 0 條評論) |