ELECTRA training reimplementation and discussion
After months of development and debugging, I finally successfully train a model from scratch and replicate the official results.ELECTRA: Pre-training Text Encoders as Discriminators Rather Than Generatorsby Kevin Clark. Minh-Thang Luong. Quoc V. Le. Christopher D. ManningCode:electra_pytorchAFAIK, the closest reimplementation to the original one, taking care of many easily overlooked details (described below).AFAIK, the only one successfully validate itself by replicating the results in the paper.Comes with jupyter notebooks, which you can explore the code and inspect the processed data.You don’t need to download and preprocess anything by yourself, all you need is running the training script.Replicated ResultsI pretrain ELECTRA-small from scratch and have successfully replicated the paper’s results on GLUE.ModelCoLASSTMRPCSTSQQPMNLIQNLIRTEAvg. of Avg.ELECTRA-Small-OWT56.888.387.486.888.378.987.968.580.36ELECTRA-Small-OWT (my)58.7288.0386.0486.1688.6380.487.4567.4680.36Table 1:Results on GLUE dev set. The official result comes fromexpected results. Scores are the average scores finetuned from the same checkpoint. (Seethis issue) My result comes from pretraining a model from scratch and thens taking average from 10 finetuning runs for each task. Both results are trained on OpenWebText corpusModelCoLASSTMRPCSTSQQPMNLIQNLIRTEAvg.ELECTRA-Small++55.691.184.984.688.081.688.36.3679.7ELECTRA-Small++ (my)54.891.684.684.288.5828964.779.92Table 2:Results on GLUE test set. My result finetunes the pretrained checkpoint loaded from huggingface.Official training loss curveMy training loss curveTable 3:Both are small models trained on OpenWebText. The official one is fromhere. You should take the value of training loss with a grain of salt since it doesn’t reflect the performance of downstream tasks.More resultsHow stable is ELECTRA pretraining?MeanStdMaxMinModels81.380.5782.2380.4214Tabel 4:Statistics of GLUE devset results for small models. Every model is pretrained from scratch with different seeds and finetuned for 10 random runs for each GLUE task. Score of a model is the average of the best of 10 for each task. (The process is as same as the one described in the paper) As we can see, although ELECTRA is mocking adeversarial training, it has a good training stability.How stable is ELECTRA finetuing on GLUE ?ModelCoLASSTMRPCSTSQQPMNLIQNLIRTEELECTRA-Small-OWT (my)1.300.490.70.290.10.150.331.93Table 5:Standard deviation for each task. This is the same model as Table 1, which finetunes 10 runs for each task.Advanced details(Skip it if you want)elow lists the details of theoriginal implementation/paper that are easy to be overlooked and I have taken care of. I found these details are indispensable to successfully replicate the results of the paper.OptimizationUsing Adam optimizer without bias correction (bias correction is default for Adam optimizer in Pytorch and fastai)There is a bug of decaying learning rates through layers in the official implementation , so that when finetuing, lr decays more than the stated in the paper. See_get_layer_lrs. Also seethis issue.Using clip gradientusing 0 weight decay when finetuning on GLUEIt didn’t do warmup and then do linear decay but do them together, which means the learning rate warmups and decays at the same time during the warming up phase. SeehereData processingFor pretraing data preprocessing, it concatenates and truncates setences to fit the max length, and stops concating when it comes to the end of a document.For pretraing data preprocessing, it by chance splits the text into sentence A and sentence B, and also by chance changes the max lengthFor finetuning data preprocessing, it follow BERT’s way to truncate the longest one of sentence A and B to fit the max lengthTrickFor MRPC and STS tasks, it augments training data by add the same training data but with swapped sentence A and B. This is called “double_unordered” in the official implementation.It didn’t mask sentence like BERT, within the mask probability (15% or other value) of tokens,  a token has 85% chance to be replaced with [MASK] and 15% remains the same but no chance to be replaced with a random token.Tying parameterInput and output word embeddings of generator, and input word embeddings of discriminator. The three are tied together.It tie not only word/pos/token type embeddings but also layer norm in the embedding layers of both generator and discriminator.OtherThe output layer is initialized by Tensorflow v1’s default initialization (i.e. xavier uniform)Using gumbel softmax to sample generations from geneartor as input of discriminatorIt use a dropout and a linear layer in the output layer for GLUE finetuning, not whatElectraClassificationHeaduses.All public model of ELECTRA checkpoints are actually ++ model. Seethis issueIt downscales generator by hidden_size, number of attention heads, and intermediate size, but not number of layers.Need your helpPlease consider help us on the problems listed below, or tag someone else you think might help.Haven’t success to replicate results of WNLI trick for ELECTRA-Large described in the paper.When I finetune on GLUE (usingfinetune.py), GPU-util is only about 30-40%. I suspect the reason to be small batch and model size (forward pass only takes 1ms) or slow cpu speed ?About moreThe updates of this reimplementation and other tools I created will be tweeted on my TwitterRichard Wang.Also my personal research based on ELECTRA is underway, hope I can share some good results on Twitter then.
2020-09-06T10:53:03Z
This is awesome!
2020-09-09T15:23:35Z
Really great work@RichardWang!Here’s btw. the discussion about the learning rate decay through layers:https://github.com/google-research/electra/issues/51
2020-09-09T23:07:29Z
Thanks for the link !
2020-09-23T17:26:54Z
Hi! Good job!Can you please explain the use of gumbel-softmax for sampling a little bit? I want to be able to use it for sampling with other transformers(T5 for example) and I don’t know how to start.
2020-09-23T19:50:15Z
Great stuff. What an achievement. Job well done!
2020-09-25T00:06:05Z
I don’t know whether gumbel-softmax can be for text generation or not, but there is thepaper.As for implementation, create andist = torch.distributions.gumbel.Gumbel(0.,1.)and add gumbel noise to the output logitslogits = T5(...)[0]andnew_logits = logits + self.gumbel_dist.sample(logits.shape). You could also see my code.
2020-10-06T08:51:37Z
I have fixed several bugs to get closer to the official ELECTRA. And I found the content of BookCorpus hubbed on HuggingFace now is scattered, so I choose to switch to OpenWebText corpus, which the authors also train small model on.If you are using the old version of this implementation, be sure togit pullandpip install -r requirements.txt
2020-10-16T08:52:05Z
This is no easy feat, I know it first hand as I am doing something similar with BERT pre-training from scratch. Any reason why you didn’t use HF Trainer?
2020-10-18T11:08:34Z
I develop this reimplementation from a very early time before trainer get matured, so trainer was not in the consideration then.
2021-05-13T23:33:56Z
Does huggingface provide an internal way to perform this training yet?
2021-10-15T15:07:26Z
This is awesome. Thanks for sharing. I plan to warm start with google’s pre-trained models and continue pre-training on my domain-specific corpus. Can I use the same script for continual pre-training. The only changes would be to load generator and discriminator weights using ElectraForPreTraining.from_pretrained(“google/disc”) right?  Thanks in advance.
2021-10-16T01:59:17Z
That’s right
2023-09-08T04:35:16Z
Hey, I have just started studying the ELECTRA paper. And had a few doubts. I was wondering if you could help me with those?What exactly does the “Step” mean in step count? Does it mean 1 epoch or 1 minibatch?Also, in paper I saw (specifically in Table 1) ELECTRA-SMALL and BERT-SMALL borh have 14M parameters, how is that possible as ELECTRA should have more parameters because its generator and discriminator module are both BERT based?ALso, what is the architecture of both generator and discriminator?Are they both BERT to something else?Also, we have a sampling step between generator and discriminator . How are you back-propogating the gradients through this?Thanks in advance
2023-09-17T01:08:13Z
MinibatchDiscriminator of Electra small  is as the same size as BERT, generator of electra small is smaller than regular BERT. Note that we only use discriminator in finetuning.Both bert4.No backprop in sampling step, they train generator and discriminator under a multi task setting.I suggest you can read the paper thoroughly, as it have already reveal the information of your questions.