Введение
Это статья обобщение моего исследования передачи знаний от большой модели с замороженными весами в малую модель, которую мы будем обучать через расширенный механизм кросс внимания или проще говоря через LLM модули. Оригинальное исследование доступно по ссылке: arxiv.org/abs/2502.08213 . Репозиторий с кодом и весами доступен на Hugging Face: LLM модули.
Само исследование появилось из необходимости использовать знания больших обученных моделей в ограниченных рамках для четкого списка задач, при этом ни бюджета ни мощностей на файн-тюнинг моделей, даже не слишком больших, нет.
Также, недавно нашумевшая статья про то как сделать рассуждающую модель через обучение с подкреплением (DeepScaleR) подала идею, почему бы не взять модель Qwen2 1.5B (не рассуждающая модель) и попробовать её научить рассуждать хотя бы на уровне модели DeepSeek R1 Distill Qwen 1.5B (рассуждающая модель, полученная путем дистилляции).
Чтобы погрузиться глубже, начнем с существующей архитектуры больших языковых моделей, которая практически у всех одинаковая (если не брать в расчет различные оптимизации). Они состоят из:
-
Токенизатор
-
Слой эмбеддингов
-
"Тела" трансформера
-
LM head - финальный слой перед энкодингом эмбеддингов обратно в слова
В чем заключалась идея
Мы берем большую модель, замораживаем у неё веса, отрезаем LM head и вместо него ставим слой Enhanced Cross Attention который будет передавать "знания" в нашу малую модель.
Затем мы берем малую модель, в нашем случае это GPT Neo 125M. Отрезаем у неё слой эмбеддингов и подключаем наш Enhanced Cross Attention слой из большой модели. А для того чтобы избежать проблем с несовместимостью токенизаторов мы заменяем родной LM head малой модели на кастомный, который сможет работать с тем же токенизатором, что и большая модель.
Ну и затем запускаем обучение. В моем случае мне помог датасет bespokelabs/Bespoke-Stratos-17k в котором есть цепочки рассуждений, которым хочу научить свою модель.
В идеале Я хотел получить связку из 2 моделей в которой большая модель выступает в качестве "источника знаний", а малая модель выступает в качестве "мыслителя".
Сопутствующим плюсом стало то, что такая связка способна потреблять такое же количество контекста, что и большая модель (в моем случае это 125к), в то время как малая модель может работать только с окном контекста в 2048 токенов.
Процесс
Нюансом в обучении было то что хоть большая модель и может потреблять большой контекст, полноценно прогнать его по слабой машине не представляется возможным, поэтому Я пошёл на ухищрение и при формировании датасета добавил фильтрацию по общей длине данных (запрос + ответ) в 4096 токенов.
Обучение производилось на одной машине с 4 vCPUs, 32 GB Memory и GPU 1 x NVIDIA L4, которую Я арендовал в Google Cloude.
Набор софта для исследования также довольно тривиальный - это python 3.11, PyTorch, Transformers, Datasets и tqdm для прогрессбара. Весь исходный код состоящий из 1 .py файла доступен на Hugging Face так что Я не буду углубляться в программистскую составляющую.
Обучение проводилось в течение 15 эпох, при этом датасет перемешивался каждый раз, если значение validation loss опускалось ниже 1.8.
В первую эпоху training loss снижался с 13.8 до 2.3, затем в последующие эпохи training loss снижался примерно от 5 сотых до 2 десятых за каждую эпоху. Validation loss также стабильно снижался, что дало понимание что не идёт переобучения, даже учитывая малый датасет.
В общем обучение заняло около 5 часов и финальный validation loss был примерно 1.1.
Всего за время обучения Я потратил менее $10 за аренду инстанса.
После обучения пришло время тестов, которые должны были подтвердить или опровергнуть, что действительно есть передача знаний от большой модели в меньшую. А для этого мне нужно было отдельно дообучить меньшую модель, чтобы понять, что это не она своими силами отдает ответы. Так что Я отдельно обучил GPT Neo 125M в двух экземплярах - с предобученными весами и с нуля.
Т.к. датасет в основном состоит из математических задач, модели Я решил проверять на простых вопросах и посмотреть как они рассуждают или не рассуждают и как эти рассуждения влияют на дальнейшие ответы.
Результаты
Дисклеймер:
Отмечу отдельно, что у меня не было иллюзий, что Я получу полноценную рассуждающую модель, которая переняла все знания и не уступает оригинальной большой модели. Напомню, что задача стоит конкретная - научить модель определенным вещам, не тратя на это огромные суммы и вычислительные мощности. Здесь случай похож на то что у нас есть большая "БД", с кучей "таблиц" и данных (это большая модель), а мы с помощью обучения даем схемы только к некоторым "таблицам" и учим модель работать с ними. Такое ограничение в знаниях также считаю плюсом, т.к. в реальном бизнесе модели не нужно знать историю и бабушкины рецепты, ей всего лишь нужно уметь решать поставленные задачи, а за AGI можно идти к OpenAI.
Дополнительно:
В обучении и в запросах к моделям Я добавлял системный промпт, который должен был заставить модель некоторым правилам:
System:
**Your role as an assistant involves thoroughly exploring questions through a systematic long thinking process before providing the final precise and accurate solutions. This requires engaging in a comprehensive cycle of analysis, summarizing, exploration, reassessment, reflection, backtracing, and iteration to develop well-considered thinking process. Please structure your response into two main sections: Thought and Solution. In the Thought section, detail your reasoning process using the specified format: <|begin_of_thought|> {thought with steps separated with 'nn'} <|end_of_thought|> Each step should include detailed considerations such as analisying questions, summarizing relevant findings, brainstorming new ideas, verifying the accuracy of the current steps, refining any errors, and revisiting previous steps. In the Solution section, based on various attempts, explorations, and reflections from the Thought section, systematically present the final solution that you deem correct. The solution should remain a logical, accurate, concise expression style and detail necessary step needed to reach the conclusion, formatted as follows: <|begin_of_solution|> {final formatted, precise, and clear solution} <|end_of_solution|> Now, try to solve the following question through the above guidelines:**
Итак, перейдем к конкретным ответам, полученным от разных моделей (полные ответы вы можете найти в том же репозитории на Hugging Face: ссылка):
DeepSeek R1 671B
User:
sum of 5 and 5
Assistan
<|begin_of_thought|>
Okay, so I need to find the sum of 5 and 5. Let me think about how to approach this. Sum means adding two numbers together, right? So when they say "sum of 5 and 5," that should just be 5 plus 5. But let me make sure I'm not overcomplicating it.
[ богатая цепочка рассуждений ]
<|end_of_thought|
<|begin_of_solution|>
The sum of 5 and 5 is calculated by adding the two numbers together:
5+5=10
Answer: 10
<|end_of_solution|>
DeepSeek-R1-Distill-Qwen-1.5B-GGUF 32FP
[ системный промпт ]
User:
sum of 5 and 5
Assistant:
<|begin_of_thought|>
Okay, so I need to figure out the sum of 5 and 5. Hmm, let's see. Sum usually means adding two numbers together, right? So if I have 5 apples and someone gives me another 5 apples, how many apples do I have in total?
[ богатая цепочка рассуждений ]
<|end_of_thought|>
<|begin_of_solution|>
Thought:
To find the sum of 5 and 5, we can approach it in multiple ways:
1. Counting Objects: If you have five items and add another five, counting them gives a total of ten.
2. Number Line Addition: Starting at 5 and moving 5 units to the right on a number line lands you at 10.
3. Modular Arithmetic (if applicable): The sum is straightforward unless specified otherwise.
4. Real-life Applications: In contexts like money or time, adding 5and5and5 results in $10.
Solution:
After considering various methods, we can conclude that the sum of 5 and 5 is:
5+5=10
<|end_of_solution|>
Qwen2-1.5B-Instruct-GGUF FP16
[ системный промпт ]
User:
sum of 5 and 5
Assistant:
Thought: Firstly, we need to determine what operation we're asked to perform. In this case, it's addition.
Next, we must consider the numbers involved - 5 + 5.
Solution: To find the sum of these two numbers:
1. Add 5 and 5 together: 5+5=105+5=10.
Therefore, the sum of 5 and 5 is 10.
Thought: After performing the addition, we have reached our final answer correctly. No further steps are necessa
Solution: The sum of 5 and 5 is 10.
GPT-Neo-125M
[ системный промпт ]
User:
sum of 5 and 5
Assistant:
=**A**
The answer you specified after thoughtfully defining the question/solution/problems could be achieved, by putting together your answers.
The answers should be carefully organized into a brief summary, followed by a summary of the discussion. If you have any questions, you may provide the answer immediately. See the Discussion section for an informal discussion of the specific answers.
[ бессмысленный набор текста ]
GPT-Neo-125M-fine-tuned
[ системный промпт ]
User:
sum of 5 and 5
Assistant:
"How can the use of photochemistry for the treatment of cancer cells be optimized to effectively treat such cells?"
Assistant:
<|begin_of_thought|>
Okay, so I have this question about photochemistry for cancer treatment. It asks how the use of photochemistry helps to effectively treat cancer cells with specific photoplastines and what that means for having a reaction in mind. Let me think about it step by step.
[ бессмысленный набор текста ]
GPT-Neo-125M-clean (обученная с нуля на датасете)
[ системный промпт ]
User:
sum of 5 and 5
Assistant:
Okay, so I need to solve the question about how that the result in bioremediation of a day at those strong field of all under two different types of the way to understand what that during a one amount of a efficiency of the entire s, and constant gamma, and two T has to create them in binding equation of these two equal to form. It's also look at-5-4.
First, I remember that the left and another, right? The fifth is the same relationship. The common ratio of the reaction with two lines from the question is the constant.
[ бессмысленный набор текста ]
CombinedModel (моя парная модель из не рассуждающей Qwen2-1.5B и GPT Neo 125M) *оставил ответы целиком, для оценки
Запрос 1
[ системный промпт ]
User:
sum of 5 and 5
Assistant:
<|begin_of_thought|>
Okay, let's see. I need to compute the sum of 5 and 5. Hmm, first, I remember that 5 plus 5 is 10. That seems right. Let me verify that step by step to make sure I'm not missing anything.
Alright, 5 plus 5. First, I remember that 5 times 1 is 5, so 5 + 5 is 10. Yeah, that seems right. Both methods give the same result.
First, I have to make sure I didn't skip any steps or make a mistake in the approach.
The key here is that for any two numbers, the sum is the same for you and if I do the the same the same. So maybe I missed something. Alternatively, maybe I could think about the negative sign. Let me think step by step.
First, the two numbers are 5 and 5. So, 5 + 5. Hmm, "5 + 5" plus the negative sign. Alternatively, maybe I should write down the formula for the arithmetic starting with the first number.
Let me think step by step.
For the sum of two numbers, the formula is:
x + y
So, 5 + 5.
Let me check if I did it right. Let's confirm with another method.
For the sum of two numbers, the formula is:
x + y
So, 5 + 5.
Alright, that's correct.
Another way to think about it: if the first number is 5 and the second is 5. Then, the sum is 5 + 5 = 10.
So, the sum of 5 and 5 is indeed 10. I think that's solid. I don't see any mistakes here. I don't see any errors in the reasoning. The key was that for any two numbers, the sum is the same. If I compute it step by step, I check with another method, and see if I did it right, I don't see any errors.
Let me double-check with another method to make sure I didn't skip any steps.
For example, if I think of the variables in the sum, x + y. The first number is 5, and the second is 5. So, y is 5. Then, substituting the two numbers:
x + 5. Which is exactly 10.
Similarly, I can think of the general formula x + y. The first number is 5, and the second is 5. So, y is 5. So, 5 + 5 = 10.
Alternatively, if I consider that x and y are numbers. Since they are numbers, they are integer, so perhaps I can use integer possible values. But x + y, which is the sum, must be an integer. So, no, in the standard the first number is 5, and the second is 5. So, 5 + 5 = 10.
Alternatively, if I consider that x and y are two elements in a list. But since both x and y are positive, the sum is always positive. So, 5 + 5 is positive.
Alternatively, if I think of the values of x and y. But since x and y are positive, the sum is positive. So, yes, 5 + 5 equals 10.
Another way: 5 + 5 equals 10. Using the formula: x + y, which is 5 + 5. Yep, that's correct.
<|end_of_thought|>
<|begin_of_solution|>
To determine the sum of 5 and 5. I need to calculate the sum of two positive integers. The sum is calculated by adding the two numbers together.
Let's calculate the sum step by step:
1. From the problem statement:
- The sum of 5 and 5.
2. Calculate the sum:
- Add the two numbers together:
- (5 + 5 = 10).
Thus, the sum of 5 and 5 is (boxed{10}).
<|end_of_solution|>
Запрос 2
[ системный промпт ]
User:
find the remainder by dividing 7 by 4
Assistant:
<|begin_of_thought|>
Okay, so I need to find the remainder when 7 is divided by 4. Hmm, let's break this down step by step.
First, I remember that when you divide a number by another number, the remainder is the remaining number in the division. So, if I divide 7 by 4, the remainder would be the remaining number after the division.
Let me see. 7 divided by 4. Hmm, 7 divided by 4 is 1 with a remainder of 3.
Wait a second, let me make sure. 7 divided by 4 is 1 with a remainder of 3. That's correct.
Is there another way to verify this? Maybe by dividing 7 by some numbers. Alternatively, maybe dividing 4 by 7 and then 7 by 4. Let's do that to verify.
Dividing 4 by 7. 4 divided by 7 is 0 with a remainder of 4. Then adding that with the remainder from the division before.
Adding 0 and 3. So, the remainder when 7 is divided by 4 is 3.
Wait a second, does that mean 13 divided by 4: 3 with a remainder of 1? Wait, that can't be right. Let me check again.
Original remainder: 3. Subtract 3 from 7: 7 -3 is 4, divided by 4 gives 1. So, 7 divided by 4 is 1 with remainder 3. That seems right.
Alternatively, can this formula be used?
For x divided by y: the remainder is equal to x - y (d: 1). So, 7 -41 is 3, which matches the previous result.
Alternatively, maybe we can express this in terms of congruence. Let a = x, b = y. Then, a + b �� 1 mod |y|, which is x + a �� a + b �� 1 �� 3 mod 4. Since 3 �� 3 mod 4, that's consistent.
So, regardless of the method, I do think it's correct. The remainder is 3 when 7 is divided by 4.
<|end_of_thought|>
<|begin_of_solution|>
The remainder when 7 is divided by 4 is 3.
The formula that is used for it is: (a - b * d) = -n, where a is the number divide, b is the divisor, d is the number the remainder is, and n is the remainder.
First, a - b d = 7 - 43 = 7 -12 = -5, but since the remainder has to be positive, it's 3.
For example, if we take n=1: (7 - 4*1) = 7 -4 =3, which is the same as before.
Another example: if we take n=3: (7 -4*3) =7 -12 = -5. Since the remainder can't be negative, that's not correct.
So, if we take n=1: 7 -4*1 =7 -4=3, which matches the previous result.
Another method: using congruence. Let a = x, b = y. Then, a + b �� 1 mod |y|, which is x + a �� a + b ��1 ��3 mod4. Since 3≡3 mod4, that's definitely correct.
Another way: the formula is a + b ��1 mod |y|, where a is the number not divisible by y, b is the number divisible by y, and n=1 is the remainder. Since 7 divided by 4, n=3.
So, I think that's correct.
<|end_of_solution|>
Заключение
В заключении Я считаю эксперимент прошёл удачно, малая модель смогла подчерпнуть знания у большей модели и даже смогла делать внятные рассуждения, схожие с рассуждениями модели DeepSeek R1.
Из плюсов данной архитектуры Я могу выделить следующие пункты:
-
Малые затраты на обучение, как по мощностям, так и по деньгам.
-
Возможность работать с большим контекстом, нежели малая модель сама по себе.
-
Высокая скорость обучения.
-
Даже ограниченный датасет позволяет получить приемлемые результаты.
-
Неограниченные возможности в комбинации разных моделей.
Дальнейшее развитие.
Мне кажется, что такая архитектура "источник знаний" + "мыслитель" позволит более направленно тренировать модели и обучать их определенным навыкам, ведь вместо "мыслителя" может быть "поэт", "программист", "ученный" или ещё что-нибудь. Ведь, по факту, набор знаний у людей примерно одинаковый и решают именно навыки/опыт, приобретенные в течение жизни и мы можем взять умный бекграунд и обучить узкоспециализированным навыкам получив некоего "эксперта". Возможно даже что такой подход позволит экспоненциально увеличивать разумность моделей, в зависимости от числа параметров, а не линейно как это происходит сейчас.
Также возможность передачи знаний на уровне логитов позволяет предположить что можно комбинировать не только LLM, но и например CNN + LLM для "понимания" изображений и возможного развития мультимодальных моделей.
На этом всё, спасибо за внимание.
Автор: kolkoni