2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
#Datawhale #AIsummercamp#summercamp
Die Aufgabe des Wettbewerbs besteht darin, festzustellen, ob es sich bei einem Gesichtsbild um ein Deepfake-Bild handelt, und einen Wahrscheinlichkeitswert auszugeben, dass es sich um ein Deepfake-Bild handelt. Die Teilnehmer müssen Erkennungsmodelle entwickeln und optimieren, um mit verschiedenen Deepfake-Generierungstechnologien und komplexen Anwendungsszenarien zurechtzukommen und dadurch die Genauigkeit und Robustheit der Deepfake-Bilderkennung zu verbessern.
Die Label-Datei train_label.txt des Trainingssatzes wird zum Training des Modells verwendet, während die Label-Datei val_label.txt des Validierungssatzes nur zur Modelloptimierung verwendet wird. Beispielsweise enthält in train_label.txt oder val_label.txt jede Zeile zwei durch Kommas getrennte Teile. Der erste Teil ist der Dateiname (Suffix .mp4), der zweite Teil ist der eigentliche Wert.
Ein Zielwert von 1 weist auf Deep-Fake-Audio und -Video hin, und ein Zielwert von 0 weist auf echte Gesichtsaudio- und -videos hin.
Nachfolgend finden Sie Beispiele von train_label.txt und val_label.txt:
train_label.txt
video_name,target
96b04c80704f02cb426076b3f624b69e.mp4,0
16fe4cf5ae8b3928c968a5d11e870360.mp4,1
val_label.txt
video_name,target
f859cb3510c69513d5c57c6934bc9968.mp4,0
50ae26b3f3ea85babb2f9dde840830e2.mp4,1
Jede Zeile in der Datei enthält zwei durch Kommas getrennte Teile. Der erste Teil ist der Name der Videodatei und der zweite Teil ist der Deepfake-Score, der der Modellvorhersage entspricht (d. h. der Wahrscheinlichkeitswert der Probe, die zum Deepfake-Video gehört). Bitte beachten Sie die untenstehende Einreichungsvorlage:
prediction.csv
video_name,score
658042526e6d0c199adc7bfeb1f7c888.mp4,0.123456
a20cf2d7dea580d0affc4d85c9932479.mp4,0.123456
Die zweite Phase folgt auf die erste Phase, in der das öffentliche Testset veröffentlicht wird. Die Teilnehmer müssen die Vorhersageergebnisdatei „prediction_test.csv“ des Testsatzes an das System übermitteln und in Echtzeit Online-Feedback zu den Testergebnisergebnissen geben.
Nach der zweiten Phase gelangen die 30 besten Teams in die dritte Phase. Zu diesem Zeitpunkt müssen die Teilnehmer Code-Docker- und technische Berichte einreichen. Zu den Docker-Anforderungen gehören der ursprüngliche Trainingscode und die Test-API (die Funktionseingabe ist der Bildpfad und die Ausgabe ist der vom Modell vorhergesagte Deepfake-Score). Der Sponsor überprüft den Algorithmuscode und führt ihn erneut aus, um den Trainingsprozess und die Testergebnisse zu reproduzieren.
Es darf nur ein einziges Modell eingereicht werden und die gültigen Netzwerkparameter dürfen 200 MB nicht überschreiten (verwenden SiethopModellparameter für Werkzeugstatistiken).
Es ist nur ein Vormodelltraining mit ImageNet1K zulässig. Erweiterte Beispiele, die auf der Grundlage des veröffentlichten Trainingssatzes generiert wurden (über Datenerweiterungs-/Deepfake-Tools), können für das Training verwendet werden, diese Tools müssen jedoch in der dritten Stufe zur Reproduktion eingereicht werden.
Der Bewertungsindex verwendet hauptsächlich die AUC unter der ROC-Kurve als Index. Der Wertebereich der AUC liegt normalerweise innerhalb0.5-1dazwischen, sonst denken wirDies ist kein gutes Modell für maschinelles Lernen . Je näher die AUC bei 1 liegt, desto besser ist das Modell. Wenn AUC mehrdeutige Ranking-Ergebnisse liefert, verwenden wir **TPR (True Positive Rate)** als Hilfsreferenz. Die entsprechende Methode ist natürlich FPR.
F1-ErgebnisseEs ist auch ein Indikator, auf den wir uns beziehen können: Es handelt sich um die Präzisionsrate und die Rückrufrateharmonische Mittel。
F1_S-Kern = 2 ∗ (TP) / (2 TP + FN + FP) F1_Score = 2*(TP)/(2TP+FN+FP)F1_SKern=2∗(TP)/(2TP+FN+FP)
Bevor wir uns mit maschinellem Lernen befassen, sollten wir zwei wichtige Konzepte überprüfen:GenauigkeitUndAbrufen。
Genauigkeit: Präzision = TPTP + FP Präzision = frac{TP}{TP+FP}PEmpf.ichchchchchSichchchchchÖN=TP+FPTP, das zur Messung des Modells verwendet wirdÜberprüfen Sie die Leistung, der Anteil der Proben, die unter den korrekt vorhergesagten Proben als positiv vorhergesagt werden.
Abrufen: Rückruf = TPTP + FN Rückruf = frac{TP}{TP+FN}RecAll=TP+FNTP, das zur Messung des Modells verwendet wirdSuchleistung, der Anteil der tatsächlich positiven Proben an den voraussichtlich positiven Proben.
True-Positiv-Rate (TPR):
TPR = TP / (TP + FN)
Falsch-Positiv-Rate (FPR):
FPR = FP / (FP + TN)
In:
TP: Das Angriffsbeispiel wird korrekt als Angriff identifiziert;
TN: Echte Proben werden korrekt als echt identifiziert;
FP: Echte Proben werden fälschlicherweise als Angriffe identifiziert;
FN: Das Angriffsbeispiel wird fälschlicherweise als real identifiziert.
Referenzen: Aghajan, H., Augusto, JC, & Delgado, RLC (Hrsg.) (Wenn der im Titel angegebene Link nicht geöffnet werden kann, klicken Sie bitte:)ganzes Buch)
Hier ist mein TPR-Berechnungsskript:
l1 = [0,1,1,1,0,0,0,1]
l2 = [0,1,0,1,0,1,0,0]
def accuracy(y_true, y_pred):
# 正确预测数初始化一个简单计数器
correct_counter = 0
# 遍历y_true, y_pred中所有元素
# zip函数接受多个元组,返回他们组成的列表
for yt, yp in zip(y_true, y_pred):
if yt == yp:
# 如果预测标签与真实标签相同,则增加计数器
correct_counter += 1
# 返回正确率,正确标签数/总标签数
return correct_counter / len(y_true)
def false_positive(y_true, y_pred):
# 初始化假阳性样本计数器
fp = 0
# 遍历y_true,y_pred中所有元素
for yt, yp in zip(y_true, y_pred):
# 若真实标签为负类但预测标签为正类,计数器增加
if yt == 0 and yp == 1:
fp += 1
return fp
def false_negative(y_true, y_pred):
# 初始化假阴性样本计数器
fn = 0
# 遍历y_true,y_pred中所有元素
for yt, yp in zip(y_true, y_pred):
# 若真实标签为正类但预测标签为负类,计数器增加
if yt == 1 and yp == 0:
fn += 1
return fn
def true_positive(y_true, y_pred):
# 初始化真阳性样本计数器
tp = 0
# 遍历y_true,y_pred中所有元素
for yt, yp in zip(y_true, y_pred):
# 若真实标签为正类且预测标签也为正类,计数器增加
if yt == 1 and yp == 1:
tp += 1
return tp
def true_negative(y_true, y_pred):
# 初始化真阴性样本计数器
tn = 0
# 遍历y_true,y_pred中所有元素
for yt, yp in zip(y_true, y_pred):
# 若真实标签为负类且预测标签也为负类,计数器增加
if yt == 0 and yp == 0:
tn += 1
# 返回真阴性样本数
return tn
# 您可以尝试更好的精确度计算方式
def accuracy_v2(y_true, y_pred):
# 真阳性样本数
tp = true_positive(y_true, y_pred)
# 假阳性样本数
fp = false_positive(y_true, y_pred)
# 假阴性样本数
fn = false_negative(y_true, y_pred)
# 真阴性样本数
tn = true_negative(y_true, y_pred)
# 准确率
accuracy_score = (tp + tn) / (tp + tn + fp + fn)
return accuracy_score
# F1-score的计算方法
def f1(y_true,y_pred):
p = precision(y_true, y_pred)
r = recall(y_true,y_pred)
score = 2*p*r/(p+r)
return score
Wenn eine Klassifizierung erforderlich ist, benötigen Sie möglicherweise einen Schwellenwert. Seine Beziehung zum vorhergesagten Wert ist wie folgt:
Vorhersage = Wahrscheinlichkeit > Schwellenwert Vorhersage = Wahrscheinlichkeit > SchwellenwertPReDichchchchchCTichchchchchÖN=ProBabymichchchchchTj>THAuflösungHÖmD
Nachdem Sie AUC kennengelernt haben, ist der Protokollverlust eine weitere wichtige Kennzahl, die Sie lernen sollten. Für binäre Klassifizierungsprobleme definieren wir den Protokollverlust als:
L og Verlust = − Ziel ∗ log ( p ) − ( 1 − Ziel ) ∗ log ( 1 − p ) LogVerlust = -Ziel*log(p) - (1-Ziel)*log(1-p)MÖgLoss=−TARGtT∗mÖG(P)−(1−TARGtT)∗mÖG(1−P)
Unter diesen ist der Zielwert 0 oder 1 und der vorhergesagte Wert ist die Wahrscheinlichkeit, dass die Stichprobe zur Kategorie 1 gehört. Der Protokollverlust bestraft sowohl sehr sichere als auch sehr falsche Vorhersagen. Je kleiner der Protokollverlust ist, desto näher liegt die vom Modell vorhergesagte Wahrscheinlichkeit am Zielwert.
Wir können diese Indikatoren auch bei Klassifizierungsproblemen verwenden:
# “word count” 的缩写,是一个用于计数的 Unix 命令。-l 只计算行数
!wc -l /kaggle/input/ffdv-sample-dataset/ffdv_phase1_sample/train_label.txt
!wc -l /kaggle/input/ffdv-sample-dataset/ffdv_phase1_sample/val_label.txt
Wir müssen nur die Anzahl der Zeilen zählen, was die Anzahl der Stichproben angibt.
from IPython.display import Video
Video("/kaggle/input/ffdv-sample-dataset/ffdv_phase1_sample/valset/00882a2832edbcab1d3dfc4cc62cfbb9.mp4", embed=True)
„Video“ erstellt ein Videoobjekt und „Einbetten“ bedeutet, dass bei der Einstellung „True“ der Videoplayer direkt in der Ausgabe der Notebook-Zelle angezeigt wird.
Nachdem Sie die Basislinie von Kaggle ausgeführt haben, sollten Sie Ergebnisse wie diese sehen:
!pip install moviepy librosa matplotlib numpy timm
Dokumentationslinks für verwendete Bibliotheken:
filme
librosa(Librosa ist eine sehr leistungsstarke Bibliothek eines Drittanbieters für die Verarbeitung von Python-Sprachsignalen. In dieser Basis verwenden wir hauptsächlich die Generierung und Konvertierung von MEL-Spektrogrammen.)
matplotlib
numpy
Timm(Bildklassifizierungsmodellbibliothek, schnell verschiedene Sota-Modelle erstellen)
Was ist SOTA? Der vollständige Name von SOTA lautet State of the Arts und bezieht sich auf das beste Modell in diesem Bereich. SOTA schneidet bei einigen Benchmark-Datensätzen sehr gut ab.
Nicht-Ende-zu-Ende-Modell (Pipeline): Zunächst müssen wir verstehen, was ein Ende ist. Die beiden Enden beziehen sich auf das Eingabeende bis zum Ausgabeende. Der traditionelle maschinelle Lernprozess besteht aus mehreren voneinander unabhängigen Modulen. Das Ergebnis des letzteren Moduls hängt vom Niveau des vorherigen Ergebnisses ab und wirkt sich auf das gesamte Trainingsergebnis aus.
End-to-End-Modell (End-to-End): Zunächst müssen Sie verstehen, dass die Vorhersage vom Eingabeende bis zum Ausgabeende generiert wird. Dieses Vorhersageergebnis weist im Vergleich zum tatsächlichen Ergebnis einen Fehler auf (dies muss berücksichtigt werden). dass die Kernaufgabe des maschinellen Lernens immer noch bestehtvorhersagen ), wird dieser Fehler an jede Schicht im neuronalen Netzwerk zurückgegeben und die Gewichte und Parameter des Modells werden angepasst, bis das Modell konvergiert oder die von uns erwarteten Ergebnisse erhalten werden. Wenn wir es als Kontrollsystem betrachten, handelt es sich um ein Regelsystem mit geschlossenem Regelkreis. (z. B. BP neuronales Netzwerk)
Sequenz-zu-Sequenz (seq2seq): Dies ist eine allgemeineEnde zu EndeSequenzvorhersagemethode, deren Struktur aus einem Encoder und einem Decoder besteht. Wenn Sie den Frage- und Antwortdatensatz zum Codieren/Decodieren verwenden, können Sie einen Frage-und-Antwort-Roboter erhalten.
Die Frage geht auf Baseline selbst zurück: Was ist Baseline?Baseline bezieht sich normalerweise auf ein einfaches und leicht zu implementierendes Basismodell.
Bei der Optimierung des Algorithmus und der Parameteranpassung besteht die Aufgabe von Baseline darin, sich selbst zu vergleichen, um das Modell immer besser zu machen.
Benchmark ist ebenfalls ein wichtiges Konzept, seine Bedeutung istBenchmarks . Es bezieht sich normalerweise auf eine standardisierte Bewertungs- und Vergleichsmethode der Leistung von Algorithmen, Modellen oder Methoden, die zur Messung der Unterschiede zwischen Modellen verwendet wird.
Sie können sie häufig auf Modell-Benchmarking-Sites sehen.Zum BeispielSi Nan。
Beim Ausführen der Baseline ist ein CUDA-Konfigurationsfehler aufgetreten. Bitte verwenden Sie einen anderen Accelerator:
import torch
# 设置pytorch的种子
torch.manual_seed(0)
# deterministic当设置为False时,cuDNN将允许一些操作的非确定性优化
torch.backends.cudnn.deterministic = False
# benchmark设置为true允许cuDNN在每个前向传播中自动寻找最适合当前配置的卷积算法,以提高性能。
torch.backends.cudnn.benchmark = True
# 导入必要的库,我们需要用到cv2,glob,os,PIL
import torchvision.models as models
import torchvision.transforms as transforms
import torchvision.datasets as datasets
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.autograd import Variable
from torch.utils.data.dataset import Dataset
import timm
import time
import pandas as pd
import numpy as np
import cv2, glob, os
from PIL import Image
Generate_mel_spectrogram akzeptiert Parameter wie den Videodateipfad, die Anzahl der Mel-Frequenzfilter, die höchste Frequenz (die den berechneten Spektrumbereich steuert) und die Zielbildgröße.
import moviepy.editor as mp
import librosa
import numpy as np
import cv2
def generate_mel_spectrogram(video_path, n_mels=128, fmax=8000, target_size=(256, 256)):
# 提取音频
audio_path = 'extracted_audio.wav'
# video_path 应该是之前定义的变量,包含了要处理的视频文件的路径。创建了一个 VideoFileClip 对象,存储在 video 变量中。
video = mp.VideoFileClip(video_path)
# video.audio 访问视频的音频轨道。write_audiofile() 方法将音频写入文件。verbose=False: 设置为False表示不在控制台输出处理进度。logger=None: 设置为None表示不使用日志记录器。实际上我们做这个预测没有这样的需求,也就不消耗占存。
# 其默认参数:write_audiofile(self, filename, fps=None, nbytes=2, buffersize=2000, codec=None, bitrate=None, ffmpeg_params=None, write_logfile=False, verbose=True, logger='bar')
video.audio.write_audiofile(audio_path, verbose=False, logger=None)
# 加载音频文件,加载采样率
y, sr = librosa.load(audio_path)
# 生成MEL频谱图(梅尔频谱图,与之相对应的有mel倒频谱图)
# 默认参数:librosa.feature.melspectrogram(y=None, sr=22050, S=None, n_fft=2048, hop_length=512, power=2.0, **kwargs)
# 参数解释:y:音频时间序列,sr:采样率,n_mels 是指在计算梅尔频谱图时,将频谱图划分为多少个梅尔频率滤波器(Mel filters),其决定了最终生成的梅尔频谱图的分辨率,也可以理解为梅尔频谱图的高度。
S = librosa.feature.melspectrogram(y=y, sr=sr, n_mels=n_mels)
# 将频谱图转换为dB单位,S:输入功率,ref:作为参考,如果是标量,则振幅 abs(S) 相对于 ref: 10 * log10(S / ref) 进行缩放。此处np.max指的是将谱图中的最大值作为参考值,这也是一种常用的参考值取法
S_dB = librosa.power_to_db(S, ref=np.max)
# 归一化到0-255之间,NORM_MINMAX:数组的数值被平移或缩放到一个指定的范围,线性归一化。
S_dB_normalized = cv2.normalize(S_dB, None, 0, 255, cv2.NORM_MINMAX)
# 将浮点数转换为无符号8位整型
S_dB_normalized = S_dB_normalized.astype(np.uint8)
# 缩放到目标大小256,256
img_resized = cv2.resize(S_dB_normalized, target_size, interpolation=cv2.INTER_LINEAR)
return img_resized
# 使用示例
video_path = '/kaggle/input/ffdv-sample-dataset/ffdv_phase1_sample/trainset/001b0680999447348bc9f89efce0f183.mp4' # 替换为您的视频文件路径
mel_spectrogram_image = generate_mel_spectrogram(video_path)
!mkdir ffdv_phase1_sample
!mkdir ffdv_phase1_sample/trainset
!mkdir ffdv_phase1_sample/valset
Die Datenmenge ist zu groß, daher werde ich hier kein Bild veröffentlichen. Stattdessen werde ich unter normalen Umständen ein Mel-Diagramm veröffentlichen:
Bildquelle:Simon Fraser Universität
Wenn Sie es einschalten und anhören, handelt es sich um ein Audiostück, dessen Lautstärke allmählich abnimmt.
# 使用glob.glob函数查找/kaggle/input/ffdv-sample-dataset/ffdv_phase1_sample/trainset/目录下前400个.mp4视频文件的路径。
for video_path in glob.glob('/kaggle/input/ffdv-sample-dataset/ffdv_phase1_sample/trainset/*.mp4')[:400]:
mel_spectrogram_image = generate_mel_spectrogram(video_path)
cv2.imwrite('./ffdv_phase1_sample/trainset/' + video_path.split('/')[-1][:-4] + '.jpg', mel_spectrogram_image)
# a. 调用generate_mel_spectrogram(video_path)函数生成梅尔频谱图,并将其存储在mel_spectrogram_image变量中。b. 使用cv2.imwrite函数将梅尔频谱图保存为JPEG图像。图像被保存在./ffdv_phase1_sample/trainset/目录下,并使用与原始视频文件相同的名称(但扩展名改为.jpg)。
for video_path in glob.glob('/kaggle/input/ffdv-sample-dataset/ffdv_phase1_sample/valset/*.mp4'):
mel_spectrogram_image = generate_mel_spectrogram(video_path)
cv2.imwrite('./ffdv_phase1_sample/valset/' + video_path.split('/')[-1][:-4] + '.jpg', mel_spectrogram_image)
Die AverageMeter-Klasse wird zum Berechnen und Speichern des Durchschnitts und des aktuellen Werts einer Variablen verwendet.
class AverageMeter(object):
"""Computes and stores the average and current value"""
def __init__(self, name, fmt=':f'):
self.name = name
self.fmt = fmt
self.reset()
def reset(self):
self.val = 0
self.avg = 0
self.sum = 0
self.count = 0
def update(self, val, n=1):
self.val = val
self.sum += val * n
self.count += n
self.avg = self.sum / self.count
def __str__(self):
fmtstr = '{name} {val' + self.fmt + '} ({avg' + self.fmt + '})'
return fmtstr.format(**self.__dict__)
Die ProgressMeter-Klasse wird verwendet, um während des Trainingsprozesses aktuelle Batch-Informationen und statistische Indikatoren auszugeben.
class ProgressMeter(object):
def __init__(self, num_batches, *meters):
self.batch_fmtstr = self._get_batch_fmtstr(num_batches)
self.meters = meters
self.prefix = ""
def pr2int(self, batch):
entries = [self.prefix + self.batch_fmtstr.format(batch)]
entries += [str(meter) for meter in self.meters]
print('t'.join(entries))
def _get_batch_fmtstr(self, num_batches):
num_digits = len(str(num_batches // 1))
fmt = '{:' + str(num_digits) + 'd}'
return '[' + fmt + '/' + fmt.format(num_batches) + ']'
Die Validierungsfunktion bewertet regelmäßig die Leistung des Modells im Validierungssatz während des Trainingsprozesses und berechnet und druckt die Top-1-Genauigkeit.
def validate(val_loader, model, criterion):
batch_time = AverageMeter('Time', ':6.3f')# 批处理时间
losses = AverageMeter('Loss', ':.4e')# 损失
top1 = AverageMeter('Acc@1', ':6.2f')# Top-1准确率
progress = ProgressMeter(len(val_loader), batch_time, losses, top1)# 输出ProgressMeter
# switch to evaluate mode,eval()为评估函数,关闭训练时使用的一些特定层(如 Dropout),并启用 Batch Normalization 层的运行统计。
model.eval()
with torch.no_grad():# 定时设置requires_grad为False,防止梯度计算并节省内存。
end = time.time()
for i, (input, target) in enumerate(val_loader):
input = input.cuda()# 将输入数据和目标数据转移到GPU计算
target = target.cuda()
# compute output
output = model(input)
loss = criterion(output, target)# 计算训练损失
# measure accuracy and record loss,acc百分比显示
acc = (output.argmax(1).view(-1) == target.float().view(-1)).float().mean() * 100
losses.update(loss.item(), input.size(0))
top1.update(acc, input.size(0))
# measure elapsed time
batch_time.update(time.time() - end)
end = time.time()
# TODO: this should also be done with the ProgressMeter
print(' * Acc@1 {top1.avg:.3f}'
.format(top1=top1))
return top1
Die Vorhersagefunktion wird verwendet, um Rückschlüsse auf den Testsatz zu ziehen, und unterstützt die Verwendung von Test Time Augmentation (TTA), um die Stabilität von Modellvorhersagen durch mehrere Vorhersagen und Mittelung zu verbessern.
def predict(test_loader, model, tta=10):
# switch to evaluate mode
model.eval()
# TTA(Test Time Augmentation)
test_pred_tta = None
for _ in range(tta):# 执行 TTA 次数的循环,每次循环会生成一个略有不同的输入数据。
test_pred = []
with torch.no_grad():
end = time.time()
for i, (input, target) in enumerate(test_loader):
input = input.cuda()
target = target.cuda()
# compute output
output = model(input)
output = F.softmax(output, dim=1)# 对模型输出进行 softmax 归一化处理,以获得类别概率。
output = output.data.cpu().numpy()
test_pred.append(output)
test_pred = np.vstack(test_pred)
if test_pred_tta is None:
test_pred_tta = test_pred
else:
test_pred_tta += test_pred
return test_pred_tta
Die Zugfunktion ist für das Training des Modells, die Aktualisierung der Modellparameter durch Berechnung der Verlustfunktion und -genauigkeit sowie für die Durchführung von Backpropagation- und Optimierungsschritten verantwortlich.
def train(train_loader, model, criterion, optimizer, epoch):
batch_time = AverageMeter('Time', ':6.3f')
losses = AverageMeter('Loss', ':.4e')
top1 = AverageMeter('Acc@1', ':6.2f')
progress = ProgressMeter(len(train_loader), batch_time, losses, top1)
# switch to train mode
model.train()
end = time.time()
for i, (input, target) in enumerate(train_loader):
input = input.cuda(non_blocking=True)
target = target.cuda(non_blocking=True)
# compute output
output = model(input)
loss = criterion(output, target)
# measure accuracy and record loss
losses.update(loss.item(), input.size(0))
acc = (output.argmax(1).view(-1) == target.float().view(-1)).float().mean() * 100
top1.update(acc, input.size(0))# 更新 top1 计量器,记录当前批次的准确率。
# compute gradient and do SGD step
optimizer.zero_grad() # 清除之前累积的梯度。
loss.backward()# 计算损失相对于模型参数的梯度
optimizer.step()# 根据 backward() 计算的梯度更新模型参数。
# measure elapsed time
batch_time.update(time.time() - end)# 更新 batch_time 计量器,记录当前批次的处理时间。
end = time.time()
if i % 100 == 0:
progress.pr2int(i)
train_label = pd.read_csv("/kaggle/input/ffdv-sample-dataset/ffdv_phase1_sample/train_label.txt")
val_label = pd.read_csv("/kaggle/input/ffdv-sample-dataset/ffdv_phase1_sample/val_label.txt")
train_label['path'] = '/kaggle/working/ffdv_phase1_sample/trainset/' + train_label['video_name'].apply(lambda x: x[:-4] + '.jpg')
val_label['path'] = '/kaggle/working/ffdv_phase1_sample/valset/' + val_label['video_name'].apply(lambda x: x[:-4] + '.jpg')
train_label = train_label[train_label['path'].apply(os.path.exists)]
val_label = val_label[val_label['path'].apply(os.path.exists)]
transform hinterlässt einen Parameter für die nachfolgende Datenverbesserung und der Standardwert ist „None“.
Das Bild wird in den RGB-Modus konvertiert.
Beschriftungen werden als Torch.Tensor zurückgegeben.
class FFDIDataset(Dataset):
def __init__(self, img_path, img_label, transform=None):
self.img_path = img_path
self.img_label = img_label
if transform is not None:
self.transform = transform
else:
self.transform = None
def __getitem__(self, index):
img = Image.open(self.img_path[index]).convert('RGB')
if self.transform is not None:
img = self.transform(img)
return img, torch.from_numpy(np.array(self.img_label[index]))
def __len__(self):
return len(self.img_path)
Verweist auf die oben festgelegte FFDID-Klasse.
train_loader = torch.utils.data.DataLoader(
FFDIDataset(train_label['path'].values, train_label['target'].values,
transforms.Compose([
transforms.Resize((256, 256)),
transforms.RandomHorizontalFlip(),
transforms.RandomVerticalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
), batch_size=40, shuffle=True, num_workers=12, pin_memory=True
)
val_loader = torch.utils.data.DataLoader(
FFDIDataset(val_label['path'].values, val_label['target'].values,
transforms.Compose([
transforms.Resize((256, 256)),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
), batch_size=40, shuffle=False, num_workers=10, pin_memory=True
)
# 重点:这里调用timm提供的resnet18模型,因为分类为0/1(真视频/假视频),可以在后续改进,比如换用更深的网络ResNet-34、ResNet-50或是其他变体
model = timm.create_model('resnet18', pretrained=True, num_classes=2)
model = model.cuda()
# 交叉熵损失,针对多类别
criterion = nn.CrossEntropyLoss().cuda()
# Adam优化器,学习率设置为0.003。
optimizer = torch.optim.Adam(model.parameters(), 0.003)
# 每4个epoch将学习率按0.85的因子进行调整。
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=4, gamma=0.85)
# 初始化最优acc
best_acc = 0.0
for epoch in range(10):
scheduler.step()
print('Epoch: ', epoch)
# 调用train函数
train(train_loader, model, criterion, optimizer, epoch)
# 调用validate函数
val_acc = validate(val_loader, model, criterion)
if val_acc.avg.item() > best_acc:
best_acc = round(val_acc.avg.item(), 2)
torch.save(model.state_dict(), f'./model_{best_acc}.pt')
Ausgabe:
Epoch: 0
[ 0/10] Time 6.482 ( 6.482) Loss 7.1626e-01 (7.1626e-01) Acc@1 35.00 ( 35.00)
* Acc@1 64.000
Epoch: 1
[ 0/10] Time 0.819 ( 0.819) Loss 4.6079e-01 (4.6079e-01) Acc@1 80.00 ( 80.00)
* Acc@1 75.500
Epoch: 2
[ 0/10] Time 0.914 ( 0.914) Loss 1.4983e-01 (1.4983e-01) Acc@1 97.50 ( 97.50)
* Acc@1 88.500
Epoch: 3
[ 0/10] Time 0.884 ( 0.884) Loss 2.4681e-01 (2.4681e-01) Acc@1 87.50 ( 87.50)
* Acc@1 84.000
Epoch: 4
[ 0/10] Time 0.854 ( 0.854) Loss 5.3736e-02 (5.3736e-02) Acc@1 100.00 (100.00)
* Acc@1 90.500
Epoch: 5
[ 0/10] Time 0.849 ( 0.849) Loss 5.9881e-02 (5.9881e-02) Acc@1 97.50 ( 97.50)
* Acc@1 89.500
Epoch: 6
[ 0/10] Time 0.715 ( 0.715) Loss 1.6215e-01 (1.6215e-01) Acc@1 92.50 ( 92.50)
* Acc@1 65.000
Epoch: 7
[ 0/10] Time 0.652 ( 0.652) Loss 5.3892e-01 (5.3892e-01) Acc@1 80.00 ( 80.00)
* Acc@1 78.500
Epoch: 8
[ 0/10] Time 0.847 ( 0.847) Loss 6.6098e-02 (6.6098e-02) Acc@1 97.50 ( 97.50)
* Acc@1 81.000
Epoch: 9
[ 0/10] Time 0.844 ( 0.844) Loss 9.4254e-02 (9.4254e-02) Acc@1 97.50 ( 97.50)
* Acc@1 81.500
Tiefere Netzwerke: Wenn Sie eine höhere Leistung und komplexere Funktionen zur Merkmalsextraktion benötigen, können Sie die Verwendung tieferer Netzwerke wie ResNet-34, ResNet-50 oder noch größerer ResNet-Varianten (wie ResNet-101 oder ResNet-152) in Betracht ziehen.
Andere vorab trainierte Modelle: Zusätzlich zur ResNet-Serie stehen viele weitere vorab trainierte Modelle zur Auswahl, wie zum Beispiel:
EfficientNet: verfügt über eine hervorragende Leistung und Parametereffizienz.
DenseNet: Eine dicht verbundene Netzwerkstruktur hilft, Funktionen besser zu nutzen.
VGG-Serie: Einfache und klassische Architektur, geeignet für den Einsatz unter Ressourcenbeschränkungen.
Benutzerdefiniertes Modell: Abhängig von den spezifischen Merkmalen des Datensatzes und den Aufgabenanforderungen können Sie auch den Entwurf und das Training einer benutzerdefinierten Modellarchitektur in Betracht ziehen, was möglicherweise mehr Debugging und Experimente erfordert.
Ensemble-Lernen: Erwägen Sie die Verwendung von Ensemble-Lernmethoden wie Bagging oder Boosting, um Vorhersagen aus mehreren Modellen zu kombinieren und so die Leistung und Stabilität weiter zu verbessern.
Hyperparameter-Tuning: Zusätzlich zur Modellauswahl kann die Modellleistung auch durch Anpassen der Lernrate, der Stapelgröße, der Optimiererauswahl und der Datenerweiterungsstrategien optimiert werden.
Erwägen Sie die Anwendung von Dice Loss, um die Verlustfunktion in Zukunft zu verbessern. Dice Loss misst die Ähnlichkeit zwischen dem Vorhersageergebnis und der Zielmaske und eignet sich besser für binäre Klassifizierungsaufgaben mit offensichtlichen Grenzen. Es handelt sich um eine Verlustfunktion, die bei der Vorhersage auf Pixelebene eine bessere Leistung erbringt.
Behalten Sie auch den Fokusverlust im Auge. Es wurde speziell zur Lösung des Klassenungleichgewichts entwickelt und kann die Leistung des Modells bei Minderheitenkategorien weiter verbessern, indem das Gewicht leicht zu klassifizierender Stichproben reduziert wird, um sich auf schwierige Stichproben zu konzentrieren.
RAdam ist eine Verbesserung gegenüber Adam, die Stabilität und Leistung durch dynamische Anpassung der Lernratenkorrektur verbessert.
AdamW ist eine Variante von Adam, die einen Gewichtsabfall einführt, um die Leistungsprobleme zu lösen, die Adam in einigen Fällen verursachen kann, insbesondere wenn die Anzahl der Modellparameter groß ist.
AdamW ist eine Variante von Adam, die einen Gewichtsabfall einführt, um die Leistungsprobleme zu lösen, die Adam in einigen Fällen verursachen kann, insbesondere wenn die Anzahl der Modellparameter groß ist.
# 用模型 (model) 对验证数据集 (val_loader) 进行预测。这部分假设 [:, 1] 给出了类别1的概率。
val_pred = predict(val_loader, model, 1)[:, 1]
# 赋值,预测的概率(或者预测值)赋给了 val_label 数据框中名为 "y_pred" 的列
val_label["y_pred"] = val_pred
submit = pd.read_csv("/kaggle/input/multi-ffdv/prediction.txt.csv")
# 使用 merge 函数将提交文件 (submit) 中的数据与验证数据集标签 (val_label) 中的 video_name 和 y_pred 列合并
merged_df = submit.merge(val_label[['video_name', 'y_pred']], on='video_name', suffixes=('', '_df2'), how='left', )
# 将合并后的数据中 y_pred_df2 列(从验证集中获取的预测结果)的值填充到 y_pred 列中
merged_df['y_pred'] = merged_df['y_pred_df2'].combine_first(merged_df['y_pred'])
merged_df[['video_name', 'y_pred']].to_csv('submit.csv', index=None)
Es dauert keine 10 Minuten, bis die Basislinie abgeschlossen ist. Normalerweise bleibt sie bei 4,7 hängen, um das Mel-Spektrogramm zu erstellen. Aber es erfordert 5 Stunden geduldiger Erkundung. Hier ist eine stille Zusammenfassung der wichtigsten Prozesse:
Die Aufgabendefinition von Deep Learning kann tatsächlich als „Backpropagation“ zusammengefasst werden, da ihr Kern darin besteht, mithilfe des Backpropagation-Algorithmus die Modellparameter anzupassen, um die definierte Verlustfunktion zu minimieren.
Es ist meiner Meinung nach sehr gut geeignet, Deep Learning für die Bewältigung solcher Audio- und Videoaufgaben zu verwenden, da es große Mengen an Audio- und Videodaten gibt und eine komplexe Klassifizierung dieser Daten erforderlich ist.Der Deep-Learning-Mechanismus bestimmt, dass eine große Datenmenge erforderlich ist, und tatsächlich ist ein sehr wichtiger Punkt, dass Deepfake selbst benötigtEinstufungDenken ist im Wesentlichen eine Klassifizierungsaufgabe, und Deep Learning bietet große Vorteile bei großen Datenmengen und einer verfeinerten Klassifizierung. Ein bekanntes Beispiel ist das kontradiktorische Generationsnetzwerk GAN.
Zweitens werden statistisch ähnliche Daten in großen Mengen erstellt und die Verteilung großer Datenmengen kann erlernt werden. Es kann auch die umgekehrte Aufgabe ausführen.
AIGC sollte Deepfake einschließen. Aus entwicklungspolitischer Sicht wird die Entwicklung und Dimensionalität der Deepfake-Technologie mit der Verarbeitungsleistung von AIGC definitiv zunehmen. Natürlich müssen wir auch sehen, was diese Videos sind Wenn es für die Entwicklung literarischer und künstlerischer Unterhaltung verwendet werden kann, wird es bald vor ethischen und moralischen Herausforderungen stehen.
Einer meiner Gedanken ist, dass Deepfake in Kombination mit der aktuellen Begeisterung für Kurzdramen der Öffentlichkeit ein äußerst kostengünstiges audiovisuelles Unterhaltungserlebnis ermöglichen kann, aber es stellt auch die traditionelle Film- und Fernsehindustrie und sogar die Art der Schauspieler vor eine Herausforderung und audiovisuelle Stimulation, die das menschliche Auge braucht. Das ist ein umstrittenes Thema.