File size: 9,749 Bytes
91feea3
4e0a704
91feea3
d5b15a3
60d30cc
91feea3
 
 
 
 
72b1673
ae63b0f
 
03f2529
 
 
 
3a0bedd
91feea3
50b8512
ada63db
50b8512
 
 
21357fc
50b8512
ada63db
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50b8512
a748911
d38b680
a748911
 
 
 
50b8512
3cf5a13
 
 
 
 
 
 
0e34887
378e7cb
 
 
 
 
 
 
 
 
 
 
 
 
181494a
0e34887
cc3b6f3
 
37c4d2f
115c7e5
03d727b
f3a3745
91feea3
cc37d8c
91feea3
50daa38
91feea3
50daa38
91feea3
4128faf
 
013cf76
9f3da8d
c50213d
4128faf
60d9a0b
 
181494a
72b1673
 
 
181494a
 
4b87cce
181494a
ae63b0f
 
 
 
9acbf52
b596828
ae63b0f
181494a
 
 
 
 
 
 
72b1673
 
 
 
 
 
 
 
1a07f51
72b1673
 
 
3cf5a13
 
 
 
 
 
72b1673
 
 
 
 
ba2d3ab
 
72b1673
618fdbd
7ddeab6
252f8d4
 
378e7cb
 
 
72b1673
 
d500f0f
77ee5c9
252f8d4
 
 
 
 
 
 
 
91fda76
1b85a4d
91fda76
a6ca5ee
72b1673
1a07f51
72b1673
95d0743
 
 
72b1673
 
 
7ddeab6
9f3da8d
3cf5a13
95d0743
1a07f51
95d0743
a748911
252f8d4
dde4e83
cbcdf0d
d8a47fd
deb4c1f
b6fc2f9
deb4c1f
8f623a8
deb4c1f
dde4e83
d38b680
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b6fc2f9
 
 
378e7cb
b6fc2f9
 
 
 
 
 
 
d38b680
 
f3a3745
d38b680
f3a3745
 
 
 
a748911
 
 
d38b680
a748911
 
 
 
 
b41357d
 
 
 
 
7416abf
f3a3745
b41357d
3e7d36b
 
7416abf
a748911
b41357d
f3a3745
0e34887
 
 
 
c7110f3
0e34887
b41357d
21a4e7c
80b50b6
b41357d
 
3e7d36b
 
 
8bad0a0
3447965
c7110f3
91feea3
 
0e34887
72b1673
a4f2192
72b1673
 
831f0b2
72b1673
91feea3
ecd5b13
1d2196a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
#!/usr/bin/env python
# -*- coding: utf-8 -*- 

import os 
from huggingface_hub import login
import gradio as gr
#from transformers import pipeline 
import torch
from utils import *
from presets import *
from transformers import Trainer, TrainingArguments
import numpy as np
import evaluate
import pandas as pd
import sklearn
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, recall_score, precision_score, f1_score


#####################################################
#Hilfsfunktionen für das Training
#####################################################
#Datensets in den Tokenizer schieben...
def tokenize_function(examples):
    return tokenizer(examples["text"])

#Funktion, die den gegebenen Text aus dem Datenset gruppiert
def group_texts(examples):
    # Concatenate all texts.
    concatenated_examples = {k: sum(examples[k], []) for k in examples.keys()}
    total_length = len(concatenated_examples[list(examples.keys())[0]])
    # We drop the small remainder, we could add padding if the model supported it instead of this drop, you can
    # customize this part to your needs.
    total_length = (total_length // block_size) * block_size
    # Split by chunks of max_len.
    result = {
        k: [t[i : i + block_size] for i in range(0, total_length, block_size)]
        for k, t in concatenated_examples.items()
    }
    result["labels"] = result["input_ids"].copy()
    return result    

#Generate Response - nach dem training testen, wie es funktioniert
def generate_response(prompt, model, tokenizer):
    input_ids = tokenizer.encode(prompt, return_tensors="pt")
    output = model.generate(input_ids, max_length=100)
    response = tokenizer.decode(output[:, input_ids.shape[-1]:][0], skip_special_tokens=True)
    return response

#Funktion, die der trainer braucht, um das Training zu evaluieren - mit einer Metrik
def compute_metrics(eval_pred):
    logits, labels = eval_pred
    predictions = np.argmax(logits, axis=-1)
    #Call compute on metric to calculate the accuracy of your predictions.
    #Before passing your predictions to compute, you need to convert the predictions to logits (remember all Transformers models return logits):
    return metric.compute(predictions=predictions, references=labels)

#oder mit allen Metriken
def compute_metrics_alle(eval_pred):
    metrics = ["accuracy", "recall", "precision", "f1"] #List of metrics to return
    metric={}
    for met in metrics:
       metric[met] = load_metric(met)
    logits, labels = eval_pred
    predictions = np.argmax(logits, axis=-1)
    metric_res={}
    for met in metrics:
       metric_res[met]=metric[met].compute(predictions=predictions, references=labels)[met]
    return metric_res


###################################################################################
###################################################################################
#Access-Token (in Secrets)

#aus den Secrets importieren (siehe Setting zu diesem Space)
login(token=os.environ["HF_ACCESS_TOKEN"])   #for read access!!!!
     
#Modelle und Tokenizer

#Alternativ mit beliebigen Modellen:
#base_model = "project-baize/baize-v2-7b"  #load_8bit = False (in load_tokenizer_and_model)
#base_model = "TheBloke/airoboros-13B-HF"  #load_8bit = False (in load_tokenizer_and_model)
base_model = "EleutherAI/gpt-neo-1.3B"    #load_8bit = False (in load_tokenizer_and_model)
#base_model = "TheBloke/airoboros-13B-HF"   #load_8bit = True

#Tokenizer und Model laden
tokenizer,model,device = load_tokenizer_and_model(base_model,  False)
#tokenizer.add_special_tokens({'pad_token': '[PAD]'}) #not necessary with fast Toekenizers like GPT2

#Datensets für Finetuning laden
dataset_neu = daten_laden("alexkueck/tis") 
#dataset_neu = daten_laden("EleutherAI/pile")

#############################################
#Vorbereiten für das Training der neuen Daten
#############################################

#alles zusammen auf das neue datenset anwenden - batched = True und 4 Prozesse, um die Berechnung zu beschleunigen. Die "text" - Spalte braucht man anschließend nicht mehr, daher weglassen.
tokenized_datasets = dataset_neu.map(tokenize_function, batched=True, num_proc=4, remove_columns=["id","text"])

#wenn man zum Trainieren erstmal nur einen kleinen Datensatz nehem möchte:
#small_train_dataset = tokenized_datasets["train"].shuffle(seed=42).select(range(1000))
#small_eval_dataset = tokenized_datasets["test"].shuffle(seed=42).select(range(1000))

print (tokenized_datasets["train"][4])


#den Text nun zusammenführen (concatenieren) und anschließend in kleine Häppchen aufteilen (block_size=128), die verarbeitet werden können
#das macht die map-Funktion und das Attribut batched = True
#man könnte das weglassen, wenn jeder Satz einzeln gegeben wurde in den Texten...
#eigentlich nimmt man als block_size die max. Länge in der das Model trainiert wurde -> könnte aber zu groß sein für den RAm der GPU , daher hier 128 gewählt
# block_size = tokenizer.model_max_length
block_size = 128

#nochmal die map-Funktion auf das bereits tokenisierte Datenset anwenden
#die bereits tokenisierten Datensatze ändern sich dadurch: die samples enthalten nun Mengen aus block_size Tokens
lm_datasets = tokenized_datasets.map(
    group_texts,
    batched=True,
    batch_size=1000,
    num_proc=4,
)
print ("lm datasets")
#die Daten wurden nun "gereinigt" und für das Model vorbereitet.
#z.B. anschauen mit: tokenizer.decode(lm_datasets["train"][1]["input_ids"])

###################################################
#Metrik
#Metrik berechnen, um das training messen zu können - wird es besser???
metric = evaluate.load("accuracy")   # 3 Arten von gegebener Metrik: f1  oder roc_auc  oder accuracy


####################################################
#Training
####################################################

#Training Args
batch_size = 2

training_args = TrainingArguments(
    output_dir="alexkueck/test-tis-1",
    overwrite_output_dir = 'True',
    per_device_train_batch_size=batch_size,  #batch_size = 2 for full training
    per_device_eval_batch_size=batch_size,
    evaluation_strategy = "steps",  #oder  
    logging_strategy="steps",   #oder epoch
    logging_steps=10,
    learning_rate=2e-5,
    weight_decay=0.01,
    save_total_limit = 2,
    #predict_with_generate=True,
    #logging_steps=2,  # set to 1000 for full training
    #save_steps=16,    # set to 500 for full training
    #eval_steps=4,     # set to 8000 for full training
    #warmup_steps=1,   # set to 2000 for full training
    #max_steps=16,     # delete for full training
    # overwrite_output_dir=True,
    #save_total_limit=1,
    #fp16=True,
    save_strategy = "no",
    optim="adamw_torch",
    load_best_model_at_end=False,
    #push_to_hub=True,
)
print ("training args")
############################################
#def trainieren_neu(name):
#Trainer zusammenstellen
trainer = Trainer(
        model=model,
        args=training_args,
        train_dataset=lm_datasets["train"],
        eval_dataset=lm_datasets["test"],
        #tokenizer=tokenizer,
        compute_metrics=compute_metrics,
)
print ("trainer")
#trainer ausführen
trainer.train()
#Wenn man vom letzten checkpoint aus weiter trainieren möchte: trainer.train(resume_from_checkpoint=True)
print("trained!!!!!")


##################
#Evaluate the new Model auf evual dataset
print("Evaluate:")
trainer.evaluate(eval_dataset=lm_datasets["test"])
print("Done Eval")

###################################################
#Save to a place -????? Where????
print("Save to ???")
login(token=os.environ["HF_WRITE_TOKEN"]) 
trainer.save_model("test-tis-1")
print("done")

#####################################
#Push to Hub
#print("push to hub")
#login(token=os.environ["HF_WRITE_TOKEN"]) 
#trainer.push_to_hub("test-tis-1")
#tokenizer.push_to_hub("test-tis-1")????
#print("done")

#######################################
# Load model
print("load model_neu")
login(token=os.environ["HF_ACCESS_TOKEN"]) 
model_name_neu = "alexkueck/test-tis-1"
#model_neu = trainer.load("test-tis-1")

#oder ...
model_neu, device_neu = load_tokenizer_and_model(model_name_neu, False)
print("done load")



############################
#Test des Modells
############################
print("Test")
text = "Was ist Tis?"

# Example usage
prompt = "Was ist TIS?"

response = generate_response(prompt, model_neu, tokenizer)
print(response)
print("response done")


'''
#encoding = tokenizer(text, return_tensors="pt")
#encoding = {k: v.to(trainer.model.device) for k,v in encoding.items()}

#outputs = trainer.model(**encoding)
#logits = outputs.logits
#print(logits.shape)

#greedy_output = model.generate(input_ids, max_length=50)

print("Output:\n" )
#print(tokenizer.decode(outputs[0], skip_special_tokens=True))
'''




##############################################
#Testen des fine-tuned Modells
'''
print("Predict")
login(token=os.environ["HF_ACCESS_TOKEN"]) #read access token!!!!!!!!!!
model_name = "alexkueck/test-tis-1"
tokenizer_neu = load_tokenizer(base_model)
model_neu, device_neu = load_model(model_name, False)
antwort = predict(model_neu, tokenizer_neu, device_neu, "Was ist Tis?", [["Tis", ""]], top_p=5,
            temperature=0.8,
            max_length_tokens=1024,
            max_context_length_tokens=2048,)
print(antwort)
print("done Predict")
'''
#######################################################################
#Darstellung mit Gradio
'''
with gr.Blocks() as demo:
    name = gr.Textbox(label="Model")
    output = gr.Textbox(label="Output Box")
    start_btn = gr.Button("Start")
    start_btn.click(fn=trainieren_neu, inputs=name, outputs=output, api_name="trainieren_neu")


demo.queue(default_enabled=True).launch(debug=True) 
'''