Ela.kpi.ua



НАЦ?ОНАЛЬНИЙ ТЕХН?ЧНИЙ УН?ВЕРСИТЕТ УКРА?НИ?КИ?ВСЬКИЙ ПОЛ?ТЕХН?ЧНИЙ ?НСТИТУТ ?МЕН? ?ГОРЯ С?КОРСЬКОГО??НСТИТУТ ПРИКЛАДНОГО СИСТЕМНОГО АНАЛ?ЗУКАФЕДРА МАТЕМАТИЧНИХ МЕТОД?В СИСТЕМНОГО АНАЛ?ЗУНа правах рукопису До захисту допущеноУДК 004.421.2 В. о. зав?дувача кафедри ММСА О.Л.Тимощук?___? ____________ 2019 р.Маг?стерська дисертац?яна здобуття ступеня маг?стра за спец?альн?стю 122 Комп’ютерн? наукина тему: ?Система створення балансу в асиметричних ?грах?Виконала: студентка ?? курсу, групи зКА-82мпМороз Влада В?ктор?вна ____________Кер?вник: доцент кафедри ММСА, к.т.н, доц. Дiдковська М.В ____________Рецензент: доцент кафедри ПЗКС ФПМ,к.т.н, доц. Заболотня Т.М. ____________Засв?дчую, що у ц?й маг?стерськ?й дисертац?? нема? запозичень з праць ?нших автор?в без в?дпов?дних посиланьСтудент ____________Ки?в2019НАЦ?ОНАЛЬНИЙ ТЕХН?ЧНИЙ УН?ВЕРСИТЕТ УКРА?НИ?КИ?ВСЬКИЙ ПОЛ?ТЕХН?ЧНИЙ ?НСТИТУТ ?МЕН? ?ГОРЯ С?КОРСЬКОГО??НСТИТУТ ПРИКЛАДНОГО СИСТЕМНОГО АНАЛ?ЗУКАФЕДРА МАТЕМАТИЧНИХ МЕТОД?В СИСТЕМНОГО АНАЛ?ЗУР?вень вищо? осв?ти – другий (маг?стерський) Спец?альн?сть (спец?ал?зац?я) – 122 ?Комп’ютерн? науки? (??нтелектуальний анал?з даних в управл?нн? проектами?)ЗАТВЕРДЖУЮВ. о. зав?дувача кафедри ММСАО. Л. Тимощук?___? ____________ 2019 р.ЗАВДАННЯна маг?стерську дисертац?ю студенту Мороз Влад? В?ктор?вн?1. Тема дисертац??: ?Система створення балансу в асиметричних ?грах?, науковий кер?вник дисертац?? Д?дковська Марина В?тал??вна, доктор техн?чних наук, професор кафедри ММСА, затверджен? наказом по ун?верситету в?д ?05? листопада 2019 р. № 3825-с2.Терм?н подання студентом дисертац??: __________________________3. Об’?кт досл?дження: системи балансування асиметричних ?гор4. Предмет досл?дження: системи балансування асиметричних ?гор5. Перел?к завдань, як? потр?бно розробити:1) провести анал?з метод?в штучного ?нтелекту для вир?шення прикладних задач;2) вибрати навчальний наб?р даних;3) синтезувати арх?тектуру системи;4) провести тестування cистеми;5) розробити ?нтерфейс для введення даних по гр?;6) виконати тестування програмно? частини системи6. Дата видач? завдання: ________________________________________Календарний план№ з/пНазва етап?в виконання маг?стерсько? дисертац??Терм?н виконання етап?в маг?стерсько? дисертац??Прим?тка1.Написання вступу маг?стерсько? дисертац??02.09.2019–08.09.20192.Пор?вняльний анал?з п?дход?в по вир?шенню поставлено? задач?, виб?р арх?тектур моделей для пор?вняння09.09.2019–15.09.20193.П?дготовка навчально? виб?рки, навчання моделей16.09.2019–22.09.20194.П?дготовка матер?ал?в першого розд?лу маг?стерсько? дисертац??23.09.2019–29.09.20195.Проведення пор?вняльного анал?зу побудованих моделей30.09.2019–06.10.20196.П?дготовка матер?ал?в другого розд?лу маг?стерсько? дисертац??07.10.2019–13.10.20197.П?дготовка граф?чно? частини маг?стерсько? дисертац??14.10.2019–27.10.20198.П?дготовка матер?ал?в третього розд?лу маг?стерсько? дисертац??28.10.2019–10.11.20199.П?дготовка матер?ал?в розд?лу стартап-проекту маг?стерсько? дисертац??11.11.2019–17.11.201910.Написання висновку маг?стерсько? дисертац??18.11.2019–25.11.2019Студент В.В. МорозНауковий кер?вник дисертац??М.В. Д?дковськаРЕФЕРАТМаг?стерська дисертац?я: 107 с., 2 Рисунока, 18 табл., 20 джерел л?тератури, 1 додаток.Об’?кт досл?дження: системи балансування асиметричних ?гор.Предмет досл?дження: побудова балансу гри.Ц?л? досл?дження: створення системи балансування ?гор, як ?нструменту для ?нд?-розробник?в, або для пол?пшення балансу в уже ?снуючих ?грах.Задач? роботи: розробити алгоритм балансування гри при автоматичному заданн? складност? гри, тобто розробити систему з ?нтерфейсом, що могла б ?з введених даних користувачем провести автоматичне балансування, а також надавати рекомендац?? щодо пол?пшення при ускладнен? чи полегшен? р?вня складност? гри.П?д час виконання роботи було проведено анал?з сучасних метод?в з балансування ?гор, а особливо асиметричних ?гор, серед метод?в був обраний метод Монте-Карло як найб?льш популярний, ?нтерфейс системи буде розм?щен?й в табличному файл? з використанням мови Python.Була розроблена арх?тектура мереж? для середньо? складност? балансу асиметрично? гри, на основ? якого розроблена система, що викону? поставлену задачу. Актуальн?сть проекту мотиву?ться в?дсутн?стю аналог?чних р?шень ? потенц?йною зац?кавлен?стю з боку б?знесу.Результати роботи можуть бути використан? як комерц?йними орган?зац?ями для балансування вже ?снуючих р?шень, так ? ентуз?астами та ?нд?-початк?вцями, що прагнуть розробити нову гру. БАЛАНС АСИМЕТРИЧНО? ГРИ, АВТОМАТИЧНЕ РОЗП?ЗНАВАННЯ СКЛАДНОСТ? ГРИ, PYTHON, TENSORFLOW, NUMPY, МЕТОД МОНТЕ-КАРЛО, TABLEAU, INDI BALANCE.ABSTRACTMaster's Thesis: 107 p., 2 fig., 18 tabl., 20 ref., 1 appendixes.Research Object: Asymmetric Balancing Systems.Subject of study: balance of the game.Aims of the research: creation of a system for keeping text of meetings.Tasks of work: to develop an algorithm for balancing the game when automatically setting the complexity of the game, that is, to develop a system with an interface that could perform automatic balancing from the entered data, as well as provide recommendations for improvement in case of complicated or facilitated levels of difficulty of the game.During the work, the analysis of modern methods for balancing games, and especially asymmetric games, was carried out, among the methods was chosen Monte Carlo method as the most popular, the system interface will be placed in a spreadsheet using Python.The network architecture was developed for the average complexity of the balance of the asymmetric game, on the basis of which the system fulfilling the task was developed.The urgency of the project is motivated by the absence of similar solutions and potential interest from the business.The results of the work can be used by business organizations to balance existing solutions, as well as enthusiasts and indie starters seeking to develop a new game.ASYMMETRIC GAME BALANCE, AUTOMATIC DIFFICULTY GAME RECOGNITION, PYTHON, TENSORFLOW, NUMPY, MONTE-CARLO, TABLEAU, INDI BALANCE.ЗМ?СТ TOC \o "1-3" \h \z \u ВСТУП PAGEREF _Toc26294721 \h 8РОЗД?Л 1 ОГЛЯД ПРОБЛЕМАТИКИ ПОБУДОВИ БАЛАНСУ PAGEREF _Toc26294722 \h 101.1.Основи ?грового балансу: Детерм?нован?, недетерм?нован? ? розв'язн? гри PAGEREF _Toc26294723 \h 111.2.Парадигма балансу PAGEREF _Toc26294724 \h 161.3.Види балансу PAGEREF _Toc26294725 \h 17Висновки до розд?лу PAGEREF _Toc26294726 \h 26РОЗД?Л 2 МЕТОД МОНТЕ-КАРЛО. КОНСТАНТИ ТА ПРОГРЕС?Я. PAGEREF _Toc26294727 \h 272.1 Метод Монте-Карло PAGEREF _Toc26294728 \h 27Висновки до розд?лу PAGEREF _Toc26294729 \h 44РОЗДIЛ 3 ОПИС АРХIТЕКТУРИ БАЛАНСЕРУ ГРИ PAGEREF _Toc26294730 \h 453.1 (Не) очевидн? параметри PAGEREF _Toc26294731 \h 533.2 Ефективн?сть групи PAGEREF _Toc26294732 \h 553.3 Синерг?я PAGEREF _Toc26294733 \h 56Висновки до розд?лу PAGEREF _Toc26294734 \h 59РОЗД?Л 4 РОЗРОБЛЕННЯ СТАРТАП-ПРОЕКТУ PAGEREF _Toc26294735 \h 614.1 Опис ?де? проекту PAGEREF _Toc26294736 \h 614.2 Технолог?чний аудит ?де? проекту PAGEREF _Toc26294737 \h 634.3 Анал?з ринкових можливостей запуску стартап-проекту PAGEREF _Toc26294738 \h 654.4 Розроблення ринково? стратег?? проекту PAGEREF _Toc26294739 \h 724.5 Розроблення маркетингово? програми стартап-проекту PAGEREF _Toc26294740 \h 75Висновки до розд?лу PAGEREF _Toc26294741 \h 80ВИСНОВКИ ПО РОБОТ? PAGEREF _Toc26294742 \h 81ПЕРЕЛ?К ПОСИЛАНЬ PAGEREF _Toc26294743 \h 82ДОДАТОК А. ЛIСТИНГ ФАЙЛIВ PAGEREF _Toc26294744 \h 85ВСТУПВ сучасному св?т? важко знайти людину, яка б не грала в ?гри. В кожного вподобання на ?гри сво? - хтось полюбля? сес?йн? ?гри з друзями, хтось ААА ?гри з голл?вудським сюжетом, а хтось не може соб? в?дмовити в?д години перед сном за “три в ряд”. Проте за кожною такою грою сховано безмежна к?льк?сть старань не т?льки в?зуальних дизайнер?в та гейм розробник?в, а й гейм дизайнер?в - це люди котр? продумують для вас гру в?д початку до к?нця, визначають складн?сть гри, розробляють механ?ки гри ? взагал? кожну деталь з якою стика?ться гравець. ? одна з самих головних виклик?в для геймдизайнера - це саме баланс асиметрично? гри.Для початку важливо зрозум?ти: що ж все-таки ? асиметрична гра? Це ?гри в як?й противники розпочинають з нер?вних умов, наприклад хтось один ма? можлив?сть ходити першим, а бо ж при роздач? початкових ресурс?в, ресурс?в не р?вна к?льк?сть у вс?х гравц?в. В таких ?грах баланс гри форму?ться на основ? багатьох фактор?в, б?льш того у кожно? гри вони можуть бути сво?, проте все це можно звести до простого тезису, який би описував проблему балансу в асиметричних ?грах - знаходження р?вноваги всередин? системи, в як?й вза?мод?ють безл?ч р?зних елемент?в, при цьому спос?б вза?мод?? також р?зний.?деальним прикладом класично? асиметрично? гри з гарним балансом - ? шахи. Шахи гра асиметрична, не дивлячись на те що ф?гури гравцям видаються однаков?, але можлив?сть ходити першим, да? неабияк? переваги на початку гри, нав?ть теор?я спортивних шах?в почина?ться саме з порядку ходу, оск?лька стратег?я ходу зв?дси зм?ню?ться. З урахуванням нав?ть такого дисбалансу - завдяки функц?ям ф?гур через 3 ?гров? кроки гра може вир?внятися. Все ж з чого склада?ться баланс шах?в? Це р?зноман?тн?сть ф?гур, ?х к?льк?сть, симетричн?сть позиц?й ? сам? позиц?? грають неабияку роль. Т?льки уяв?ть, або спробуйте вдома, якби ряд п?шок ? ряд з королем зм?нились би м?сцями - цього достатньо, щоб вс? сучасн? книги про спортивн? шахи стали грудою непотребу. Сучасн? шахи мають такий баланс завдяки десятил?ттям чи нав?ть стол?ттям формування, адже ще в стародавн?й римськ?й ?мпер?? були знайден? перш? артефакти схож? на шахи.Приклад?в гарного балансу сучасних ?гор можна привести багато, проте вони формувалися не одну верс?ю або покол?ння, тому для ускорення цього процесу необх?дна система балансування ?гор, про яку ? буде м?й диплом. Звичайно ун?версально? точно? в?дпов?д? для будь-яко? гри довол? важко знайти, проте в?дм?тити слабк? м?сця, чи запропонувати зм?ни в гр? моя система зможе.Отже стандартним кейсом вза?мод?? гри з системою балансування буде введення вх?дних даних асиметрично? гри в систему для анал?зу балансу, оц?нки складност? та рекомендац?й для пол?пшення.РОЗД?Л 1 ОГЛЯД ПРОБЛЕМАТИКИ ПОБУДОВИ БАЛАНСУКращ?й геймдизайнер Plarium Анатол?й Шестов опубл?кував в сво?му блоз? переклад одн??? з лекц?й курсу ?Принципи ?грового балансу? ?грового дизайнера Яна Шрайбера, який працював над такими проектами, як Marvel Trading Card Game ? Playboy: the Mansion.Для початку я б запитав у вас ?що ж таке ?гровий баланс??. Можливо, занадто спрощуючи визначення, ми можемо сказати, що ?гровий баланс займа?ться з'ясуванням чисел, як? сл?д використовувати в гр?.? тут же виника? питання: а що якщо в гр? нема? н?яких чисел ? н?яко? математики? Наприклад, у дитяч?й гр? квача нема? чисел. Чи означа? це, що поняття ??гровий баланс" не застосову?ться до хованки?Насправд?, числа в квача ?: на яку в?дстань ? з якою швидк?стю може б?гти кожен з гравц?в, як далеко один в?д одного знаходяться гравц?, розм?ри ?грового майданчика, як довго хто-небудь з учасник?в водить. Ми не в?дстежу?мо вс? ц? параметри, тому що квач - непрофес?йний спорт. Але якби вони ?м були, пов?рте, у нас би були колекц?йн? картки ? сайти, що м?стять всю цю статистику з купою цифр.Отже, в кожн?й гр? ? сво? числа (нав?ть якщо вони прихован? ? неявно), ? метою цих чисел ? опис стану гри.Визначити, наск?льки гра збалансована, - не завжди просте завдання. Наприклад, т? ж шахи не ?деально збалансован?: спостер?га?ться деяка перевага в тому, щоб ходити першим. Хоча не вдалося з повною впевнен?стю довести, що це порушення р?вноваги в?дбува?ться з механ?ки (тобто чисте тактичне або стратег?чну перевагу першого ходу), а не з психолог?? (гравц? вважають, що у шимпанзе, що першим ? перевага, тому повол? грають г?рше, коли ходять другими ).Ц?каво, що переваги першого ходу зовс?м нема? на початкових р?внях волод?ння грою, воно з'явля?ться т?льки на турн?рах чемп?он?в. Не забувайте: це гра, в яку грають в тому чи ?ншому вигляд? вже тисяч? рок?в. А ми до сих п?р не зна?мо, чи добре вона збалансована.У випадку з шахами, високий р?вень майстерност? порушу? баланс гри. В ?нших випадках все навпаки - досв?дчен? гравц? можуть виправити притаманну гр? незбалансован?сть майстерною техн?кою.Наприклад, в гр? Settlers of Catan д?я розгорта?ться навколо торг?вл? ресурсами з ?ншими учасниками. Якщо один з гравц?в ма? невелику перевагу з-за кращо? стартово? позиц??, ?нш? вир?шують просто не торгувати з ним якийсь час (або пропонують нер?вний обм?н, невиг?дний процв?таючому гравцев?) до тих п?р, поки його позиц?я не зр?вня?ться з ?ншими. Цього не в?дбува?ться, якщо грають початк?вц? гравц?, тому що вони просто не вм?ють розглед?ти таке не значну перевагу на ранн?х етапах. Тим часом, на р?вн? турн?р?в, учасники швидше пом?чають початковий дисбаланс ? д?ють в?дпов?дно. Як бачите, ?гровий баланс - непроста ? неочевидна завдання.Основи ?грового балансу: Детерм?нован?, недетерм?нован? ? розв'язн? гриСкладання критичного словника. Нам необх?дно дати визначення к?лькох ключових терм?н?в, як? ми будемо використовувати при обговоренн? р?зних вид?в балансу.Ми будемо вживати вираз ?детерм?нована гра? для тако? гри, де при певному ?? стан? одне ? те ж д?ю буде завжди приводити до одного ? того ж нового стану гри.Шахи, го ? шашки - детерм?нован? гри. Тут н?коли не виникне ситуац??, коли ви руха?те ф?гуру, але через непередбаченого результату, який випав на к?стках, ваша ф?гура губиться десь по шляху або в?дбува?ться щось под?бне (х?ба що ви гра?те в якийсь детерм?нований вар?ант).Candyland ? Chutes & Ladders - недетерм?нован? гри. У кожн?й з них ? механ?зм випадковост? для того, щоб визначати ходи гравця, тому ви н?коли не зна?те, наск?льки просунулися в наступний раз.Покер - теж недетерм?нована гра. Ви можете грати посп?ль к?лька роздач, де стан гри буде здаватися однаковим (в?дкрит? карти на стол? ? карти у вас на руках т? ж), але результати роздач? будуть ?ншими, тому що ви н?коли не можете точно знати, як? карти на руках у ваших суперник?в .?Кам?нь-ножиц?-пап?р? - недетерм?нована гра в тому сенс?, що кожен викинутий жест (наприклад, ?кам?нь?) колись буде вигравати, колись програвати, а колись давати н?чию - все залежить в?д вибору противника.Зверн?ть увагу, елемент детерм?н?зму ? в кожно? з цих ?гор. Наприклад, коли ви кинули к?стки в Chutes & Ladders, в?дпов?ли на ставку в покер? або викинули жест в ?кам?нь-ножиц?-пап?р?, гра дозволя?ться зг?дно детерм?нованим правилам. Якщо ви викинули ?кам?нь?, а ваш противник - ?пап?р?, результат завжди буде однаковим.Протилежн?стю детерм?нованою гри ? недетерм?нована гра. Найпрост?ше про?люструвати р?зницю на приклад? класично? аркади Pac-Man ? ?? продовження М s. Pac-Man.Незважаючи на те, що ?грового балансу, як в?домо, не ?сну?, ? г?потези, м?фи, емп?ричн? методи, способи, як його виявити. У ц?й лекц?? мова п?де про те, з чого склада?ться ?гровий баланс, для чого в?н потр?бен, ? як збалансувати свою гру для того, щоб вона була ц?кавою.На ц?й схем? видно, що таке баланс. Баланс, перш за все, - це не наб?р цифр, як? повинн? якимось чином зр?внятися, це не табличка в екселя, не спроба вр?вноважити що-небудь з чим-небудь. Насправд?, це спроба зробити гру б?льш ц?л?сною ? ?грабельной.В однокористувальн?й гр? – це виклик по часу. В багатокористувацьк?й – це дом?нування одн??? з? стор?н. Там де дек?лька стратег?й – дом?нування т??? чи ?ншо?. При вза?мод?? об'?кт?в – сп?вв?дношення вигоди т??? чи ?ншо? з? стор?н.?гровий баланс - це, перш за все, досягнення верхньо? точки цього вузького коридору, фана. Якщо ви зробите гру занадто простий, вона буде нудною. Якщо ви зробите гру занадто складною, вона теж не буде приносити фана, а т?льки лише б?ль. Ваше завдання - потрапити в цей дуже вузький д?апазон. Це ? ? той самий баланс. Баланс склада?ться в тому числ? ? з математики. Причому математика - це не найб?льша частина балансу. Це, скор?ше, рутинна частина, яку доведеться робити.Найб?льша частина, яку доведеться робити - це плейтести. Вам доведеться грати в гру неск?нченно довго.Чому ?грового балансу не ?сну?? Тому що його неможливо прорахувати. Таблиця в екселя - це всього лише окремий випадок, як?сь реч?, як? можна схопити ? порахувати, але не вс? це можна зробити.?сну? р?зний контекст, в якому варто розглядати ?гровий баланс.Коли ми говоримо про однопользовательские гри (там теж ? баланс), ми торка?мося насамперед складн?сть - кожен р?вень в гр? повинен бути складн?ше попереднього, тод? гравець буде в?дчувати фан, зростання свого ск?лла, зм?ни та виклики з боку гри. Баланс в одного користувача ?грах визнача? складн?сть гри, складн?сть вза?мов?дносин об'?кт?в м?ж собою в час?.У багатокористувацьких ?грах:Визначення переваги т??? чи ?ншо? сторони - коли гравц? отримують р?зну зброю, вибирають персонаж?в р?зних клас?в. Гра ? збалансованою, коли класи персонаж?в, як? вибирають гравц?, збалансован? один з одним. Тобто, наприклад, нема? н?яких ?мбових юн?т?в, коли можна отримати б?льшу перевагу при невеликому ск?лу.В ?грах, де ? к?лька стратег?й шлях?в досягнення, ми використову?мо терм?н баланс, щоб пояснити, яка стратег?я краще або г?рше, н?ж ?нша.В ?грах, де ? к?лька р?зноман?тних ?грових об'?кт?в, як, наприклад, в карткових ?грах, ми говоримо про баланс вза?мини м?ж цими об'?ктами ? синерг?ю цих об'?кт?в.?гров? систем? бувають Симетричн? та Асиметричн?. Симетричн?: Р?вн? умови для гравц?в на початку ?грово? сес??; р?вн? з позиц?? простору, ресурс?в та об'?кт?в вза?мод??. Асиметричн?: Р?зниця в початкових умовах; позиц?я, виб?р об'?кт?в вза?мод??, правила вза?мод??, початков? ресурси.?сну? 2 основних ?грових системи: симетричн? (шахи, футбол, Counter-Strike) - гри, де обидв? сторони починають з однаковими умовами, ? асиметричн? (кам?нь, ножиц?, пап?р, StarCraft).Зда?ться, що симетричн? гри балансувати дуже легко: робиш одну сторону ? таку ж другу. Але насправд? там ? теж сво? складност?. У шахах ?сну? стратег?чну вагу кожно? ф?гури. Це теж елемент балансу, а балансувати елементи нав?ть одного боку м?ж собою непросто. У симетричн?й гр? дуже важливо мати р?зноман?тн?сть, вона не повинна бути гомогенною. Найг?рший баланс - це той, в якому р?зниця м?ж об'?ктами вза?мод?? м?н?мальна. Яким би об'?ктом ти не грав, ти отриму?ш один ? той же досв?д. Це гомогенний баланс, який призводить до нудьги. Без коня шахи були б не так? фанов?. ?грове поле в шахах склада?ться з 64 кл?тин, це результат емп?ричного балансу. Виявилося, що 8 на 8 - оптимальний розм?р для швидкост? розвитку парт?я ? тактично? вар?ативност?.Сенс асиметричних ?гор в тому, що в?дносини м?ж об'?ктами, як? один з одним змагаються, не ? прямими. Найпрост?ший приклад: лицар може перемогти лучника, лучник може перемогти грифона, грифон може атакувати лицаря. Це зроблено для того, щоб по-перше, створити р?зноман?тн?сть, а по-друге, створити р?зн? тактики гри. Розум?ючи вза?мини м?ж об'?ктами, гравець вибира?, яка тактика для нього в даний момент п?дходить. Асиметричн?сть створю? коло. У гр? StarCraft таких к?л дуже багато, б?льш того, ця гра - ун?версальний приклад одного з кращих баланс?в в ?гров?й ?ндустр??, де ? р?зноман?тн?сть тактик.Асиметр?я з'явля?ться через в?дчутно? р?зниц? м?ж початковими умовами гравц?в.Street Fighter - абсолютно асинхрона гра. Матриця на зображенн? показу? вза?мини м?ж персонажами. Це матч? м?ж персонажами ц??? гри, в як? грали експерти. Коли у вас ? багато персонаж?в, як? важко пор?вняти один з одним через р?зн? модел?, ?диний адекватний спос?б балансу - емп?ричний або статистичний. Статистичний спос?б можна використовувати, коли гра вже вийшла, а до цього ?дине, що ви можете зробити - це записати результати плей тест?в у вигляд? тако? таблиц? ? сортувати так, щоб це було зрозум?ло: нижн?й персонаж - найслабк?ший, а верхн?й - найсильн?ший.Парадигма балансуКоли ви почина?те баланс, вам необх?дно придумати, зв?дки брати цифри. Перше, що ви почина?те робити, це створювати парадигми, на основ? яких ваш баланс буде будуватися. ?сну? 2 методи.Перший - метод в?д способуХудожник накида? скетч, а ви, виходячи з цього, сам? придуму?те, як? у них повинн? бути характеристики ? отриму?те приблизно наступне:Стр?лець: Сила – 20 Атака – 90 Захист – 5 Швидк?сть – 100.Лицар: Сила – 100 Атака – 60 Зах?ст – 30 Швидк?сть – 10.Це те, зв?дки можна брати початков? цифри. Вони можуть бути абсолютно рандомних, головне, щоб ви розум?ли в?дносини цих цифр: цей важкий, сильний, товстий, а цей худенький ? слабкий, але дуже швидкий ? так дал?.Другий метод - в?д характеристикКоли вам задають як?сь початков? характеристики. Бувають ?гри, в яких ти почина?ш в?д цифр, таке ц?лком можливо. Коли, наприклад, мова йде про sci-fi, а не про реальне життя. Коли ви робите sci-fi гру, вам легше починати в?д цифр, розум?ючи, що повинн? бути як?сь швидк? юн?ти, повинен бути якийсь один великий, який несе ?х усередин? ? так дал?. Часто ви не зна?те образу, але ви можете його побудувати на основ? характеристик.Зв?дки брати початков? значення? К?лька практичних приклад?в, зв?дки можна взяти початков? значення в самому початку балансування ?гри:1 – Визнача?те, в?д чого буду в?дходити та описуватися в?доме та бажане: довжина сес??, розм?р юн?та на пол?, бажана частина рендома, час в?д 0 до 100 р?вня ? тд.2 – Виводи все, що можна зв'язати ( довжина сес?? > юн?ти мають швидко вбивати один одного, так ми отрима?мо св?вв?дношення атаки та захисту; розм?р юн?та > цифра ма? вм?ститися в хелсбар ? тд)3 – Будуйте прогрес?ю: посл?довн?сть умовних цифр, в?д яко? залежить параметри вс?х об'?кт?в. Базова шкала.4 – Створ?ть базовий або “середн?й об'?кт”.5 – В?д середнього балансувати ?нш? об'?кти.Види балансуНасправд?, баланс ма? величезну к?льк?сть р?зноман?тних вектор?в. Почнемо з головного вектора, який найчаст?ше мучить гейм-дизайнера: 1.3.1 Вид балансу - силаЦе в?дносини об'?кт?в, як? вза?мод?ють з позиц?? сили один з одним в гр? (юн?ти в стратег??, персонаж? з мобами в RPG, машинки, як? ?здять по дорогах ? обганяють один одного). ?сну? три методи балансування: транзитивний, ?нтранзитивний ? некомпаративний.Транзитивний метод: пряме пор?вняння або сп?вв?дношення характеристик об'?кт?в. У нас ? 2 людини, один з них товстий ? пов?льний, а ?нший - тонкий ? швидкий. Ц? параметри ми можемо пор?вняти один з одним безпосередньо. Тобто, скласти таблицю, де йде в?дношення вс?х цих однакових параметр?в для р?зних об'?кт?в. Це найпрост?ший вид балансу: ви склада?те таблицю ваших об'?кт?в, у вс?х ?дин? характеристики, ? кожен з них можна пор?вняти один з одним ? збалансувати.?нтранз?т?вний метод. Як його балансувати? Або ви буду?те матрицю, коли у вас об'?кти один з одним стикаються, ? ви розда? ?м окуляри. можна взяти приклад з картково? гри: якщо у вас ? багато об'?кт?в з р?зними характеристиками, ?диний спос?б ?х пор?вняти - проводити матч?. У мене була карткова гра, в як?й потр?бно було пор?вняти 40 карт один з одним. У них були р?зн? аб?лк?. Я написав скрипт, який дозволя? вважати енну к?льк?сть бо?в ? зробив так, щоб в таблицю вводилися найб?льш ?мбовие карти. В?дпов?дно, я в?дкривав цю карту, намагався зрозум?ти, чому вона перемага? ?нш?, намагався ?? якось занерф?ть, запускав скрипт заново ? намагався зробити так, щоб викид?в було якомога менше.Некомпаративная метод: спос?б балансування сили тод?, коли ви н?чого не можете зробити. Уяв?ть соб?, що у вас ? гра, в як?й д?йсно дуже багато об'?кт?в, а ви просто поганий гейм-дизайнер ? не вм??те робити баланс. Що можна зробити в ц?й ситуац??? Можна просто дати юнитам незр?внянн? аб?лк?. Наприклад, заморозка ? телепорт. Як ?х пор?вняти м?ж собою? Н?як. Це, звичайно, буде ?люз?я для гравця, але ви таким чином прикри?те свою бездарн?сть як гейм-дизайнер.Деяк? прийоми балансування:Балансування в?д середнього: в транзитивних моделях, коли вам потр?бно збалансувати або карти, або раси в RPG, потр?бно створити середнього людини. Часто в RPG людина використову?ться як усереднене ?стота. Ви пишете для нього як?сь усереднен? характеристики в дус?: 100, 100, 100, 100. Це ваш середн?й юн?т, щодо якого ви баланс?руете вс? ?нш?. Чим б?льше ви будете прив'язуватися до реальност?, тим легше гравцев? буде це зрозум?ти. Дал? ви вважа?те power. Power людини - це сума вс?х його характеристик. Пот?м вважа?те power будь-якого ?ншого ?стоти ? якщо ви розд?лили ? отримали одиницю, все добре.Групи за часом: якщо у вас величезна к?льк?сть об'?кт?в, ну, до прикладу, 1000 карт. Як бути? Збалансувати в?дразу 1000 карт дуже важко. Ви д?лите 1000 карт по сотням ? розпод?ля?те ?х по часу, з самого початку позначаючи, що у вас перша сотня - найслабш? карти, остання - найсильн?ш? ? баланс?руете вже те, що знаходиться всередин?. ? змушу?те гравця зм?нювати тири за рахунок ускладнення. У вас з'явиться крива складност? ? наступн? карти - другого тиру - вийдуть сильн?ше, н?ж попередн?. Таким чином ви позбавите себе в?д необх?дност? балансувати 1000 карт. Ви просто завжди працю?те з меншою к?льк?стю.Все приводити до одного параметру: ? дв? характеристики для бойових ?гор, до яких все завжди прийдете, будучи гейм-дизайнером (DPS ? HPS). HPS - це параметр ?живучост?? юн?та, карти, об'?кта. DPS - це параметр атаки, його впливу на ?нш? об'?кти. По сут?, пошкодження в одиницю часу. До цих параметр?в можна звести все, в тому числ? ? аб?лк?. Наприклад, баф - це очевидний елемент, який зб?льшу? DPS юн?та. Природно, ти не можеш знати, коли тв?й об'?кт активу? цей баф. Тому ти просто говориш, що в?н активу?ться р?вно через кожну його тривал?сть. Наприклад, баф д?? 10 секунд, б?й трива? хвилину, ? кожн? 10 секунд вважа?ш в сво?му DPS до к?нця. Вважа?мо, що гравець пост?йно тисне, коли у нього cool down зак?нчу?ться. Наприклад, прискорення - це те ж саме: можна все перетворити в DPS, тому що прискорення зб?льшу? ?н?ц?ативу юн?та ? в?н б'? част?ше.На зображенн? написано, як робити п?драхунок сумарно? потужност?. ? два простих способи. Перший - сума характеристик, як? ви пор?вню?те м?ж собою ? тод? визнача?те, збалансован? ц? об'?кти чи н?. Другий - це коли ви приводите DPS до HPS ?, в?дпов?дно, ваш power буде в?дпов?дати DPS, помноженому на HPS. Таким чином ви можете пор?внювати вс? об'?кти вза?мод??.Я ?нод? використовую так? граф?ки, щоб оц?нювати, наск?льки р?зняться юн?ти м?ж собою ? який з них в який б?к йде. Площа ц??? ф?гури познача? power ц??? ?стоти. Природно, по кожному з вектор?в, scale може бути р?зний. Тому що швидк?сть може вим?рюватися в одному д?апазон?, сила - в ?ншому. Але головне, це дуже наочно показу?, де у вас танк, а де, наприклад, ассас?н, але це окремий випадок. Я використовую такий спос?б, щоб ч?тко розд?ляти класи, як?сь карти або персонаж?в.1.3.2 Види балансу – часДуже важливий вид балансу - час. Очевидно, що час ? нев?д'?мною частиною гри, в як?й ? прогрес. ?сну? 3 контексту часу в баланс?, про як? варто говорити.Перший контекст - це контекст виникнення ?грових под?й. У квестах, до реч?, це дуже важливий момент. Якщо взяти адвенчури, в яких гравець ма? пряме управл?ння, наприклад, це така сум?ш аркади ? квесту, то час виникнення под?й гра? там досить важливу роль. ? балансування часу в даному випадку ма?ться на уваз?, що потр?бно ч?тко д?лити, коли, в який час гравцев? подати под?я, щоб йому не було нудно або навпаки, як зробити так, щоб гравець не перенаситився тим, що йому подають. Ось, наприклад, хоррор - гри дуже добре вм?ють з цим працювати, той же Resident Evil 7. Там все розраховано р?вно так, що через певний час твого руху з'явля?ться певний под?я для того, щоб ти злякався. Спочатку тебе до цього п?дготували музикою ? створенням напруги, якийсь час н?чого не в?дбува?ться, ти розслабля?шся, ? раптом тоб? страшно.Час розвитку ?грових сутностей - це дуже просто. Ферми, б?лдери, ?гри, в яких ? прокачування персонаж?в - в них теж ? час, який потр?бно вм?ти балансувати. В?д чого воно залежить? Балансування конкретно часу розвитку ?грових сутностей поляга? в наступному: ви визнача?те довжину ?грово? сес??, частоту виникнення в?дкритт?в для гравця, спираючись на к?льк?сть контенту, яке у вас ?. Я зараз говорю про моб?льн? ?гри, тому що там це працю? дуже добре. Ця методика абсолютно ч?тко чита?ться. Наприклад, вам в?домо, що середня тривал?сть ?грово? сес?? 15 хвилин, ви припуска?те, що ваш? гравц? гратимуть кожен день по одн?й сес??. В?дпов?дно, для того, щоб гравцю не стало нудно, йому потр?бно в кожн?й сес?? в?дкривати щось нове. Це ваша основа для таймера. Наприклад, гравець запуска? на початку першо? сес?? апгрейд свого юн?та, в к?нц? сес?? в?н повинен отримати якийсь level-up. Кр?м того, що у вас ? короткостроков? завдання, ви под?ля?те ваш час на 3 довжини: коротка, яку ви отриму?те за сес?ю, середня - це коли запуска?ться на ц?й сес??, а в?дбува?ться в наступн?й, ? довгострокова, щоб повернути гравця, припустимо, через 3 сес??. Це те, на що потр?бно спиратися, коли ви продуму?те, яким чином вам побудувати таймер розвитку ?грових сутностей. Це можуть бути будиночки, вирощування моркви, це можуть бути юн?ти, як? апгрейд. Для чого це потр?бно? Природно, це вплива? на ?нтерес до гри, тому що гравець отриму? в?дкриття згодом. Саме тод?, коли потр?бно. Друге: гравець повинен оч?кувати: в?н в?дкрив таймер, який спрацю? в наступн?й сес??, ? у нього в голов? в?дклада?ться, що в наступну сес?ю щось станеться. Наприклад, побудувати будиночок. Це його поверта?. ? ц? довгостроков? завдання дозволяють повернути його ще через к?лька сес?й. П?д free-to-play ?грах це дуже важливо.Зсув - перекриття под?й. У гр? Stellaris под?? в?дбуваються так, що вони починають перекривати один одного, ? у гравця майже завжди ? нове в?дкриття. Це дуже грамотно зроблений баланс часу. Ти запуска?ш там таймер, але вони побудован? таким чином, що вони перекривають один одного ? пост?йно тримають тебе в гр?. У Цив?л?зац??, до реч?, схожа модель. Ви збиралися годину пограти в цю гру, а вже 4 ранку.Хл?бн? крихти. Коли ви робите якийсь дуже довгий таймер, роб?ть пром?жн? нагороди. Наприклад, якщо у вас герой розвива?ться 10 годин, гравцев? буде дуже нудно. Давайте йому через кожну годину, наприклад, коротк? rang up'и, як? покажуть, що в?н руха?ться до прогресу в час?. Тобто, не можна робити занадто довг? таймери, як? гравця демотивують, тому що в?н не бачить свого вкладу в це. Особливо коли мова йде про level up'и.1.3.3 Вид балансу – прост?рЛевел-дизайн - це частина ?грового дизайну ? гейм-дизайнери, хоч ? не роблять р?вн? сам?, але повинн? знати, що прост?р - це нев?д'?мна частина балансу гри. Зокрема, ? к?лька прийом?в, як балансувати прост?р. Мультипле?рний карти найчаст?ше роблять дзеркальними. Тому що у вс?х команд, як? беруть участь в гр? виходять р?вн? умови. Як ми зна?мо, прост?р корелюють м?ж собою. Симетричн? карти хорош? тим, що там ? достатньо часу ? достатн?й обсяг простору, тобто, за рахунок в?ддзеркалення, все отримують р?вн? умови. Карти маршрут?в: коли ви створю?те будь левел-дизайн, перше, що ви почина?те малювати - це карту перем?щення гравця. Незалежно в?д того, мережева це карта або це розрахована на одного гра. По сут?, ви буду?те граф, в якому позначають точки перетину гравц?в. У мульт?пле?рних картах повинно бути 3 в?дгалуження в?д кожного перехрестя, щоб гравц? могли перетинатися. Прост?р може розширюватися ? звужуватися, залежно в?д того, чого ви хочете домогтися.Що таке схема нав?гац??? На будь-як?й карт? повинн? бути ор??нтири, гравець завжди повинен знати, де в?н знаходиться. На кожн?й карт? повинн? бути певн? точки, як? дозволять гравцев? зор??нтуватися ? пояснити ?ншим гравцям, куди б?гти. Це теж елемент балансу, який потр?бно мати на уваз?. ?, в?дпов?дно, конф?гурац?я бойових областей - у вас не повинен бути надто складний лаб?ринт, карта повинна добре читатися. Якщо гра в жанр? sci-fi, на не? теж можна екстраполювати схему нав?гац??. Космос - це теж шлях, в якому можна пересуватися по з?рках.1.3.4 Вид балансу – економ?каУ баланс? економ?ки важливо: визначити ц?нн?сть вс?х об'?кт?в, як? ? в гр?. Зокрема, збро?, машини, карти ? так дал?.Побудова д?аграми в?дносин ресурс?в, ресурсний цикл. Дуже важливо правильно прорахувати, на що будуть витрачатися ресурси ? як вони будуть виходити ? побудувати цикл, за яким ч?тко видно з будь активностей що гравець здобува? ? на що в?н може це витратити. Дуже важливо, щоб в балансовому цикл? не було ситуац?й, коли ресурс купу?ться, але дуже мало куди витрача?ться. Ресурсний цикл може зм?нюватися в час?: спочатку один ресурс був затребуваний ? на нього було б?льше витрат, в ендгейм? в?н може витрачатися менше, а якийсь ?нший - б?льше.Под?л ресурсних цикл?в з ?грових активностей. Знову приклад - Heroes Charge, там кожна активн?сть ма? сво? ресурс ? валюту. Це зручно тим, що ви таким чином скорочу?те час балансування. Тобто, якщо у вас дуже велика ? складна економ?ка, д?лите ?? на м?кроеконом?ки. Якщо ви д?лите ?? на ресурси, виходить маленький цикл, який легше балансувати.Побудова шкали асортименту для р?зних груп користувач?в. Це дуже важливо для free-to-play гри. Якщо у вас гра, в як?й ? т?льки 2 in-app'а, це поганий free-to-play. По-хорошому, чим ширше у вас асортимент, тим б?льше можливостей сп?ймати в ц? мереж? покупця. Тобто, намагайтеся, щоб у вас в гр? було, що купувати.Прив'язка ц?н до ном?налах банкнот ? типовим затратам. Це один ?з способ?в таких метод?в, як придумати, ск?льки кошту? ваш in-app. Дуже часто задають питання, як придумати in-app ? ск?льки в?н повинен коштувати. Найпрост?ш? способи вказан? на зображенн?. Припустимо, для нас 10 гривень в маршрутц? - це в?дчува?ться витрата, щодо яко? можна взяти м?н?мальний in-app в Укра?н?. Тобто, це в принцип? те, на що людина може витратитися легко. Для американц?в 1 $ - це комфортний in-app. ? деяк? типов? витрати, наприклад, ск?льки витрача? людина в магазин?. Наприклад, 300 гривень. Це така середина для Укра?ни.Дуже добре, коли in-app прив'язаний до ном?налу банкнот. Люди пост?йно бачать ?х у себе в гаманц? ? легко ?х асоц?юють. Це дуже хороший ? простий прийом, за допомогою якого можна придумати ц?нн?сть свого in-app'у.Оц?нка попиту на товар, еластичн?сть попиту. Ви можете прогнозувати ?? на початку, але насправд?, найчаст?ше та економ?ка, яку ви спрогнозували, до к?нця гри буде вже не такий. Тому ви спочатку ставите варт?сть товару, щодо ц?нност?, яку ви визнача?те на початку, а п?сля цього, коли отрима?те статистику, ви почина?те ?? оц?нювати за допомогою еластичност? попиту. Розраховувати, наприклад, точковий попит, ? по еластичност? визначати його точну ц?ну. Ви н?коли не зможете спочатку це придумати.1.3.5 Вид балансу – складн?стьБудь-яка складн?сть в гр? - це якась зростаюча функц?я. Найпрост?ша складн?сть - це пряма л?н?я, яка пост?йно зроста?. Але насправд?, це погана складн?сть, тому що вона фрустрирует. Добре, коли складн?сть пост?йно пульсу?. Насправд? це просто посл?довн?сть виклик?в ? релаксу. П?сля того, як гравець отримав виклик, не потр?бно давати йому новий виклик, дайте йому можлив?сть в?дпочити. Кр?м цього, коли ви п?сля челенджу да?те гравцев? Ревард сили, теж потр?бно дати йому в?дчути себе крутим на якийсь час, ? т?льки пот?м давати нову сходинку. Ця зубчаста л?н?я створю? бадьор?сть для гравця. У деяких ?грах добре зробити п?дготовку, м?крочеллендж перед великим, наприклад, миньонов перед великим босом. Кр?м цього, добре, коли у вас ? певний коридор, по якому йде ця крива. Якщо складн?сть впаде нижче порогово? л?н??, це буде занадто просто.Вважайте FU-фактор. Ставлення спроб до виграшу до спроб близького досягнення мети, на р?вн?, наприклад. Чим б?льше це значення, тим г?рше налаштований р?вень. У match-3 цей параметр ? одним з ключових для того, щоб вим?ряти, наск?льки гравцям заходить р?вень. Коли гравець наближа?ться до мети, наприклад, йому залиша?ться один х?д, щоб зак?нчити, це означа?, що у нього залиша?ться почуття, що ще трохи ? все буде класно. ?деальний FU-фактор наближа?ться до ц??? одиниц?, до цього останнього ходу. У Gardenscapes дуже добре зроблено це в?дчуття, коли ти наближа?шся до кордону, залиша?ться один х?д, ? ти готовий задонатити в цей момент.Висновки до розд?луУ розд?л? було описано методи балансування гри в залежност? в?д тип?в та правил гри. Золот? правила балансу:Створюйте справд? р?зн? об’?кти.Легко вчитися, важко стати мастером.Використовуй зв'язок з реальн?стю, людина легко сприйма? те, що для не? близьке.Фан важлив?ше математики.Вм?й вчасно зупинитися, ?деальний баланс – ?люз?я.Естетика ? простота дуже важлив?: шкода 100 краще н?ж 102 нав?ть якщо другий збалансований.РОЗД?Л 2 МЕТОД МОНТЕ-КАРЛО. КОНСТАНТИ ТА ПРОГРЕС?ЯДля побудови системи балансування за основу в?зьму метод Монте-Карло, так як в ц?лях задач? мен? не потр?бна висока точн?сть, проте простий алгоритм метода допоможе зробити швидку реал?зац?ю, яку буде легко адаптувати до будь яких нових правил чи нових геро?в.2.1 Метод Монте-КарлоМетод Монте-Карло - це чисельний метод р?шення математичних задач за допомогою моделювання випадкових величин.Виникнення ?де? використання випадкових явищ в област? наближених обчислень прийнято в?дносити до 1878 р коли з'явилася робота Холла про визначення числа π за допомогою випадкових бросаний голки на розграфлен? паралельними л?н?ями пап?р. Щодо сут? поляга? в тому, щоб експериментально в?дтворити под?ю, ?мов?рн?сть якого виража?ться через число π, ? приблизно оц?нити цю ?мов?рн?сть.Датою народження методу Монте-Карло прийнято вважати 1949 р коли з'явилася стаття п?д назвою ?Метод Монте-Карло? (Н. Метропол?с, С. Улам). Творцями цього методу вважають американських математик?в Дж. Неймана ? С. Улама. У наш?й кра?н? перш? статт? були опубл?кован? в 1955-56 рр. (В.В. Чавчан?дзе, Ю.А. Шрейдер, В.С. Владимиров).З того часу накопичилася велика б?бл?ограф?я за методом Монте-Карло. Нав?ть поб?жний перегляд назв роб?т дозволя? зробити висновок про можлив?сть застосування методу Монте-Карло для вир?шення прикладних завдань з великого числа областей науки ? техн?ки.Спочатку метод Монте-Карло використовувався головним чином для вир?шення завдань нейтронно? ф?зики, де традиц?йн? чисельн? методи виявилися мало придатними. Дал? його вплив поширився на широкий клас задач статистично? ф?зики, дуже р?зних за сво?м зм?стом.Метод Монте-Карло зробив ? продовжу? робити ?стотний вплив на розвиток метод?в обчислювально? математики (наприклад, розвиток метод?в чисельного ?нтегрування) ? при вир?шенн? багатьох завдань усп?шно по?дну?ться з ?ншими обчислювальними методами ? доповню? ?х. Його застосування виправдане в першу чергу в тих завданнях, як? допускають теоретико-?мов?рн?сний опис. Це поясню?ться як природн?стю отримання в?дпов?д? з деякою заданою в?рог?дн?стю в задачах з ?мов?рн?сним зм?стом, так ? ?стотним спрощенням процедури вир?шення.Однак до появи ЕОМ цей метод не м?г знайти ск?льки-небудь широкого застосування, так як моделювати випадков? величини вручну - дуже трудом?стка робота. Таким чином, виникнення методу Монте-Карло як вельми ун?версального чисельного методу стало можливим т?льки завдяки появ? ЕОМ.Назва ?Монте-Карло? походить в?д м?ста Монте-Карло в княз?вств? Монако, знаменитого сво?м гральним будинком, а також одним з найпрост?ших механ?чних прилад?в для отримання випадкових величин - рулеткою.Спочатку метод Монте-Карло використовувався головним чином для вир?шення завдань нейтронно? ф?зики, де традиц?йн? чисельн? методи виявилися малопридатними. Дал? його вплив поширився на широке коло завдань статистично? ф?зики, дуже р?зних за сво?м зм?стом. До розд?л?в науки, де все в б?льш?й м?р? використову?ться метод Монте-Карло, сл?д в?днести задач? теор?? масового обслуговування, задач? теор?? ?гор ? математично? економ?ки, задач? теор?? передач? пов?домлень при наявност? перешкод ? ряд ?нших.Метод Монте-Карло зробив ? продовжу? робити ?стотний вплив на розвиток метод?в обчислювально? математики ? при вир?шенн? багатьох завдань усп?шно по?дну?ться з ?ншими обчислювальними методами ? доповню? ?х. Його застосування виправдане в першу чергу в тих завданнях, як? допускають теоретико-?мов?рн?сний опис. Це поясню?ться як природн?сть отримання в?дпов?д? з деякою заданою в?рог?дн?стю в задачах з ?мов?рн?сним зм?стом, так ? ?стотним спрощенням процедури вир?шення.У переважн?й б?льшост? завдань, що вир?шуються методами Монте-Карло, обчислюють математичн? оч?кування деяких випадкових величин. Так як найчаст?ше математичн? оч?кування ? звичайними ?нтеграли, в тому числ? ? кратн?, то центральне положення в теор?? метод?в Монте-Карло займають методи обчислення ?нтеграл?в.2.1.1 Теоретична частинаДеяк? дан? теор?? ймов?рностей. Припустимо, що нам необх?дно обчислити площу плоско? ф?гури. Це може бути дов?льна ф?гура, задана граф?чно або анал?тично (зв'язкова або склада?ться з дек?лькох частин), рис. 2.1.Рисунок 2.1 – Довiльно задана фiгураПрипустимо, що ця ф?гура розташована всередин? одиничного квадрата. Виберемо всередин? квадрата випадкових точок. Позначимо через число точок, потрапивших всередину ф?гури . Геометрично видно, що площа ф?гури приближенно р?вна в?дношенню . При чому, чим б?льше число , тим б?льше точн?сть ц??? оц?нки.Для того щоб вибирати точки випадково, необх?дно перейти до терм?ну випадкова величина. Випадкова величина безперервна, якщо вона може приймати будь-яке значення з деякого ?нтервалу .Безперервна випадкова величина визнача?ться заданим ?нтервалом , який м?стить можлив? значення ц??? величини, ? функц?? , яка назива?ться щ?льн?стю ймов?рност? випадково? величини (щ?льн?сю розпод?лу ). Ф?зичний зм?ст наступний: нехай – будь-який ?нтервал, такий що , тод? ймов?рн?сть того, що буде в ?нтервал? , дор?вню? ?нтегралу (2.1)Множина значення може бути любим ?нтервалом (можливий випадок ). Однак щ?льн?сть ма? задовольняти дв? умови:щ?льн?сть позитивна:;(2.2)?нтеграл в?д щ?льност? по всьому ?нтервалу р?вний 1:(2.3)Математичним оч?куванням неперервно? випадково? величини назива?ться число(2.4)Дисперс??ю неперервно? випадково? величини назива?ться число:.Нормальною випадковою величиною назива?ться випадкова величина , задана на вс?й ос? ? маюча щ?льн?сть (2.5),де – числов? параметриЛюба ймов?рн?сть вида легко п?драхову?ться за допомогою таблиц?, в як?й наведен? значення функц??,звано? зазвичай ?нтегралом ймов?рностей.Зг?дно (2.1), .В ?нтеграл? зробимо зам?ну зм?нно? , тод? отрима?мо –,де .Зв?дси в?рно наступне, що Також .Нормальн? випадков? величини дуже часто зустр?чаються при досл?дженн? самих р?зних за сво?ю природою питань.Вибираючи , , знайдемо . Зв?дси, (2.6)Ймов?рн?сть наст?льки близька до 1, що ?нод? останню формулу ?нтерпретують так: при одному випробуванн? практично неможливо отримати значення , в?дм?ну в?д б?льше ч?м на .Проводячи велику к?льк?сть досл?д?в, ? отримуючи велику к?льк?сть випадкових величин можна скористатися центральною граничною теоремою теор?? ймов?рностей. Ця теорема вперше була сформульована П. Лапласом. Узагальненням ц??? теореми займалися багато видатних математики, в тому числ? П.Л. Чебишев, А.А. Марков, А.М. Ляпунов. ?? доказ досить складно.Розглянемо одинаково незалежних випадкових величин , так що розпод?лу ймов?рностей цих величин зб?гаються. Отже, ?х математичн? оч?кування ? дисперс?? також зб?гаються. Величини ц? можуть бути як безперервними, так ? дискретними.Визнача?мо.Сума вс?х цих величин позначемо через .Використовуючи сп?вв?дношення .отриму?мо:.Розглянемо теперь нормальну випадкову величину з такими ж параметрами: .В центральн?й граничн?й теорем? стверджу?ться, що для будь-якого ?нтервала при великих .Сенс ц??? теореми в тому, що сума великого числа однакових випадкових величин наближено нормальна. Насправд? ця теорема справедлива при набагато б?льш широких умовах: вс? складов? не зобов'язан? бути однаковими ? незалежними; ?стотно т?льки, щоб окрем? складов? не грали велико? рол? в сум?. Ця теорема виправдову? часто зустр?чаються нормальн? випадков? величини. Справд?, коли зустр?ча?ться сумарний вплив великого числа незначних випадкових фактор?в, результуюча випадкова величина виявля?ться нормальною.2.1.2 Загальна схема метода Монте-КарлоПрипустимо, що потр?бно обчислити якусь нев?дому величину . Спробу?мо п?д?брати таку випадкову величину , щоб . Нехай при цьому .Розглянемо незалежних випадкових величин розпод?лу яких зб?гаються з розпод?лом . Якщо досить велике, то, зг?дно з центральною граничною теоремою, розпод?л суми буде приблизно нормальним с параметрами . З (2.6) виплива?, що .Останн? сп?вв?дношення перепишемо у вигляд?:(2.7)Це сп?вв?дношення да? ? метод розрахунку , ? оц?нку погр?шност?.Знайдемо значень випадково? величини . З (2.7) видно, що середн? арифметичне цих значень буде приближенно р?вне . З великою ймов?рн?стю погр?шн?сть приближення не б?льше величини . Ця погр?шн?сть наближа?ться до нуля з ростом . На практиц? часто використовують не оц?нку зверху , а на ймов?рну помилку, яка наближено р?вна Саме такий зазвичай порядок фактично? погр?шност? розрахунка, яка р?вна.Для отримання випадкових чисел використовують зазвичай три способи: таблиц? випадкових величин, генератори випадкових чисел ? метод псевдовипадкових чисел.Таблиц? випадкових чисел використовують переважно при розрахунках вручну. Визначальну роль в цьому в?д?грають два факти: 1) при використанн? ЕОМ легше ? зручн?ше скористатися генератором випадкових чисел, одержуваних тут же, чим загрожують з пам'ят? значення таблиц?, яка до того ж, буде займати там м?сце. 2) При п?драхунку вручну нема? необх?дност? використовувати ЕОМ, так як часто необх?дно з'ясувати лише порядок шукано? величини.Генератори випадкових чисел анал?зують будь-який процес, доступний для них (шуми, скачки напруги) ? складають посл?довн?сть з 0 ? 1, з яких складаються числа з певними розрядами, проте такий метод отримання випадкових величин ма? сво? недол?ки. По-перше, важко перев?рити виробляються числа. Перев?рки доводиться робити пер?одично, так як через будь-яких несправностей може виникнути так званий дрейф розпод?лу (нул? ? одиниц? в будь-якому з розряд?в стануть з'являтися не однаково часто). По-друге, зазвичай вс? розрахунки на ЕОМ проводяться к?лька раз?в, щоб виключити можлив?сть збою. Але в?дтворити т? ж сам? випадков? числа неможливо, якщо ?х т?льки не запам'ятовувати по ходу рахунку. А якщо запам'ятовувати, то знову з'явля?ться випадок таблиць.Таким чином, найефективн?шим способом отримання випадкових чисел - це використання псевдовипадкових чисел.Числа, отриман? по будь-як?й формул? ? ?м?туюч? значення випадково? величини , називаються псевдовипадковими числами.Перший алгоритм для отримання псевдовипадкових чисел був запропонований Дж. Нейманом. В?н назива?ться методом середини квадрат?в.Нехай задано 4-значне число . В?зьмемо його квадрат. Отрима?мо 8-значне число . Виберемо 4 середн? цифри цього числа ? покладемо .Дал? ? т.д.Але цей алгоритм не виправдав себе, оск?льки виходить занадто багато малих значень. Тому були розроблен? ?нш? алгоритми. Найб?льшого поширення набув алгоритм, званий методом пор?внянь (Д. Лемер): визнача?ться посл?довн?сть ц?лих чисел , в якому початкове число задано, а вс? наступн? числа п?драховуються по одн?й ? т?й же формул? при (2.8)По числам п?драховуються псевдовипадков? числа(2.9)Формула (2.8) означа?, що число р?вне залишку, отриманому при д?ленн? на , такий залишок називають найменшим позитивним в?драхування по модулю Формули (2.8), (2.9) легко реал?зувати на ЕОМ.Переваги методу псевдовипадкових чисел досить очевидн?. По-перше, на отримання кожного числа витрача?ться всього к?лька простих операц?й, так що швидк?сть генерування випадкових чисел ма? той же порядок, що ? швидк?сть роботи ЕОМ. По-друге, програма займа? не так багато м?сця в пам'ят?. По-трет?, будь-яка з чисел може бути легко в?дтворено. По-четверте, необх?дно лише один раз перев?рити ?як?сть? так?й посл?довност?, пот?м ?? можна багато раз?в безбоязно використовувати при розрахунку однотипних завдань.?диний недол?к методу - обмежен?сть к?лькост? псевдовипадкових чисел, так як якщо посл?довн?сть чисел п?драхову?ться на ЕОМ по формул? вида , то ця посл?довн?сть обов'язково пер?одична. Вт?м, для найб?льш поширених псевдовипадкових чисел пер?од наст?льки великий, що перевершу? будь-як? практичн? потреби. Переважна б?льш?сть розрахунк?в за методом Монте-Карло зд?йсню?ться з використанням псевдовипадкових чисел.Значення будь-випадково? величини можна отримати шляхом перетворення значень одн??? яко?-небудь випадково? величини. Зазвичай роль тако? випадково? величини гра? випадкова величина, р?вном?рно розпод?лена в (0, 1).Процес знаходження значення будь-яко? випадково? величини шляхом перетворення одного або дек?лькох значень назива?ться роз?груванням випадково? величини .Припустимо, що необх?дно отримувати значення випадково? величини , розпод?лено? в ?нтервал? , з щ?льн?стю, тод? можна довести, що значення можна знаходити з р?вняння(2.10),тобто обравши наступне значення , треба вир?шити р?вняння (2.10) ? знайти наступне значення .Може статися, що вир?шити р?вняння (2.10) в?дносно важко, наприклад, в випадках, коли ?нтеграл в?д не виража?ться через елементарн? функц?? чи коли щ?льн?сть задана граф?чно. Припустимо, що випадкова величина визначена на к?нцевому ?нтервал? ? щ?льн?сть ?? л?м?тована .Роз?грувати значення можна наступним способом:1) вибираються два значення ? випадково? величини ? буду?ться випадкова точка з координатами .2) якщо точка лежить п?д кривою , то вважа?мо , якщо ж точка лежить над кривою , то пара в?дкида?ться ? вибира?ться нове значення.2.1.3 Знаходження ?нтеграл?вРозглянемо функц?ю , задану на ?нтервал? , необх?дно приближено вирахувати ?нтеграл(2.11)Цей ?нтеграл може бути невласних, але абсолютно зб?жним.Виберемо дов?льну щ?льн?сть розпод?лу , задану на ?нтервал? . Разом ?з випадковою величиною , задану в ?нтервал? з щ?льн?стю, необх?дно знайти випадкову величину.В?дпов?дно сп?вв?дношенням ,отрима?мо –.Розглянемо тепер одинакових незалежних випадкових величин ? застосу?мо до ?х суми центральну граничну теорему. Формула (2.7) в цьому випадку запишеться так:Останн? сп?вв?дношення означа?, що якщо вибирати значень , то при достатньо вел?кому(2.12)Воно також показу?, що з дуже великою ймов?рн?стю погр?шн?сть приближення (2.12) не б?льше .Для розрахунку ?нтеграла (2.11) можна використовувати будь-яку випадкову величину . Задану на ?нтервал? з щ?льн?стю. В будь-якому випадку . Однак дисперс?я , а з нею ? оц?нка погр?шност? формули (2.12) залежать в?д того, яка величина використову?ться, так як (2.13)Не важко доказати, що це р?вняння буде м?н?мальним тод?, коли пропорц?йна . Використовувати щ?льн?сть для розрахунку практично неможливо, так як для цього треба знати значення ?нтеграла , а його п?драхунок представля? собою задачу, р?вноц?нну задач? про п?драхунок ?нтеграла (2.11). Тому бажано, щоб щ?льн?сть була пропорц?йна .Звичайно, обирати дуже складн? непотр?бно, так як процедури роз?грашу стане дуже працезатратною. Оц?нку (2.12) з щ?льн?стю, сх?дною , називають сутт?во? виб?ркою.Також якщо потр?бно обчислити ?нтеграл (2.11), перетворимо його до виду(2.16)Якщо тепер зазначити (2.17)То ?нтеграл прийма? вид – (2.18)? його можна обчислити за допомогою методу статистичних випробувань.В приватному випадку, якщо ? к?нечн? чи ?х можна рахувати к?нечно приближено, в якост? доц?льно вибрати р?вном?рний закон розпод?лу.Як в?домо, щ?льн?сть ймов?рност? р?вном?рного закону розпод?лу в ?нтервал? р?вна:(2.19)П?дставим в ?нтеграл (2.16) значення ?з формули (2.19) ? отрима?мо:(2.20)Процедура обчислення: ?з множени р?вном?рно розпод?ленних випадкових чисел вибира?ться . Для кожного значення обчислю?ться , пот?м обчислю?ться середн? значення функц?? на ?нтервал? (a, b) (2.21)Таким чином, величина ?нтеграла (2.11) може бути представлена в вид? наступно? формули (2.22)Розглянутий окремий випадок знаходить широке застосування ?нтеграл?в методом статистичного моделювання в силу того, що кордони област? визначення можуть бути легко приведен? до меж ?нтегрування.2.1.4 Обчислення кратних ?нтеграл?вЗазвичай при обчисленн? кратних ?нтеграл?в методом Монте-Карло використовують один з двох способ?в.Перший спос?б: Нехай треба обчислити кратний ?нтеграл (2.21)по област? G, яка лежить в м?рному одиничному куб? .Виберемо р?вном?рно розпод?леному на в?др?зку посл?довностей випадкових чиселТод? точки можна розглядать як випадков?, р?вном?рно розпод?ленн? в м?рному одиничному куб?.Нехай ?з загального числа випадкових точок точок потрапили в область G, ?нш? залишилися поза G. Тод? при достатньо великому ма? м?сце приближена формула:(2.23),де п?д вважа?ться м?рний об'?м област? ?нтегрування. Якщо обчислення об'?му важке, то можна прийняти , ? для наближенного п?драхунку ?нтеграла отрима?мо:(3.24)Зазначений спос?б можна застосувати до обчислення кратних ?нтеграл?в ? для дов?льно? област?, якщо ?сну? така зам?на зм?нних, при як?й нова область ?нтегрування буде укладена в м?рн?й одиничному куб?.Другий спос?б: Якщо функц?я y = f (x1, x2, ..., xm) ≥0, то ?нтеграл (2.21) можна розглядати як обсяг т?ла в (m + 1) -м?рному простор?, тобто(2.25),де област? ?нтегрування визначаються умовамиЯкщо в област? , то вводячи нову зм?нну , отрима?мо, де область лежить в одиничному м?рном куб? .В?зьмемо р?вном?рно розпод?леному на в?др?зку випадкових посл?довностейСп?вставимо в?дпов?дну посл?довн?сть випадкових точок .Нехай ?з загального числа випадкових точок точок належать об?му , тод? ма? м?сце наближенна формула: (2.26)Це означа?, що для забезпечення б?льшо? точност? число точок повинно бути дуже велике. Але так як наближен? формули (2.25), (2.26) не залежить в?д розм?рност? ?нтеграла, метод Монте-Карло виявля?ться виг?дним при обчисленн? ?нтеграл?в велико? розм?рност?.Висновки до розд?луУ розд?л? було описано метод Монте-Карло, який буде використовуватися для системи балансування гри в залежност? в?д тип?в та правил гри. Данi цього роздiлу лягли в основу системи та детальнiше описанi в наступному роздiлi.РОЗДIЛ 3 ОПИС АРХIТЕКТУРИ БАЛАНСЕРУ ГРИКонстанти - це значення, як? в?дом? заздалег?дь або задаються "з? стел?" (керуючись лог?кою ? здоровим глуздом). Наприклад: ми робимо простий моб?льний Баттлер начебто Blood Brothers. ? хочемо, щоб бо? тривали +-1 хвилину. Це ? буде нашою константою.Вс? ?нш? значення виводяться з констант.Знаючи тривал?сть бою, ми можемо уявити параметри карт-юн?т?в, щоб вони билися р?вно хвилину.Припустимо, вс? атаки займають 5 секунд, юн?ти атакують по черз?, значить, середн? здоров'я повинно бути 60 / (5 * 2) в 6 раз?в б?льше середнього шкоди.В реальност? все трохи складн?ше, але поки зупинимося на цьому. Тут ми повинн? задуматися: а чому не навпаки? Можна ж константою взяти ?ставлення здоров'я до атаки?, а з не? вивести ?тривал?сть бою?.В?дпов?дь проста: ?в?дношення здоров'я? нам неважливо - саме по соб? воно майже не вплива? на геймплей. Зате в моб?льн?й гр? важлива тривал?сть сес?? ? тривал?сть бою. Задавши константу, ми будемо впевнен?, що вона залишиться п?д контролем ? не зм?ниться в розрахунках.По сут?, до цього зводиться вся робота над балансом: одн? значення ми зада?мо, ?нш? з них виводимо.У б?льшост? випадк?в ?х можна пом?няти м?сцями ? це не завадить зробити правильний баланс. Але з часом баланс перетвориться на великий таблицю з купою зв'язк?в, ? в?д правильного вибору залежить, наск?льки складно буде стежити за вс?ма важливими параметрами.Точно так же п?дбираються константи, як? стосуються прогресу ? економ?ц?: спираючись на те, що важливо ? що не можна випадково зламати.Наприклад: за перемогу да?ться золото, ? ? два режими гри - PvP ? Кампан?я. Ми повинн? бути впевнен?, що гравцев? ц?кав? обидва режими, але в PvP гравц? мають 40-60% перемог, а в Кампан?? частка перемог близька до 100%. Щоб PvP не ?гнорувати - нагорода за нього повинна бути + - в 1.5 рази вище.У константи можна додати або в?дсоток перемог для кожного режиму, або множник, або дох?д на час, загальний для вс?х режим?в. Не намагайтеся виписати вс? константи в?дразу - в процес? роботи вони в будь-якому випадку будуть зм?нюватися ? поповнюватися.Поки досить розум?ння. Це просто посл?довн?сть чисел.При розрахунку балансу так? посл?довност? складають левову частку роботи: п?двищу?ться р?вень, зроста? сила загону, нагорода за перемогу. Все це - р?зн? прогрес??. Побудувавши прогрес??, ми будемо виводити з них все значення гри: параметри юн?т?в, економ?чн? показники, таблиц? досв?ду ? нагород.Очевидний питання: зв?дки брати цифри для прогрес??? Для в?дпов?д? треба зрозум?ти, що вплива? на цифри. В?зьмемо прогрес?ю досв?ду (який необх?дний для отримання нового р?вня): вона визнача?, ск?льки часу витратить гравець на отримання нових р?вн?в.? краще, якщо ми одразу поставимо максимальний р?вень ? час, який потр?бно для проходження гри (або "ви?дання" контенту). А дал?, знаючи, як гравець заробля? досв?д (завжди Х од. За годину або число зроста?), ми можемо скласти першу прогрес?ю. Вона буде приблизною, ?, швидше за все, в подальшому щось змусить нас внести зм?ни. Але поки нам вистачить.В?зьмемо б?льш складний приклад: прогрес?ю найважлив?ших значень. Що в наш?й гр? найважлив?ше? У с?т?б?лдер?: будови ? ?х ефективн?сть. В RPG: параметри прокачування героя ? шмоток. Для нашого Баттлера лог?чно взяти силу карт в?д першого до останнього р?вня. Якщо в ньому - як в будь-якому ?ншому Баттлер? - карти д?ляться по ?типам р?дкост??, то прогрес?я повинна бути у кожного типу р?дкост?.Як перетворити "силу" в реальн? параметри, ми розберемо пот?м. А поки визначимося, на що вплива? сила карт. Наск?льки найсильн?ший юн?т сильн?ше самого слабкого? У сотню раз? О десят?й? У п?втора? В?дпов?д? ми повинн? були д?знатися ран?ше, коли м?ркували про сенс чисел ? тестували прототип.Знаючи це, ми визначимо крайн? значення нашо? прогрес??. Пот?м парканом, наск?льки швидким повинен бути зростання цих значень. Як сильно 8-й р?вень в?др?зня?ться в?д 9-го? А 79-й в?д 80-го?Якщо наша прогрес?я буде експонентою - ми ризику?мо отримати величезний розрив м?ж високор?вневими гравцями (один 79-й валить чотирьох 78-х). Але це не страшно, якщо м?ж ними - тижн? ? м?сяц? плавно? прокачування. Не забувайте прикидати час, яке потр?бно для досягнення цих значень. З ?ншого боку, якщо взяти "пов?льну" прогрес?ю, гравц? не в?дчують проф?т ? пафос нового контенту. Тепер розберемося, як зробити прогрес?ю, щоб в майбутньому нам легше було м?няти ? контролювати числа.Типи прогрес??. Ви напевно чули про р?зн? прогрес??: арифметична, геометрична, ряд Ф?боначч?, метод Монте-Карло. На питання ?яку вибрати?? ? проста ? складна в?дпов?дь. Проста: бер?ть будь-яку. Ви вже визначилися з крайн?ми значеннями ? швидк?стю зростання, решта не принципово. Складна в?дпов?дь: не брати н? одну з перерахованих.Вс? ц? прогрес?? заснован? на операц?? з попередн?м числом: значить, ?х складно висловити у вигляд? формули ? з ними можна працювати т?льки всередин? наших таблиць. Я рекомендую робити так: кожне значення прогрес?? обчислю?ться не з попереднього числа, а з? свого порядкового номера (у гр? це швидше за все р?вень - з ним зручно працювати).Цей р?вень спочатку зводиться до степеня X, пот?м множиться на Y. П?дганяючи X ? Y ми заручимося р?вно тими крайн?ми значеннями ? швидк?стю зростання, як? нам потр?бн?. При необх?дност? формулу легко пом?няти. Легко, гнучко, зрозум?ло. Отже, наша прогрес?я готова. Залишилося к?лька нюанс?в. Базова прогрес?яДеяк? числа зав'язан? один на одного: наприклад, розм?р нагороди може залежати в?д сили ворог?в. Щоб зм?цнити зв'язки ? ц?л?сн?сть балансу, я рекомендую використовувати одну прогрес?ю для вс?х пов'язаних розрахунк?в.Як це вигляда?: спочатку ми робимо прогрес?ю для найважлив?ших значень. А стикаючись з? зв'язаною завданням - наприклад, прогрес??ю доход?в (а вони, як правило, прямо пов'язан? з важливими значеннями) - застосову?мо до кожного значення базово? прогрес?? в?дпов?дний множник. У нас виходить пох?дна прогрес?я, яка залежить в?д базово?.Особливою причини використовувати базову прогрес?ю нема?, можна для кожного завдання робити свою. Але якщо в гр? багато зв'язк?в, базова прогрес?я допоможе знизити плутанину. Якщо в пох?дною повинна бути ?нша швидк?сть росту - зам?сть множника можна зводити значення в ступ?нь.Кругл? значення Остання др?бниця. З деякими значеннями гравець часто стика?ться ? довго ?х спостер?га?: наприклад, досв?д до р?вня. Добре, коли так? значення кругл? ? красив?: 2500 зам?сть 2468, ? т.д. Розрахунок ефективност? - найочевидн?ша частина роботи: бойовий баланс, баланс м?ж фракц?ями, стратег?ями, юнитами ? буд?влями р?зних р?вн?в тощо. Як переконатися, що ось ця карта 23-го р?вня дор?вню? за силою ?нш?й карт? т??? ж ц?нност? того ж р?вня?В ?нших жанрах схож? завдання: ось два будови в с?т?б?лдере з? схожою ц?ною, але р?зною функц??ю - як зробити ?х р?вними по ?корисност??? Просто: зводите всю параметри до одного. Можете назвати його ?ефективн?сть?, ?корисн?сть?, ?сила?, як завгодно. Ран?ше ми вже робили прогрес?ю сили. Тепер розберемося, що це таке. Бойова ефективн?стьPWR = HP * DMG (3.1)Нав?ть якщо в гр? два десятки параметр?в, вс? вони зводяться спочатку до цих двох, а пот?м ? до одного. ?накше кажучи: в?дносна ефективн?сть юн?та = HP [сума збитк?в, яких отрима? юн?т] * DMG [ пошкодження юн?та за одиницю часу ]Розглянемо ?нш? параметри. Наприклад, ? в?дсотковий шанс завдати подв?йного шкоди (CRIT). Тод? DMG = DMG * ??(1 + CRIT%) (3.2)Тобто, додати 50% -й шанс кр?та на мов? балансу те ж саме, що зб?льшити базовий шкоди на 50%. Все просто ? лог?чно. Або, наприклад, ? шанс уникнути атаку ворога (DODGE). Тод? HP = HP / (1 - DODGE%) (3.3)Тобто, 50% -й шанс ухилитися дор?вню? зб?льшенню здоров'я вдв?ч?: лог?чно, тому що уворот в?д половини атак дозволить юниту вдв?ч? довше прожити в бою. Точно так же вважаються ефекти типу PARRY ? ABSORB.Але якщо ефект?в к?лька, то треба дивитися, як вони складаються. Наприклад, уворот разом з поглинанням шкоди - поглинання спрацьову? т?льки тод?, коли не спрацював уворот. Раз вони д?ють по черз?, ?х не можна складати. В такому випадку формула буде виглядати так:HP = HP / (1 - (DODGE% + ABSORB% * (1-DODGE%)) (3.4)Тобто, ABSORB треба зменшувати на ймов?рн?сть Уворот: б?льше уворот - р?дше поглинання. Дал? - по аналог?? - можна розраховувати не т?льки параметри юн?т?в, але також предмет?в, заклинань, буд?вель та ?ншого.Вдалося звести розрахунковий баланс клас?в до 1% в ?грашц? з купою пол?пшень ? предмет?в. Пояснення 1: "ефективн?сть" зм?ню?ться не пропорц?йно множенню параметр?в на сп?льний множник. Наприклад, якщо помножити HP ? DMG юн?та на два, його ефективн?сть зросте б?льш, н?ж удв?ч?.Пояснення 2: якщо "ефективн?сть" одного вдв?ч? сильн?ше ?ншого, значить. у сильного залишиться приблизно половина здоров'я п?сля бою. ? шанс перемогти другого слабкого ворога.Пояснення 3: Але в битв? одночасно з двома слабкими ворогами перемагають дво?, оск?льки вони завдають св?й сумарний шкоди за одиницю часу.Та ж лог?ка працю? для будь-якого ?ншого жанру, т?льки зам?сть HP ? DMG ви визнача?те ?нш? параметри, з яких склада?ться ефективн?сть юн?т?в / предмет?в / буд?вель ? т.п.Для ферми це може бути "користь", под?лена на "швидк?сть", де користь - принесений ресурс, помножений на коеф?ц??нт ц?нност? цього ресурсу, а швидк?сть - час, який потр?бно для виробництва.Параметри з ефективност?. Поверта?мося до нашо? прогрес?? сили. Ми вже роз?бралися, що таке сила ? у нас вже ? прогрес?я. Залишилося т?льки вивести з не? параметри юн?т?в. У цього героя з Dark Souls ма? бути багато HP. Найпрост?ше це робити за допомогою коеф?ц??нт?в до середн?х значень: наприклад, для ?танка? потр?бно буде вказати, що його здоров'я в 1.5 рази вище середнього.Тепер докладно: припустимо, сила (PW) юн?т?в 1-ого р?вня = 100. Тод? середн? значення HP ? DMG = SQRT (100) = 10 (квадратний кор?нь з ефективност?). Однак ран?ше ми вир?шили, що здоров'я ма? бути в 6 раз?в б?льше шкоди.HP = SQRT (100) * SQRT (6) = 24 (3.5)В?дпов?дно, середн? DMG 24/6 = 4 Перев?ря?мо: 24 * 4 = 96 (не р?вно 100, тому що до цього я округлила, але в рамках балансу так? похибки допустим?). Тепер ми хочемо зробити ?танка?. Нам треба помножити середн?й HP на ран?ше обраний множник 24 * 1.5 = 37 , в?дпов?дно DMG = 4 * (1 / 1.5) = 4 * 0.7 = 3 Перев?ря?мо: 37 * 3 = 111 (Все вийшло, хоч ? з похибкою округлення).Все ?нше генеру?ться автоматично, н?чого не треба заповнювати ? перев?ряти, в цьому ? ? чудо автоматизац??.Параметри можна вписувати ? вручну, а формулою т?льки ?перев?ряти?, щоб вписане не сильно в?др?знялося в?д розрахункового.Тепер все значення внесен? вручну, а п?д кожним юн?том ? стовпчик з перев?ркою. У ньому - в?дносна р?зниця м?ж отриманим PW ? розрахунковим, яка п?дсв?чу?ться червоним (conditional formating), якщо перевищу? 10%.Плюси вписування: значення краще виглядають, ?х можна пов'язати з емоц?ями, наприклад ?Пекельна бомба з втратою 666".Ще я люблю використовувати парн? числа для ?товстих? юн?т?в ? непарн? для дамагеров. А еп?чн? юн?ти добре виглядають з круглими числами.М?нуси вписування: б?льше роботи, б?льше см?ття в таблицях ? вище ризик помилки. Автоматичне заповнення з коеф?ц??нтами або ручне з перев?ркою - виб?р за вами. Якщо ваш? юн?ти ? здатност? можуть прокачуватися на десятки р?вн?в, в емоц?йних числах нема? н?якого сенсу, все одно ?х майже не буде пом?тно. Зате, якщо мова про якийсь ун?кальний контент, який не зм?ню?ться ? не ма? сотню стан?в, задумайтеся про ручному заповненн?, з ним красив?ше. Використовуючи ручне заповнення, додайте на головний лист результат вс?х перев?рок, щоб не було потреби п?сля кожно? зм?ни перев?ряти вс? листи. На цьому основи зак?нчуються, а ми можемо спок?йно отримати вс? параметри вс?х юн?т?в. 3.1 (Не) очевидн? параметриХардкорн? частина балансу. Як я вже згадувала: автоматизац?я вносить похибку. Бачачи перед собою т?льки цифри, ми забува?мо про реч?, здавалося б, очевидн?. ?х краще проговорити заздалег?дь ? враховувати при балансуванню.Так, вс? параметри зводяться до HP ? DMG, це чиста математика. Але в баланс? завжди ? здорова частка ?маг??? через неможлив?сть передбачити ? порахувати вс? можлив? под?? ? комб?нац??. ? не скр?зь ? пряме математичне р?шення - ?нод? вам доведеться вносити зм?ни ?на око? ? перев?ряти в прототип?. Ядерний синтез ?люстру? роботу балансер, який спробував математично розрахувати взагал? все залежить в гр?. Найпрост?ший: л?кування.Легко здогадатися, що для ц?лителя DMG = сил? зц?лення. Однак, атакуючий завжди знайде мета, а ц?литель може бути неефективний, коли в?н один на поле або коли вс? здоров?. Плюс в?н не л?ку? вище максимального здоров'я.Тому при пор?внянн? ц?лителя ? дамагера з однаковими параметрами розрахункова ефективн?сть ц?лителя повинна бути нижче. ?нший приклад: лучник атаку? л?таюч? ц?л?, лицар - нема?. Лучник, очевидно, ?ефективн?ше? ? для правильного балансу йому треба закласти коеф?ц??нт до втрат.Але п?дбирати коеф?ц??нт доведеться ?на око?, спираючись на тестування ? деяк? м?ркування. наприклад: К?льк?сть л?тун?в в гр?. Якщо л?тун, припустимо, всього один - к-т повинен бути м?н?мальний. Ефективн?сть самих л?тун?в. Якщо все л?туни св?домо слабк? ? легко виносяться, а ?лучник?в? в гр? багато - к-т так само не повинен бути надто високим. Цей приклад в?дноситься до вс?х параметр?в, який передбача? певний ф?льтр характеристик (у Шрайбера це зветься ?нтранз?т?вним? механ?ками).Наприклад, до ?пробиття брон??, за умови, що броня ? не у вс?х персонаж?в. Або до п?двищеного ?втрат по буд?влях?. Або до ?ст?йкост? проти гобл?н?в?. У деяких випадках ? можлив?сть порахувати коеф?ц??нт математично: помноживши чисту ефективн?сть властивост? на ймов?рн?сть його використання. Наприклад "+100 до втрат проти гобл?н?в" треба вважати як "+100 * ймов?рн?сть вдарити по гобл?ни", ?накше кажучи, "+100 * частку гобл?н?в серед оч?куваних ворог?в".?нший приклад: атака на в?дстан?. У гр? з перем?щенням ?л?поз?ц?он?рован?ем перемага? той, хто почав атакувати ран?ше; в?дпов?дно, йому потр?бен коеф?ц??нт до втрат. Вам може здатися, що у цього завдання ? математичне р?шення: ми можемо порахувати середню к?льк?сть влучень до прямого з?ткнення, спираючись на середню швидк?сть ворог?в. ? в цьому нав?ть ? сенс. Але не можна забувати:По-1-ше, далеко не завжди з?ткнення буде починатися з максимального рад?усу атака. В ?грах типу Clash Royal можна скидати юн?т?в з ближньо? атакою прямо на юн?т?в з далеко? - тод? весь ефект далекого бою зводиться до нуля. У кожн?й гр? сво? обмеження - вважаючи по максимуму, ми, швидше за все, завищивши ефективн?сть.По-2-ге, ми не врахову?мо тактику комб?нування ?жирних? юн?т?в спереду ? далекоб?йних ззаду. Залежно в?д гри ця тактика може бути виг?дна по-р?зному, в?д ?взагал? не ма? сенсу? (к-т м?н?мальний), до ?т?льки так ? треба грати? (к-т максимальний). Визначтеся, що потр?бно для геймплея, ? п?дкр?пите цей вар?ант коеф?ц??нтом.Цей же приклад можна в?днести до вс?х питань позиц?онування, включаючи, наприклад, прегражден?е шляху, упов?льнення, ?нш? форми crowd-control'a.? в кожному випадку ? лог?чне, але не повне математичне р?шення: наприклад, для мага з ?заморозки? можна порахувати середн? число слабости ц?лей, помножити на середню атаку ? на його силу упов?льнення - вийде обгрунтоване число ?шкоди, який ц?л? не змогли нанести з -за ефекту упов?льнення ?, ? це число см?ливо можна плюсовать кDMG мага.Але - в залежност? в?д механ?к ? тактик гри - реальна ефективн?сть може сильно в?др?знятися в?д наших розрахунк?в. Так що без тестування ? правок ?на око? не об?йтися.3.2 Ефективн?сть групиЦе питання вже згадувався: якщо в гр? ? битви з р?зною к?льк?стю юн?т?в або юн?ти типу ?заг?н з N персонаж?в? - ми повинн? знати, як порахувати ?х ефективн?сть з урахуванням к?лькост?.Просто помножити ?силу? на к?льк?сть недостатньо - наше число буде в?дображати ?силу? загону, в якому одночасно бореться т?льки один юн?т.На к?льк?сть (N) сл?д помножити окремо HP, окремо DMG:PW (N) = (HP * N) * (DMG * ??N) (3.6)?накше це можна записати HP * DMG * ??N?, що зда?ться нав?ть лог?чн?ше - але ми так робити не будемо, ? ось чому: цей запис в?добража? ефективн?сть загону, який ма? загальне здоров'я ? пост?йний шкоди, не зм?нний в?д загибел? член?в загону.У реальност? таке зустр?ча?ться р?дко, тому DMG треба знизити на коеф?ц??нт, що в?добража? смертн?сть. А це вже залежить в?д конкретних механ?к гри: наприклад, в?д поширеност? AoE атак, в?д можливост? загону атакувати на в?дстан? ? т.д.В?зьмемо навскидку коеф?ц??нт 0.7, ? тод? формула вигляда? так:PW (N) при N> 1 = (HP * N) * (DMG * ??0.7 * N) (3.7)Але якщо ви хочете використовувати одну формулу ? для загон?в ? для одиночних геро?в, то ?? треба переписати:PW (N) = (HP * N) * (DMG + DMG * ??0.7 * (N-1)) (3.8)3.3 Синерг?яОчевидно, що з розумом з?брана колода сильн?ше, н?ж сумарна сила карт, з яких вона склада?ться. ? справа не т?льки в ефект? групи: сенс декб?лд?нга (п?дбору колоди) в хорошому вза?модоповнення. Наприклад, потужн?, але вразлив? карти можна по?днувати з "захисниками", як? приймають на себе шкоди. Теоретично синерг?ю можна порахувати в баланс? - але нав?що?Припустимо, ми з'ясу?мо, що в гр? ? ряд виг?дних комб?нац?й. Ми можемо скоротити ?х користь, але гравець втратить мотивац?ю шукати вза?модоповнююч? карти, але ж це при?мний ?гровий момент.Проблема наста? тод?, коли вигода невеликого числа комб?нац?й наст?льки явна, що значна частина гравц?в користу?ться однаковими колодами. Це зменшу? р?зноман?тн?сть ? знижу? фан в?д знах?дки хорошого по?днання.Але явна - не математична категор?я. До того ж повед?нка гравц?в часто не пов'язане з реальним балансом. Наприклад, вони нер?дко вважають якусь комб?нац?ю або стратег?ю "?мбой" - в?д imbalanced, незбалансовано? - т?льки тому, що нею користу?ться популярний к?берспортсмен.У п?дсумку - синерг?ю, яку не можна передбачити заздалег?дь, керуючись т?льки здоровим глуздом, не ма? сенсу ? балансувати. Проблеми краще вир?шувати тод?, коли вони виникнуть у гр?: для цього буде потр?бно добре налаштувати анал?тику ? виправляти проблеми ран?ше, н?ж гравц? встигнуть затаврувати баланс.Це абсолютно окрема механ?ка, в яку можна було б ? не заглиблюватися, якби не ?? поширен?сть ? часта необх?дн?сть. Почну з проблеми: припустимо, ми робимо класичний World of Warcraft ? хочемо, щоб лицар-захисник в нормально? брон? поглинав 40% утрати. Це правильна лог?ка: вона закр?плю? за класом певну роль протягом вс??? гри, що набагато краще, н?ж якби на початку було 10%, а в к?нц? - п?д 80%. Танк клас з Терри. Важка броня символ?зу? збереження ? над?йний захист героя. Принаймн? ?нтимних зон.Але ось проблема: вс? параметри в MMO повинн? рости. Нав?що нам ходити в рейди ? валити бос?в, якщо перша броня да? 40% ? остання - теж 40%? А якщо давати б?льше - ? ризик перевищити 100%. У проблеми ? р?шення: нехай броня 5-го р?вня да? 40% захисту т?льки проти ворог?в 5-го р?вня.А проти ворог?в 6-го р?вня та ж броня дасть, скаж?мо, 36%. Проти 7-го всього 32% - ? так дал?. Так ми збережемо роль клас?в ? забезпечимо потребу в пост?йному зростанн?. Техн?чно р?шення звучить так: процентний параметр робиться залежним в?д ?ншого абсолютного параметра (рейтингу) ? н?кого модиф?катора (наприклад, р?вня атакуючого ворога). Модиф?катором може бути ? р?вень самого героя ? будь-який ?нший параметр, наприклад, ?пробиття брон?? у атакуючого.Недол?к у такого методу р?вно один: все це доведеться пояснювати гравцев?. ? зам?сть простих ? зручних в?дсотк?в показувати, на додачу, незрозум?лий ?рейтинг брон??. На щастя, той же World of WarCraft вже виховав покол?ння звичних до цього гравц?в. Розгляда?мо на тому ж приклад?: 40% захисту проти ворога того ж р?вня. Спочатку нам потр?бна прогрес?я нормальних значень брон? для цього класу. Тобто: ск?льки ?рейтингу брон?? (ARMOR) ма? бути у гравця на кожному р?вн?, щоб його поглинання (ARMOR%) було = 40%.Згодом з ц??? ж прогрес?? ми отрима?мо параметри вс?х шмоток, доступних цього класу, оск?льки зна?мо, чому повинна дор?внювати сума ?х брон?.Формула, яка перетворить рейтинг в в?дсоток, вигляда? просто:ARMOR% = ARMOR / (ARMOR + PENETRATION) (3.9)Легко здогадатися, що за рахунок д?лення числа на його суму з ?ншим позитивним числом ми н?коли не отрима?мо> 100%У найпрост?шому сценар?? - це значення з т??? ж прогрес??, взяте за р?внем ворога.Тод? проти р?вного ворога ми будемо мати:ARMOR / (ARMOR + PENETRATION) = 50% поглинання. (3.10)Нам, однак, потр?бно 40%. Для цього ми повинн? зробити ще одну прогрес?ю: пенетрации. ? значення в н?й повин? бути в 1.5 рази вище, н?ж в попередн?й прогрес??. Таким чином: у нас 10-й р?вень, для якого потр?бно, припустимо, 300 брон?. Нас б'? ворог 10-го ж р?вня, з пенетрац??ю 300 * 1.5 = 450. Раху?мо: 300 / (300 + 450) = 40%Тепер, п?дбираючи модиф?катори, ми можемо розписати оч?куван? значення брон? для вс?х клас?в. Якщо нам не подоба?ться, як пада? або п?двищу?ться% в?д р?зниц? в р?внях, ми можемо додати залежн?сть другого доданка в?д ц??? р?зниц?. ? останн?: в наш?й ММОRPG отриманий шкоди буде розраховуватися на сервер? за т??ю формулою, з яко? зроблен? прогрес?? брон? ? пенетрац??. Якщо для прогрес?? ви використовували Ф?боначч? - вас, швидше за все, засунуть в блендер ? порвуть на сотню маленьких Геймдизайнер.Висновки до розд?луОтже ми розглянули побудову балансу гри, яка лягла в основу програмного продукту мо?? роботи рисунок 3.1. В розд?л? повноц?нно описано вс? етапи побудови балансу, в теоретичн?й частин?, для повноти обрахунк?в та впровадженн? в умовах сучасних реал?й ринку необх?дно розширити к?льк?сть геро?в та детальн?ше пропрацювати механ?ки та загальн? умови р?вн?в при в?дпов?дних складностях, що вже ? впровадженим в програмному продукт?. Рисунок 3.1 – Iнтерфейс продуктуРОЗД?Л 4 РОЗРОБЛЕННЯ СТАРТАП-ПРОЕКТУУ даному розд?л? буде розглянуто ключов? особливост? розроблено? системи як стартап-проекту. Проект розглядатиметься як система для створення балансу в асиметричних ?грах.4.1 Опис ?де? проектуСпочатку проанал?зу?мо та подамо у вигляд? таблиц? зм?ст ?де? стартап-проекту, можлив? напрямки застосування та основн? вигоди, як? може отримати користувач товару. Ц? характеристики стартап-проекту зображено в таблиц? 4.1.Таблиця 4.1 - Опис ?де? стартап-проектуЗм?ст ?де?Напрямки застосуванняВигоди для користувачаПрограмна онлайн-платформа для створення балансу в асиметричних ?грах.1. Застосування для оц?нки якост? створеного балансу для асиметрично? гри Можлив?сть швидко отримати зв?т для оц?нки створеного користувачем балансу в асиметричн?й гр?2. Застосування для формування ?нтерактивно? таблиц?-зв?ту для вибрано? асиметрично? гри. Можлив?сть ?нтерактивно налаштувати баланс асиметрично? гри без необх?дност? додаткових ресурс?в.Тепер зробимо анал?з потенц?йних техн?ко-економ?чних переваг ?де? пор?вняно ?з пропозиц?ями конкурент?в. Результати анал?зу зображено в таблиц? 4.2.Таблиця 4.2 – Визначення сильних, слабких та нейтральних характеристик ?де? проекту№ п/пТехн?ко-економ?чн? характери-тики ?де?Товари/концепц?? конкурент?вW (слабка сторона)N (нейтральна сторона)S (сильна сторона)М?й проектКонку-рент 1Конку-рент 21.Ц?на2500$/ р?к5000$/ р?к7000$/ р?к+2.Прибутки32000$/ р?к40000$/ р?к41000$/ р?к+3.Контроль якост?Геймдизайнери, тестувальникиАнал?-тики, прог-рам?сти та деяк? кл??нтиПрог-рам?сти, кл??нти+4.Динам?ка галуз?Швид-каПов?-льнаШвид-ка+5.Пост?йн? витрати10000$/ р?к34000$/ р?к39500$/ р?к+6.Зм?нн? витрати5000$ -10000$/ р?к10000$ -30000$/ р?к20000$ -50000$/ р?к+7.Патенти на продуктиНема?Патент на кож-ний проектДек?-лька патен-т?в на винах?д+Продовження таблиц? 4.2№ п/пТехн?ко-економ?чн? характери-тики ?де?Товари/концепц?? конкурент?вW (слабка сторона)N (нейтральна сторона)S (сильна сторона)М?й проектКонку-рент 1Конку-рент 28.Гнучк? ц?ниЦ?на ?динаЦ?на вар?ю-?ться з року в р?кЦ?на ?дина+9.Законо-давч? обмеженняНема?Нема?Обме-ження на к?ль-к?сть розро-бник?в+4.2 Технолог?чний аудит ?де? проектуВизначимо технолог?чну зд?йсненн?сть ?де? проекту за допомогою анал?зу таких складових, як технолог??, за якою буде виготовлено товар зг?дно ?де? проекту, ?снування таких технолог?й, чи ?х необх?дно розробити / доробити, доступн?сть таких технолог?й авторам проекту. Результати даного анал?зу зображено в таблиц? 4.3.Таблиця 4.3 – Технолог?чна зд?йсненн?сть ?де? проекту?дея проектуТехнолог?? ?? реал?зац??Наявн?сть технолог?йДоступн?сть технолог?йПрограмна онлайн-платформа для створення балансу в асиметричних ?грах.Технолог?я проектування та розробки нейронних мереж Scikit-learn.ТакТехнолог?я доступна, однак, ?й функц?онал менший за в?дпов?дний у альтернативних технолог?й.Технолог?я проектування та розробки нейронних мереж tensorflow (без застосування додаткових модул?в).ТакДан? технолог?? доступн?, однак, штатного функц?оналу все ще не вистача? для вир?шення поставлених задач.Технолог?я проектування та розробки нейронних мереж tensorflow (?з застосуванням Keras).ТакДан? технолог?? доступн?.Обрана технолог?я реал?зац?? ?де? проекту: технолог?я проектування та розробки нейронних мереж tensorflow (?з застосуванням Keras).4.3 Анал?з ринкових можливостей запуску стартап-проектуПроведемо анал?з попиту: наявн?сть попиту, обсяг, динам?ка розвитку ринку. Результати даного анал?зу зображено в таблиц? 4.4. Таблиця 4.4 – Попередня характеристика потенц?йного ринку стартап-проекту№ п/пПоказники стану ринку (найменування)Характеристика1К?льк?сть головних гравц?в, од32Загальний обсяг продаж, грн/ум.од400?0003Динам?ка ринку (як?сна оц?нка)Зроста?4Наявн?сть обмежень для входу (вказати характер обмежень)Висока ?нтерактивн?сть та швидка реакц?я5Специф?чн? вимоги до стандартизац?? та сертиф?кац??Нема?6Середня норма рентабельност? в галуз? (або по ринку), %167Таким чином, за попередн?м оц?нюванням, ринок ? привабливим для входження. Надал? визначимо потенц?йн? групи кл??нт?в, ?х характеристики, та сформу?мо ор??нтовний перел?к вимог до товару для кожно? групи. Ц? дан? зображено в таблиц? 4.5.Таблиця 4.5 – Характеристика потенц?йних кл??нт?в стартап-проекту№ п/пПотреба, що форму? ринокЦ?льова аудитор?я (ц?льов? сегменти ринку)В?дм?нност? у повед?нц? р?зних потенц?йних ц?льових груп кл??нт?вВимоги споживач?в до товару1Зниження витрат на балансування з високим показником користувацького досв?дуМалий, середн?й та великий б?знесиМасштаби гри пропорц?йно зб?льшують розм?ри ресурс?в для вирахування балансуВисокий показник ?нтеграц?? ?з ?снуючою системою, низький пор?г входження для роботи ?з системою2Можлив?сть використовувати систему незалежно в?д типу та масштабу гриМалий, середн?й та великий б?знесиНема?Компан?я передбача? розробку та п?дтримку б?льше одн??? гриП?сля визначення потенц?йних груп кл??нт?в проведемо анал?з ринкового середовища: складемо таблиц? фактор?в, що сприяють ринковому впровадженню проекту (таблиця 4.6), та фактор?в, що йому перешкоджають (таблиця 4.7).Таблиця 4.6 – Фактори загроз№ п/пФакторЗм?ст загрозиМожлива реакц?я компан??1В?дсутн?сть попитуБ?знес може не оц?нити переваги продукту, або ж у ц?лому в?дмовитися в?д балансу гриАкцентувати увагу на кл??нтах, що вже скористалися продуктом, якщо так? ?, навести ?нфограф?ку результативност? (оч?кувану), запропонувати знижку потенц?йному кл??нту в рамках тендеру.2Специф?чн?сть ?снуючо? екосистеми гриДефекти та особливост? ?снуючо? гри, специф?чн? структурн? елементи та часткова неможлив?сть ?нтеграц?? додаткових абстракц?йРозробка ? випуск додаткових функц?ональних можливостей для п?двищення ефективност?.Таблиця 4.7 – Фактори можливостей№ п/пФакторЗм?ст можливост?Можлива реакц?я компан??1Кобренд?нгПропозиц?я в?д певно? компан??, що спец?ал?зу?ться на продуктах для розробки гриВид?лення частини штату на реал?зац?ю проекту, п?дготовка акц?йних пропозиц?й по переходу на новий продукт ?снуючим кл??нтам. Надал? проведемо анал?з пропозиц??: визначимо загальн? риси конкуренц?? на ринку. Результати даного анал?зу зображен? в таблиц? 4.8.Таблиця 4.8 – Ступеневий анал?з конкуренц?? на ринкуОсобливост? конкурентного середовищаВ чому проявля?ться дана характеристикаВплив на д?яльн?сть п?дпри?мства (можлив? д?? компан??, щоб бути конкурентоспроможною)1. Чиста конкуренц?яГравц? ринку не мають явних переваг один над однимБ?льш виг?дн? умови на тендерах, агресивний маркетинг2. Рег?ональна конкуренц?яГравц? ринку – ?нтернац?ональн? п?дпри?мстваВих?д на т? ринки, як? ще не зайнят? конкурентами3. Внутр?шньогалузева конкуренц?яГравц? ринку знаходяться в одн?й галуз? – розробц? ПЗ4. Товарно-видова конкуренц?яУс? продукти гравц?в ринку мають одне призначенняРозробка найб?льш ?нту?тивного ?нтерфейсу, розробка ун?кальних мовленн?вих пакет?в, оптим?зац?я алгоритм?в (щоб анал?з проходив швидше, н?ж у конкурент?в)5. Конкурентн? переваги нец?нов?Продукти в?др?зняються гнучк?стю, функц?оналом (незначно) ? над?йн?стю.У маркетингу неявно пор?внювати власний продукт з ?ншими, робити виг?дн? ц?нов? пропозиц??6. Марочна конкуренц?яЗначна увага прид?ля?ться бренду, що розробив продуктКобренд?нгП?сля анал?зу конкуренц?? проведемо б?льш детальний анал?з умов конкуренц?? в галуз? програмних продукт?в для проектування двигун?в. Результати даного анал?зу зображено в таблиц? 4.9.Тепер визначимо та об?рунту?мо фактори конкурентоспроможност?, як? зображен? в таблиц? 4.10.Таблиця 4.10 – Об?рунтування фактор?в конкурентоспроможност?№ п/пФактор конкурентоспроможност?Об?рунтування (наведення чинник?в, що роблять фактор для пор?вняння конкурентних проект?в значущим)1?нтеграц?яПродукт може бути використаний абсолютно в любому продукт? за наявност? доступу до мереж? ?нтернет.2Гнучк?стьКожен замовник ма? можлив?сть замовити розширення функц?оналу продукту п?д його конкретн? задач?3?нтерактивн?стьПродукт автоматично реагу? на внесен? зм?ни без потреби в додаткових ресурсах Таблиця 4.9 – Анал?з конкуренц?? в галуз? за М. ПортеромСкладов? анал?зуПрям? конкуренти в галуз?Потенц?йн? конкурентиПостачальни-киКл??нтиТовари-зам?нникиДинам?ка галуз?, продуктова л?н?я, бар’?ри проникнен-няНаявн?сть товарних знак?в, доступ до ресурс?в, патенти на продуктиКонцентрац?я постачальни-к?в, диференц?ац?я витратР?вень чутливо-ст? до зм?ни ц?н, прибутки, контроль якост?Ц?на, лояльн?сть спожива-ч?вВиснов-ки:Конкуренц?я не ? ?нтенсивною, адже даний ринок ще н?ким не зайнятий.Для входу на ринок необх?дно створити товарний знак та написати бета-верс?ю програмного продукту. На даний момент потенц?йних конкурент?в нема?.Постачальники не диктують умови роботи на ринку, бо программному продукту не потр?бно постачання.Кл??нти диктують умови роботи на ринку, бо вони ? ?диним джерелом прибутку компан??.При наявност? товар?в зам?нник?в необх?дно буде зменшува-ти ц?ну програмного продукту чи створю-вати ПЗ для ?нших техн?чних систем.За визначеними факторами конкурентоспроможност? проведемо анал?з сильних та слабких стор?н стартап-проекту. Результати даного анал?зу зображено в таблиц? 4.11.Таблиця 4.11 – Пор?вняльний анал?з сильних та слабких стор?н системи ?MeetSpeech?.№ п/пФактор конкуренто-спроможност?Бали 1-20Рейтинг товар?в-конкурент?в у пор?внянн? з MeetSpeech–3–2–10+1+2+31?нтеграц?я15*2Гнучк?сть18*3Розд?лення ос?б17*Тепер проведемо SWOT-анал?з на основ? вид?лених загроз ? можливостей, та сильних ? слабких стор?н проекту. SWOT-матриця зображено в таблиц? 4.12.Таблиця 4.12 – SWOT-анал?з стартап-проектуСильн? сторони: Висока ?нтеграц?я, можлив?сть багатоц?льового використанняСлабк? сторони: ?нтеграц?я обмежена необх?дн?стю наявност? доступу до мереж? ?нтернет та серверного обладнання.Можливост?: Кобренд?нгЗагрози: Неточн?сть балансування, в?дсутн?сть попитуНа основ? SWOT-анал?зу розробимо альтернативи ринково? повед?нки для виведення стартап-проекту на ринок та ор??нтований оптимальний час ?х ринково? реал?зац?? з огляду на потенц?йн? проекти конкурент?в, що можуть бути виведен? на ринок. Дан? альтернативи зображено в таблиц? 4.13.Таблиця 4.13 – Альтернативи ринкового впровадження стартап-проекту№ п/пАльтернатива (ор??нтовний комплекс заход?в) ринково? повед?нкиЙмов?рн?сть отримання ресурс?вСтроки реал?зац??1Реал?зац?я можливост? використання системи для вс?х тип?в ?грСередня18 м?сяц?в2Створення багатокомпонентного вар?анту системи для великих компан?й-розробник?в ?грВисока24 м?сяц?3Розробка MVPВисока12 м?сяц?вСеред даних альтернатив було обрано третю альтернативу, адже строки ?? реал?зац?? найменш? та ? ймов?рн?сть отримання ресурс?в.4.4 Розроблення ринково? стратег?? проектуДля розроблення ринково? стратег?? першим кроком необх?дно описати ц?льов? груп потенц?йних споживач?в, як? можна побачити в таблиц? 4.14.Таблиця 4.14 – Виб?р ц?льових груп потенц?йних споживач?в№ п/пОпис проф?лю ц?льово? групи потенц?йних кл??нт?вГотовн?сть споживач?в сприйняти продуктОр??нтов-ний попит в межах ц?льово? групи (сегменту)?нтенсив-н?сть конкуренц?? в сегмент?Простота входу у сегмент1.Малий б?знесСередня5-10 п?дпри-?мств в р?кСередняСередня2.Середн?й б?знесГотов?5-10 п?дпри- ?мств в р?кСлабкаСередня3.Великий б?знесГотов?3-5 заклад?в в р?кСлабкаСкладнаБуло обрано ц?льову групу п?дпри?мств групи середнього б?знеса.Для роботи в обраних сегментах ринку необх?дно сформувати базову стратег?ю розвитку, яку зображено в таблиц? 4.15.Таблиця 4.15 – Визначення базово? стратег?? розвиткуСтратег?я охоплення ринкуКлючов? конкурентоспроможн? позиц?? в?дпов?дно до обрано? альтернативиБазова стратег?я розвиткуКонцентрац?я на потребах одного ц?льового сегменту – нарадах.Створений продукт ? ун?кальним ? не ма? аналог?в.Стратег?я спец?ал?зац??.Наступним кроком ? виб?р стратег?? конкурентно? повед?нки, яку зображено в таблиц? 4.16.Таблиця 4.16 – Визначення базово? стратег?? конкурентно? повед?нкиЧи ? проект ?першопрох?д-цем? на ринку?Чи буде компан?я шукати нових споживач?в, або забирати ?снуючих у конкурент?в?Чи буде компан?я коп?ювати основн? характеристики товару конкурента, ? як??Стратег?я конкурентно? повед?нкиТак.Компан?я буде шукати нових споживач?в, але ? буде намагатися забирати ?снуючих у конкурент?в.Компан?я не буде коп?ювати характеристики конкурент?в.Стратег?я заняття конкурентно? н?ш?.Тепер розробимо стратег?я позиц?онування, що поляга? у формуванн? ринково? позиц?? (комплексу асоц?ац?й), за яким споживач? мають ?дентиф?кувати торг?вельну марку/проект. ?? зображено в таблиц? 4.17.Таблиця 4.17 – Визначення стратег?? позиц?онуванняВимоги до товару ц?льово? аудитор??Базова стратег?я розвиткуКлючов? конкурентоспро-можн? позиц?? власного стартап-проектуВиб?р асоц?ац?й, як? мають сформувати комплексну позиц?ю власного проекту (три ключових)Обробка критер??в ?гри мають бути повними.Проведен-ня крупних оновлень (оптим?-зац?я розрахун-к?в), створення додатков-ого функц?она-лу.Товар ? ?першопрох?д-цем? на ринку та проект не буде коп??ю ?нших програм.Перша в кра?н? програма для автоматичного балансування асиметрично? гри4.5 Розроблення маркетингово? програми стартап-проектуСформу?мо маркетингову концепц?ю товару, який отриму? споживач. В таблиц? 4.18 зображено результати попереднього анал?зу конкурентоспроможност? товару. Таблиця 4.18 – Визначення ключових переваг концепц?? потенц?йного товару№ п/пПотребаВигода, яку пропону? товарКлючов? переваги перед конкурентами (?снуюч? або так?, що потр?бно створити)1.Точне балансування гри. Гнучка система балансування без необх?дност? сутт?вих ресурс?в.Великий показник масштабування, низький пор?г входження, ?нтерактивн?сть.Надал? розробимо трир?вневу маркетингову модель товару: уточнимо ?дею продукту, його ф?зичн? складов?, особливост? процесу його надання. Дана модель зображена в таблиц? 4.19.Таблиця 4.19 – Опис трьох р?вн?в модел? товаруР?вн? товаруСутн?сть та складов??. Товар за задумомПрограмний продукт для розрахунк?в балансу гри. Продукт для допомоги геймдизайнер?в: початк?вц?в та вже досв?дчених спец?ал?ст?в, як? просто хочуть в?дбалансувати вже готову гру.??. Товар у реальному виконанн?Властивост? / характеристики:1. Можлив?сть задавати власн? техн?чн? характеристики гри.2. Можлив?сть вибору критер?ю оптимальност? та складност? серед запропонованих.3. Збер?гання отриманих результат?в для впровадження на реальному продукт?.Як?сть: програмний продукт пройшов вс? етап? тестування та готовий до використання.Файл spreadsheets, в?ртуальне середовище.Марка: назва орган?зац??-розробника ?Wargaming?, назва товару ?MultyBattle?.Продовження таблиц? 4.19Р?вн? товаруСутн?сть та складов????. Товар ?з п?дкр?пленнямСпец?ал?ст ?з впровадження встановлю? налаштування з файлу.В?дд?л тестування перев?ря? та форму? ф?дбек для кал?брування в майбутньому .Захист програмного продукту буде орган?зовано за допомогою GDPR.Тепер визначимо ц?нов? меж?, якими необх?дно керуватись при встановленн? ц?ни на потенц?йний товар, яке передбача? анал?з ц?ни на товари-аналоги або товари субститути, а також анал?з р?вня доход?в ц?льово? групи споживач?в. Анал?з проводився експертним методом ? його результати зображено в таблиц? 4.20.Таблиця 4.20 – Визначення меж встановлення ц?нР?вень ц?н на товари-зам?нникиР?вень ц?н на товари-аналогиР?вень доход?в ц?льово? групи споживач?вВерхня та нижня меж? встановлення ц?ни на товар/послугу30000-50000 $/р?к50000-60000 $/р?к3000000-5000000 $/р?кНижня межа – 40000 $/р?к, верхня межа - 50000 $/р?кНадал? визначимо оптимальну систему збуту, в межах якого прийма?ться р?шення. Дану систему зображено в таблиц? 4.21. Таблиця 4.21 – Формування системи збутуСпециф?ка закуп?вельно? повед?нки ц?льових кл??нт?вФункц?? збуту, як? ма? виконувати постачальник товаруГлибина каналу збутуОптимальна система збутуКл??нт виплачу? грош? на р?к, тод? до нього приходить на пошту посилання на продукт, яким можна вже користуватисяВ?дпов?дати на запити про додатков? впровадження або доопрацювання над продуктом.Один посередник – спец?ал?ст по пошуку кл??нт?в.Канал збуту одного р?вня.Тепер розробимо концепц?ю маркетингових комун?кац?й, що спира?ться на попередньо обрану основу для позиц?онування, визначену специф?ку повед?нки кл??нт?в. Дану концепц?ю зображено в таблиц? 4.22. Таблиця 4.22 – Концепц?я маркетингових комун?кац?йСпециф?ка повед?нки ц?льових кл??нт?вКанали комун?кац?й, якими користуються ц?льов? кл??нтиКлючов? позиц??, обран? для позиц?онува-нняЗавдання рекламного пов?домленняКонцепц?я рекламного зверненняКл??нт намага?ться знайти нов? методи покращення створюваних ним продукт?в.E-mail, мережа ?нтернет, соц?альн? мереж?.Ун?кальн?сть ПЗ, можлив?сть вибору власних критер??в оптимальност? гри.Продемонструва-ти ун?кальн?сть даного ПЗ та показати можливу економ?ю щодо створення асиметрично? гри при його використанн?.Показати можлив?сть не за велику ц?ну зб?льшити св?й прибуток за допомогою покращення гри.Висновки до розд?луВ даному розд?л? було повн?стю виконано перший етап розроблення стартап-проекту, а саме, виконано маркетинговий анал?з стартап-проекту. За допомогою нього можна сказати, що ?сну? можлив?сть ринково? комерц?ал?зац?? проекту, адже на ринку програм для п?дпри?мств з машинобудування наявний попит на програмн? продукти, здатн? оптимально проектувати ?гри, до того ж рентабельн?сть роботи ? досить високою.З огляду на потенц?йну групу кл??нт?в, а саме, ?нд?-розробники сфери геймдеву, та в?дсутност? конкуренц?? ? велик? перспективи впровадження даного програмного забезпечення. Для ринково? реал?зац?? проекту доц?льно обрати таку альтернативу впровадження: створення MVP та впровадження його в невелику к?льк?сть компан?й геймдеву.ВИСНОВКИ ПО РОБОТ?П?д час роботи було проведено досл?дження сучасних метод?в балансування ?гор. Було проведено анал?з сучасних засоб?в розробки механ?к та складност? у задач? автоматичного балансування гри.У якост? контейнера результат?в було обрано spreadsheets через його поширен?сть ? в?дсутн?сть л?ценз?йних збор?в. Серед метод?в обробки даних як л?м?тованостей в гр? було обрано стандартн? формули розширення, так як в?н да? кращ? результати в?дносно фур’?-анал?зу.У якост? засобу ?нтелектуального анал?зу звуку було обрано метод Монте-Карло, так як в?н забезпечу? р?зноман?ття та ма? просту реал?зац?ю для ун?версального використання. Отриман? знання та досв?д значно просунули роботу над маг?стерською дисертац??ю ? вивели досл?дження на етап активно? розробки системи. А також допомогли п?дготуватися до реального п?лотного запуску власно? гри з можлив?стю налаштувати баланс завдяки власн?й систем?.ПЕРЕЛ?К ПОСИЛАНЬRaph Koster, A Theory of Fun for Game Design. USA: O'Reilly Media; 2013, 815p.Iнструментарiй геймдизайнера – URL: (дата звернення: 12.10.2019)Lessons on game design – URL: (дата звернення: 12.10.2019)A List of Game Mechanics and a Random Mechanic Mixer – URL: (дата звернення: 12.10.2019)Board game mechanics patterns – URL: (дата звернення: 12.10.2019)Корисностi для Google spreadsheets – URL: (дата звернення: 12.10.2019)Stratonovich, R.L. Conditional Markov Processes. Theory of Probability and its Applications . 1960. Vol. 5, No. 2. pp. 156–178. LeNet-5, convolutional neural networks – URL: (дата звернення: 12.10.2019)Shift-invariant pattern recognition neural network and its optical architecture – URL: (дата звернення: 12.10.2019)Parallel distributed processing model with local space-invariant interconnections and its optical architecture – URL: (дата звернення: 12.10.2019)Subject independent facial expression recognition with robust face detection using a convolutional neural network – URL: (дата звернення: 12.10.2019)Deep content-based music recommendation – URL: (дата звернення: 12.10.2019)Convolutional Neural Networks (LeNet) – DeepLearning 0.1 documentation – URL: (дата звернення: 12.10.2019)Guide to convolutional neural networks?: a practical application to traffic-sign detection and classification – URL: (дата звернення: 12.10.2019)Flexible, High Performance Convolutional Neural Networks for Image Classification – URL: (дата звернення: 12.10.2019)ImageNet Classification with Deep Convolutional Neural Networks – URL: (дата звернення: 12.10.2019)Multi-column deep neural networks for image classification – URL: (дата звернення: 12.10.2019)LSTM: A Search Space Odyssey – URL: (дата звернення: 12.10.2019)The Large Text Compression Benchmark – URL: (дата звернення: 12.10.2019)A Novel Connectionist System for Improved Unconstrained Handwriting Recognition – URL: (дата звернення: 12.10.2019)Speech Recognition with Deep Recurrent Neural Networks.?Acoustics, Speech and Signal Processing (ICASSP) – URL: (дата звернення: 12.10.2019)ДОДАТОК А. ЛIСТИНГ ФАЙЛIВФайл charmap.py:"""Defines two dictionaries for converting between text and integer sequences."""char_map_str = """' 0<ПРОБЕЛ> 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"""# the "blank" character is mapped to 28char_map = {}index_map = {}for line in char_map_str.strip().split('\n'): ch, index = line.split() char_map[ch] = int(index) index_map[int(index)+1] = chindex_map[2] = ' 'Файл create_desc_json.py:"""Use this script to create JSON-Line description files that can be used totrain deep-speech models through this library.This works with data directories that are organized like LibriSpeech:data_directory/group/speaker/[file_id1.wav, file_id2.wav, ..., speaker.trans.txt]Where speaker.trans.txt has in each line, file_id transcription"""from __future__ import absolute_import, division, print_functionimport argparseimport jsonimport osimport waveimport reimport pandas as pddef main(data_directory, output_file_train, output_file_test, test_pcn=.1): labels = [] durations = [] keys = [] for speaker in os.listdir(data_directory): speaker_path = os.path.join(data_directory, speaker) labels_file = os.path.join(speaker_path, 'etc', 'prompts-original') with open(labels_file, 'rb') as labels_f: lines = labels_f.read().decode('utf8') for line in lines.split('\n'): split = line.strip().split() if len(split) < 2: continue file_id = split[0] label = re.sub(r'[,.;?!:+]', '', ' '.join(split[1:]).lower()).replace(' - ', ' ').replace('-', ' ') label = label.replace('a', 'а').replace('e', 'е').replace('i', 'и').replace('m', 'м') label = label.replace('18', 'восемнадцать').replace('1662', 'тысяча шестьсот шестьдесят второй') label = label.replace('12', 'двенадцать').replace('2х', 'двух').replace('2 х', 'двух').replace('23', 'двадцать три') label = label.replace('326 го', 'триста двадцать шестого').replace('23', 'двадцать три') def remove_doubles(word): res = '' for c in word: if res == '': res += c continue if res[-1] != c: res += c else: res += "'" + c return res new_label = [] for word in label.split(' '): new_label.append(remove_doubles(word)) label = ' '.join(new_label) if len(label) > 150: continue audio_file = os.path.join(speaker_path, 'wav', file_id) + '.wav' audio = wave.open(audio_file) duration = float(audio.getnframes()) / audio.getframerate() audio.close() keys.append(audio_file) durations.append(duration) labels.append(label) test_size = int(test_pcn * len(keys)) dataset = pd.DataFrame( [{'key': key, 'duration': duration, 'text': label} for key, duration, label in zip(durations, keys, labels)]) test_ix = dataset.sample(n=test_size).index.values del dataset with open(output_file_train, 'wb') as out_file: for i in range(len(keys)): if i not in test_ix: line = json.dumps({ 'key': keys[i], 'duration': durations[i], 'text': labels[i], }, ensure_ascii=False) out_file.write((line + '\n').encode('utf8')) with open(output_file_test, 'wb') as out_file: for i in test_ix: line = json.dumps({ 'key': keys[i], 'duration': durations[i], 'text': labels[i], }, ensure_ascii=False) out_file.write((line + '\n').encode('utf8'))if __name__ == '__main__': # parser = argparse.ArgumentParser() # parser.add_argument('data_directory', type=str, # help='Path to data directory') # parser.add_argument('output_file', type=str, # help='Path to output file') # args = parser.parse_args() main(os.path.abspath('./Voxforge'), os.path.abspath('./train_corpus.json'), os.path.abspath('./valid_corpus.json'), 0.5)Файл data_generator.py"""Defines a class that is used to featurize audio clips, and providethem to the network for training or testing."""import jsonimport numpy as npimport randomfrom python_speech_features import mfccimport librosaimport scipy.io.wavfile as wavimport matplotlib.pyplot as pltfrom mpl_toolkits.axes_grid1 import make_axes_locatablefrom utils import calc_feat_dim, spectrogram_from_file, text_to_int_sequencefrom utils import conv_output_lengthRNG_SEED = 123class AudioGenerator(): def __init__(self, step=10, window=20, max_freq=8000, mfcc_dim=13, minibatch_size=20, desc_file=None, spectrogram=True, max_duration=10.0, sort_by_duration=False): """ Params: step (int): Step size in milliseconds between windows (for spectrogram ONLY) window (int): FFT window size in milliseconds (for spectrogram ONLY) max_freq (int): Only FFT bins corresponding to frequencies between [0, max_freq] are returned (for spectrogram ONLY) desc_file (str, optional): Path to a JSON-line file that contains labels and paths to the audio files. If this is None, then load metadata right away """ self.feat_dim = calc_feat_dim(window, max_freq) self.mfcc_dim = mfcc_dim self.feats_mean = np.zeros((self.feat_dim,)) self.feats_std = np.ones((self.feat_dim,)) self.rng = random.Random(RNG_SEED) if desc_file is not None: self.load_metadata_from_desc_file(desc_file) self.step = step self.window = window self.max_freq = max_freq self.cur_train_index = 0 self.cur_valid_index = 0 self.cur_test_index = 0 self.max_duration = max_duration self.minibatch_size = minibatch_size self.spectrogram = spectrogram self.sort_by_duration = sort_by_duration def get_batch(self, partition): """ Obtain a batch of train, validation, or test data """ if partition == 'train': audio_paths = self.train_audio_paths cur_index = self.cur_train_index texts = self.train_texts elif partition == 'valid': audio_paths = self.valid_audio_paths cur_index = self.cur_valid_index texts = self.valid_texts elif partition == 'test': audio_paths = self.test_audio_paths cur_index = self.test_valid_index texts = self.test_texts else: raise Exception("Invalid partition. " "Must be train/validation") features = [self.normalize(self.featurize(a)) for a in audio_paths[cur_index:cur_index + self.minibatch_size]] # calculate necessary sizes max_length = max([features[i].shape[0] for i in range(0, self.minibatch_size)]) max_string_length = max([len(texts[cur_index + i]) for i in range(0, self.minibatch_size)]) # initialize the arrays X_data = np.zeros([self.minibatch_size, max_length, self.feat_dim * self.spectrogram + self.mfcc_dim * (not self.spectrogram)]) labels = np.ones([self.minibatch_size, max_string_length]) * 28 input_length = np.zeros([self.minibatch_size, 1]) label_length = np.zeros([self.minibatch_size, 1]) for i in range(0, self.minibatch_size): # calculate X_data & input_length feat = features[i] input_length[i] = feat.shape[0] X_data[i, :feat.shape[0], :] = feat # calculate labels & label_length label = np.array(text_to_int_sequence(texts[cur_index + i])) labels[i, :len(label)] = label label_length[i] = len(label) # return the arrays outputs = {'ctc': np.zeros([self.minibatch_size])} inputs = {'the_input': X_data, 'the_labels': labels, 'input_length': input_length, 'label_length': label_length } return (inputs, outputs) def shuffle_data_by_partition(self, partition): """ Shuffle the training or validation data """ if partition == 'train': self.train_audio_paths, self.train_durations, self.train_texts = shuffle_data( self.train_audio_paths, self.train_durations, self.train_texts) elif partition == 'valid': self.valid_audio_paths, self.valid_durations, self.valid_texts = shuffle_data( self.valid_audio_paths, self.valid_durations, self.valid_texts) else: raise Exception("Invalid partition. " "Must be train/validation") def sort_data_by_duration(self, partition): """ Sort the training or validation sets by (increasing) duration """ if partition == 'train': self.train_audio_paths, self.train_durations, self.train_texts = sort_data( self.train_audio_paths, self.train_durations, self.train_texts) elif partition == 'valid': self.valid_audio_paths, self.valid_durations, self.valid_texts = sort_data( self.valid_audio_paths, self.valid_durations, self.valid_texts) else: raise Exception("Invalid partition. " "Must be train/validation") def next_train(self): """ Obtain a batch of training data """ while True: ret = self.get_batch('train') self.cur_train_index += self.minibatch_size if self.cur_train_index >= len(self.train_texts) - self.minibatch_size: self.cur_train_index = 0 self.shuffle_data_by_partition('train') yield ret def next_valid(self): """ Obtain a batch of validation data """ while True: ret = self.get_batch('valid') self.cur_valid_index += self.minibatch_size #print(ret) if self.cur_valid_index >= len(self.valid_texts) - self.minibatch_size: self.cur_valid_index = 0 self.shuffle_data_by_partition('valid') yield ret def next_test(self): """ Obtain a batch of test data """ while True: ret = self.get_batch('test') self.cur_test_index += self.minibatch_size if self.cur_test_index >= len(self.test_texts) - self.minibatch_size: self.cur_test_index = 0 yield ret def load_train_data(self, desc_file='train_corpus.json'): self.load_metadata_from_desc_file(desc_file, 'train') self.fit_train() if self.sort_by_duration: self.sort_data_by_duration('train') def load_validation_data(self, desc_file='valid_corpus.json'): self.load_metadata_from_desc_file(desc_file, 'validation') if self.sort_by_duration: self.sort_data_by_duration('valid') def load_test_data(self, desc_file='test_corpus.json'): self.load_metadata_from_desc_file(desc_file, 'test') def load_metadata_from_desc_file(self, desc_file, partition): """ Read metadata from a JSON-line file (possibly takes long, depending on the filesize) Params: desc_file (str): Path to a JSON-line file that contains labels and paths to the audio files partition (str): One of 'train', 'validation' or 'test' """ audio_paths, durations, texts = [], [], [] with open(desc_file, 'rb') as json_line_file_b: json_line_file = json_line_file_b.read().decode('utf8') for line_num, json_line in enumerate(json_line_file.split('\n')): if json_line == '': continue try: spec = json.loads(json_line, encoding='utf-8') if float(spec['duration']) > self.max_duration: continue audio_paths.append(spec['key']) durations.append(float(spec['duration'])) texts.append(spec['text']) except Exception as e: # Change to (KeyError, ValueError) or # (KeyError,json.decoder.JSONDecodeError), depending on # json module version print('Error reading line #{}: {}' .format(line_num, json_line)) if partition == 'train': self.train_audio_paths = audio_paths self.train_durations = durations self.train_texts = texts elif partition == 'validation': self.valid_audio_paths = audio_paths self.valid_durations = durations self.valid_texts = texts elif partition == 'test': self.test_audio_paths = audio_paths self.test_durations = durations self.test_texts = texts else: raise Exception("Invalid partition to load metadata. " "Must be train/validation/test") def fit_train(self, k_samples=100): """ Estimate the mean and std of the features from the training set Params: k_samples (int): Use this number of samples for estimation """ k_samples = min(k_samples, len(self.train_audio_paths)) samples = self.rng.sample(self.train_audio_paths, k_samples) feats = [self.featurize(s) for s in samples] feats = np.vstack(feats) self.feats_mean = np.mean(feats, axis=0) self.feats_std = np.std(feats, axis=0) def featurize(self, audio_clip): """ For a given audio clip, calculate the corresponding feature Params: audio_clip (str): Path to the audio clip """ if self.spectrogram: return spectrogram_from_file( audio_clip, step=self.step, window=self.window, max_freq=self.max_freq) else: (rate, sig) = wav.read(audio_clip) return mfcc(sig, rate, numcep=self.mfcc_dim) def normalize(self, feature, eps=1e-14): """ Center a feature using the mean and std Params: feature (numpy.ndarray): Feature to normalize """ return (feature - self.feats_mean) / (self.feats_std + eps)def shuffle_data(audio_paths, durations, texts): """ Shuffle the data (called after making a complete pass through training or validation data during the training process) Params: audio_paths (list): Paths to audio clips durations (list): Durations of utterances for each audio clip texts (list): Sentences uttered in each audio clip """ p = np.random.permutation(len(audio_paths)) audio_paths = [audio_paths[i] for i in p] durations = [durations[i] for i in p] texts = [texts[i] for i in p] return audio_paths, durations, textsdef sort_data(audio_paths, durations, texts): """ Sort the data by duration Params: audio_paths (list): Paths to audio clips durations (list): Durations of utterances for each audio clip texts (list): Sentences uttered in each audio clip """ p = np.argsort(durations).tolist() audio_paths = [audio_paths[i] for i in p] durations = [durations[i] for i in p] texts = [texts[i] for i in p] return audio_paths, durations, textsdef vis_train_features(index=0): """ Visualizing the data point in the training set at the supplied index """ # obtain spectrogram audio_gen = AudioGenerator(spectrogram=True) audio_gen.load_train_data() vis_audio_path = audio_gen.train_audio_paths[index] vis_spectrogram_feature = audio_gen.normalize(audio_gen.featurize(vis_audio_path)) # obtain mfcc audio_gen = AudioGenerator(spectrogram=False) audio_gen.load_train_data() vis_mfcc_feature = audio_gen.normalize(audio_gen.featurize(vis_audio_path)) # obtain text label vis_text = audio_gen.train_texts[index] # obtain raw audio vis_raw_audio, _ = librosa.load(vis_audio_path) # print total number of training examples print('There are %d total training examples.' % len(audio_gen.train_audio_paths)) # return labels for plotting return vis_text, vis_raw_audio, vis_mfcc_feature, vis_spectrogram_feature, vis_audio_pathdef plot_raw_audio(vis_raw_audio): # plot the raw audio signal fig = plt.figure(figsize=(12, 3)) ax = fig.add_subplot(111) steps = len(vis_raw_audio) ax.plot(np.linspace(1, steps, steps), vis_raw_audio) plt.title('Audio Signal') plt.xlabel('Time') plt.ylabel('Amplitude') plt.show()def plot_mfcc_feature(vis_mfcc_feature): # plot the MFCC feature fig = plt.figure(figsize=(12, 5)) ax = fig.add_subplot(111) im = ax.imshow(vis_mfcc_feature, cmap=plt.cm.jet, aspect='auto') plt.title('Normalized MFCC') plt.ylabel('Time') plt.xlabel('MFCC Coefficient') divider = make_axes_locatable(ax) cax = divider.append_axes("right", size="5%", pad=0.05) plt.colorbar(im, cax=cax) ax.set_xticks(np.arange(0, 13, 2), minor=False); plt.show()def plot_spectrogram_feature(vis_spectrogram_feature): # plot the normalized spectrogram fig = plt.figure(figsize=(12, 5)) ax = fig.add_subplot(111) im = ax.imshow(vis_spectrogram_feature, cmap=plt.cm.jet, aspect='auto') plt.title('Normalized Spectrogram') plt.ylabel('Time') plt.xlabel('Frequency') divider = make_axes_locatable(ax) cax = divider.append_axes("right", size="5%", pad=0.05) plt.colorbar(im, cax=cax) plt.show()Файл requirements.txt:h5py==2.7.0ipykernel==4.6.1jupyter==1.0.0keras==2.0.5librosa==0.5.1opencv-python==3.2.0.7python-speech-features==0.5seaborn==0.7.1soundfile==0.9.0.post1Файл train_utils.py:"""Defines a functions for training a NN."""from data_generator import AudioGeneratorimport _pickle as picklefrom keras import backend as Kfrom keras.models import Modelfrom keras.layers import (Input, Lambda, BatchNormalization)from keras.optimizers import SGD, RMSpropfrom keras.callbacks import ModelCheckpointimport osimport tensorflow as tffrom tensorflow.python.ops import math_ops, array_opsdef ctc_lambda_func(args): y_pred, labels, input_length, label_length = args #return K.ctc_batch_cost(labels, y_pred, input_length, label_length) # test label_length = math_ops.to_int32(array_ops.squeeze(label_length, axis=-1)) input_length = math_ops.to_int32(array_ops.squeeze(input_length, axis=-1)) sparse_labels = math_ops.to_int32( K.ctc_label_dense_to_sparse(labels, label_length)) y_pred = math_ops.log(array_ops.transpose(y_pred, perm=[1, 0, 2]) + K.epsilon()) return array_ops.expand_dims( tf.nn.ctc_loss( inputs=y_pred, labels=sparse_labels, sequence_length=input_length, ignore_longer_outputs_than_inputs=True), 1)def add_ctc_loss(input_to_softmax): the_labels = Input(name='the_labels', shape=(None,), dtype='float32') input_lengths = Input(name='input_length', shape=(1,), dtype='int64') label_lengths = Input(name='label_length', shape=(1,), dtype='int64') output_lengths = Lambda(input_to_softmax.output_length)(input_lengths) # output_length = BatchNormalization()(input_lengths) # CTC loss is implemented in a lambda layer loss_out = Lambda(ctc_lambda_func, output_shape=(1,), name='ctc')( [input_to_softmax.output, the_labels, output_lengths, label_lengths]) model = Model( inputs=[input_to_softmax.input, the_labels, input_lengths, label_lengths], outputs=loss_out) return modeldef train_model(input_to_softmax, pickle_path, save_model_path, train_json='train_corpus.json', valid_json='valid_corpus.json', minibatch_size=20, spectrogram=True, mfcc_dim=13, optimizer=SGD(lr=0.02, decay=1e-6, momentum=0.9, nesterov=True, clipnorm=5), epochs=20, verbose=1, sort_by_duration=False, max_duration=10.0): # create a class instance for obtaining batches of data audio_gen = AudioGenerator(minibatch_size=minibatch_size, spectrogram=spectrogram, mfcc_dim=mfcc_dim, max_duration=max_duration, sort_by_duration=sort_by_duration) # add the training data to the generator audio_gen.load_train_data(train_json) audio_gen.load_validation_data(valid_json) # calculate steps_per_epoch num_train_examples = len(audio_gen.train_audio_paths) steps_per_epoch = num_train_examples // minibatch_size # calculate validation_steps num_valid_samples = len(audio_gen.valid_audio_paths) validation_steps = num_valid_samples // minibatch_size # add CTC loss to the NN specified in input_to_softmax model = add_ctc_loss(input_to_softmax) # ctc_loss = tf.reduce_mean(tf.nn.ctc_loss(labels, logits, final_seq_lens)) # CTC loss is implemented elsewhere, so use a dummy lambda function for the loss pile(loss={'ctc': lambda y_true, y_pred: y_pred}, optimizer=optimizer) # make results/ directory, if necessary if not os.path.exists('results'): os.makedirs('results')# # add checkpointer checkpointer = ModelCheckpoint(filepath='results/' + save_model_path, verbose=0) # train the model hist = model.fit_generator(generator=audio_gen.next_train(), steps_per_epoch=steps_per_epoch, epochs=epochs, validation_data=audio_gen.next_valid(), validation_steps=validation_steps, callbacks=[checkpointer], verbose=verbose) # save model loss with open('results/' + pickle_path, 'wb') as f: pickle.dump(hist.history, f)Файл utils.py:"""Defines various functions for processing the data."""import numpy as npimport soundfilefrom numpy.lib.stride_tricks import as_stridedfrom char_map import char_map, index_mapdef calc_feat_dim(window, max_freq): return int(0.001 * window * max_freq) + 1def conv_output_length(input_length, filter_size, border_mode, stride, dilation=1): """ Compute the length of the output sequence after 1D convolution along time. Note that this function is in line with the function used in Convolution1D class from Keras. Params: input_length (int): Length of the input sequence. filter_size (int): Width of the convolution kernel. border_mode (str): Only support `same` or `valid`. stride (int): Stride size used in 1D convolution. dilation (int) """ if input_length is None: return None assert border_mode in {'same', 'valid'} dilated_filter_size = filter_size + (filter_size - 1) * (dilation - 1) if border_mode == 'same': output_length = input_length elif border_mode == 'valid': output_length = input_length - dilated_filter_size + 1 return (output_length + stride - 1) // stridedef spectrogram(samples, fft_length=256, sample_rate=2, hop_length=128): """ Compute the spectrogram for a real signal. The parameters follow the naming convention of matplotlib.mlab.specgram Args: samples (1D array): input audio signal fft_length (int): number of elements in fft window sample_rate (scalar): sample rate hop_length (int): hop length (relative offset between neighboring fft windows). Returns: x (2D array): spectrogram [frequency x time] freq (1D array): frequency of each row in x Note: This is a truncating computation e.g. if fft_length=10, hop_length=5 and the signal has 23 elements, then the last 3 elements will be truncated. """ assert not np.iscomplexobj(samples), "Must not pass in complex numbers" window = np.hanning(fft_length)[:, None] window_norm = np.sum(window**2) # The scaling below follows the convention of # matplotlib.mlab.specgram which is the same as # matlabs specgram. scale = window_norm * sample_rate trunc = (len(samples) - fft_length) % hop_length x = samples[:len(samples) - trunc] # "stride trick" reshape to include overlap nshape = (fft_length, (len(x) - fft_length) // hop_length + 1) nstrides = (x.strides[0], x.strides[0] * hop_length) x = as_strided(x, shape=nshape, strides=nstrides) # window stride sanity check assert np.all(x[:, 1] == samples[hop_length:(hop_length + fft_length)]) # broadcast window, compute fft over columns and square mod x = np.fft.rfft(x * window, axis=0) x = np.absolute(x)**2 # scale, 2.0 for everything except dc and fft_length/2 x[1:-1, :] *= (2.0 / scale) x[(0, -1), :] /= scale freqs = float(sample_rate) / fft_length * np.arange(x.shape[0]) return x, freqsdef spectrogram_from_file(filename, step=10, window=20, max_freq=None, eps=1e-14): """ Calculate the log of linear spectrogram from FFT energy Params: filename (str): Path to the audio file step (int): Step size in milliseconds between windows window (int): FFT window size in milliseconds max_freq (int): Only FFT bins corresponding to frequencies between [0, max_freq] are returned eps (float): Small value to ensure numerical stability (for ln(x)) """ with soundfile.SoundFile(filename) as sound_file: audio = sound_file.read(dtype='float32') sample_rate = sound_file.samplerate if audio.ndim >= 2: audio = np.mean(audio, 1) if max_freq is None: max_freq = sample_rate / 2 if max_freq > sample_rate / 2: raise ValueError("max_freq must not be greater than half of " " sample rate") if step > window: raise ValueError("step size must not be greater than window size") hop_length = int(0.001 * step * sample_rate) fft_length = int(0.001 * window * sample_rate) pxx, freqs = spectrogram( audio, fft_length=fft_length, sample_rate=sample_rate, hop_length=hop_length) ind = np.where(freqs <= max_freq)[0][-1] + 1 return np.transpose(np.log(pxx[:ind, :] + eps))def text_to_int_sequence(text): """ Convert text to an integer sequence """ int_sequence = [] for c in text: if c == ' ': ch = char_map['<ПРОБЕЛ>'] else: ch = char_map[c] int_sequence.append(ch) return int_sequencedef int_sequence_to_text(int_sequence): """ Convert an integer sequence to text """ text = [] for c in int_sequence: ch = index_map[c] text.append(ch) return textФайл vui_notebook.ipynb:{ "cells": [ { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The autoreload extension is already loaded. To reload it, use:\n %reload_ext autoreload\n" ] } ], "source": [ "#####################################################################\n", "# RUN THIS CODE CELL IF YOU ARE RESUMING THE NOTEBOOK AFTER A BREAK #\n", "#####################################################################\n", "\n", "# allocate 50% of GPU memory (if you like, feel free to change this)\n", "from keras.backend.tensorflow_backend import set_session, get_session\n", "import tensorflow as tf\n", "\n", "config = tf.ConfigProto()\n", "#config.gpu_options.per_process_gpu_memory_fraction = 0.95\n", "#config.log_device_placement = True\n", "set_session(tf.Session(config=config))\n", "\n", "# watch for any changes in the sample_models module, and reload it automatically\n", "% load_ext autoreload\n", "% autoreload 2\n", "# import NN architectures fo\n", "# r speech recognition\n", "from sample_models import *\n", "# import function for training acoustic model\n", "from train_utils import train_model\n" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "_________________________________________________________________\nLayer (type) Output Shape Param # \n=================================================================\nthe_input (InputLayer) (None, None, 13) 0 \n_________________________________________________________________\nconv1d (Conv1D) (None, None, 200) 28800 \n_________________________________________________________________\nbn_conv_1d (BatchNormalizati (None, None, 200) 800 \n_________________________________________________________________\nrnn (GRU) (None, None, 200) 240600 \n_________________________________________________________________\nbn_rnn_1d (BatchNormalizatio (None, None, 200) 800 \n_________________________________________________________________\ntime_distributed_2 (TimeDist (None, None, 36) 7236 \n_________________________________________________________________\nsoftmax (Activation) (None, None, 36) 0 \n=================================================================\nTotal params: 278,236\nTrainable params: 277,436\nNon-trainable params: 800\n_________________________________________________________________\nNone\n" ] } ], "source": [ "test = cnn_rnn_model(input_dim=13, filters=200, kernel_size=11, conv_stride=2,\n", " conv_border_mode='valid', units=200, output_dim=36)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1/20\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 82s 5s/step - loss: 406.1687 - val_loss: 301.1680\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 2/20\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 66s 4s/step - loss: 257.5253 - val_loss: 253.3529\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 3/20\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 66s 4s/step - loss: 241.0051 - val_loss: 243.9929\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 4/20\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 66s 4s/step - loss: 235.5289 - val_loss: 239.6616\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 5/20\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 67s 4s/step - loss: 230.9776 - val_loss: 237.4719\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 6/20\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 67s 4s/step - loss: 226.8700 - val_loss: 236.9606\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 7/20\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 67s 4s/step - loss: 222.1577 - val_loss: 249.1466\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 8/20\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 68s 4s/step - loss: 214.3618 - val_loss: 283.3436\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 9/20\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 68s 4s/step - loss: 208.8090 - val_loss: 212.9035\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 10/20\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 68s 4s/step - loss: 202.3790 - val_loss: 203.7667\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 11/20\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 67s 4s/step - loss: 197.6383 - val_loss: 195.2024\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 12/20\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 67s 4s/step - loss: 191.1561 - val_loss: 190.6448\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 13/20\n" ] },{ "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 67s 4s/step - loss: 183.1598 - val_loss: 186.7194\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 14/20\n" ] },{ "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 67s 4s/step - loss: 174.8511 - val_loss: 179.9593\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 15/20\n" ] },{ "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 67s 4s/step - loss: 166.7852 - val_loss: 168.4928\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 16/20\n" ] },{ "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 66s 4s/step - loss: 161.1418 - val_loss: 182.6162\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 17/20\n" ] },{ "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 66s 4s/step - loss: 155.3598 - val_loss: 164.6843\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 18/20\n" ] },{ "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 67s 4s/step - loss: 149.4317 - val_loss: 153.5656\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 19/20\n" ] },{ "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 67s 4s/step - loss: 143.0694 - val_loss: 151.3519\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 20/20\n" ] },{ "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r17/17 [==============================] - 66s 4s/step - loss: 138.1250 - val_loss: 142.6263\n" ] } ], "source": [ "from keras.optimizers import Adam\n", "\n", "train_model(input_to_softmax=test,\n", " pickle_path='model_test.pickle',\n", " save_model_path='model_test.h5',\n", " epochs=20,\n", " minibatch_size=200,\n", " spectrogram=False,\n", " optimizer=Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-8),\n", " max_duration=10)\n" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "_________________________________________________________________\nLayer (type) Output Shape Param # \n=================================================================\nthe_input (InputLayer) (None, None, 13) 0 \n_________________________________________________________________\nlayer_1_conv (Conv1D) (None, None, 200) 28800 \n_________________________________________________________________\nconv_batch_norm (BatchNormal (None, None, 200) 800 \n_________________________________________________________________\nbidirectional_1 (Bidirection (None, None, 300) 421200 \n_________________________________________________________________\nbt_lstm_0 (BatchNormalizatio (None, None, 300) 1200 \n_________________________________________________________________\nbidirectional_2 (Bidirection (None, None, 300) 541200 \n_________________________________________________________________\nbt_lstm_1 (BatchNormalizatio (None, None, 300) 1200 \n_________________________________________________________________\nbidirectional_3 (Bidirection (None, None, 300) 541200 \n_________________________________________________________________\nbt_lstm_2 (BatchNormalizatio (None, None, 300) 1200 \n_________________________________________________________________\nbidirectional_4 (Bidirection (None, None, 300) 541200 \n_________________________________________________________________\nbt_final_lstm_layer (BatchNo (None, None, 300) 1200 \n_________________________________________________________________\ntime_distributed_2 (TimeDist (None, None, 36) 10836 \n_________________________________________________________________\nsoftmax (Activation) (None, None, 36) 0 \n=================================================================\nTotal params: 2,090,036\nTrainable params: 2,087,236\nNon-trainable params: 2,800\n_________________________________________________________________\nNone\n" ] } ], "source": [ "me = saloedov(filters=200,\n", " kernel_size=11,\n", " conv_stride=2,\n", " dropout_rate=.1,\n", " conv_border_mode='valid',\n", " units=150,\n", " lstm_layers=4, )\n" ] }, "source": [ "from keras.optimizers import Adam\n", "\n", "train_model(input_to_softmax=me,\n", " pickle_path='model_my.pickle',\n", " save_model_path='model_my.h5',\n", " epochs=5,\n", " minibatch_size=2,\n", " spectrogram=False,\n", " #optimizer=Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-8),\n", " max_duration=10)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Please execute the code cell below to train the neural network you specified in `input_to_softmax`. After the model has finished training, the model is [saved]() in the HDF5 file `model_end.h5`. The loss history is [saved]() in `model_end.pickle`. You are welcome to tweak any of the optional parameters while calling the `train_model` function, but this is not required." ] }, { "cell_type": "heading", "metadata": { "collapsed": true }, "level": 6, "source": [ "#model_end = model_end(input_dim=13,\n", "# filters=200,\n", "# kernel_size=11,\n", "# conv_stride=2,\n", "# conv_border_mode='valid',\n", "# units=250,\n", "# activation='relu',\n", "# cell=GRU,\n", "# dropout_rate=1,\n", "# number_of_layers=2,\n", "# output_dim=36)\n", "\n", "train_model(input_to_softmax=model_4,\n", " pickle_path='model_4.pickle',\n", " save_model_path='model_4.h5',\n", " minibatch_size=100,\n", " spectrogram=False,\n", " max_duration=1) # change to False if you would like to use MFCC features\n" ] }, { "cell_type": "heading", "metadata": { "collapsed": true }, "level": 6, "source": [ "from keras.optimizers import Adam\n", "\n", "train_model(input_to_softmax=model_end,\n", " pickle_path='model_end.pickle',\n", " save_model_path='model_end.h5',\n", " train_json='train_corpus.json',\n", " valid_json='valid_corpus.json',\n", " minibatch_size=10,\n", " #optimizer=Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-8),\n", " spectrogram=False,\n", " max_duration=1)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a id='step3'></a>\n", "## STEP 3: Obtain Predictions\n", "\n", "We have written a function for you to decode the predictions of your acoustic model. To use the function, please execute the code cell below." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import numpy as np\n", "from data_generator import AudioGenerator\n", "from keras import backend as K\n", "from utils import int_sequence_to_text\n", "from IPython.display import Audio\n", "\n", "def get_predictions(index, partition, input_to_softmax, model_path):\n", " \"\"\" Print a model's decoded predictions\n", " Params:\n", " index (int): The example you would like to visualize\n", " partition (str): One of 'train' or 'validation'\n", " input_to_softmax (Model): The acoustic model\n", " model_path (str): Path to saved acoustic model's weights\n", " \"\"\"\n", " # load the train and test data\n", " data_gen = AudioGenerator(spectrogram=False)\n", " data_gen.load_train_data()\n", " data_gen.load_validation_data()\n", " \n", " # obtain the true transcription and the audio features \n", " if partition == 'validation':\n", " transcr = data_gen.valid_texts[index]\n", " audio_path = data_gen.valid_audio_paths[index]\n", " data_point = data_gen.normalize(data_gen.featurize(audio_path))\n", " elif partition == 'train':\n", " transcr = data_gen.train_texts[index]\n", " audio_path = data_gen.train_audio_paths[index]\n", " data_point = data_gen.normalize(data_gen.featurize(audio_path))\n", " else:\n", " raise Exception('Invalid partition! Must be \"train\" or \"validation\"')\n", " \n", " # obtain and decode the acoustic model's predictions\n", " input_to_softmax.load_weights(model_path)\n", " prediction = input_to_softmax.predict(np.expand_dims(data_point, axis=0))\n", " output_length = [input_to_softmax.output_length(data_point.shape[0])] \n", " pred_ints = (K.eval(K.ctc_decode(\n", " prediction, output_length, greedy=False)[0][0])+1).flatten().tolist()\n", " \n", " # play the audio file, and display the true and predicted transcriptions\n", " print('-'*80)\n", " Audio(audio_path)\n", " print('True transcription:\\n' + '\\n' + transcr)\n", " print('-'*80)\n", " print('Predicted transcription:\\n' + '\\n' + ''.join(int_sequence_to_text(pred_ints)))\n", " print('-'*80)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Use the code cell below to obtain the transcription predicted by your final model for the first example in the training dataset." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": true }, "source": [ "for i in range(10):\n", " get_predictions(index=i, \n", " partition='train',\n", " input_to_softmax=test, \n", " model_path='results/model_test.h5')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Use the next code cell to visualize the model's prediction for the first example in the validation dataset." ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": true }, "source": [ "for i in range(1650, 1700):\n", " get_predictions(index=i, \n", " partition='validation',\n", " input_to_softmax=test, \n", " model_path='results/model_test.h5')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One standard way to improve the results of the decoder is to incorporate a language model. We won't pursue this in the notebook, but you are welcome to do so as an _optional extension_. \n", "\n", "If you are interested in creating models that provide improved transcriptions, you are encouraged to download [more data]() and train bigger, deeper models. But beware - the model will likely take a long while to train. For instance, training this [state-of-the-art]() model would take 3-6 weeks on a single GPU!" ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.3" } }, "nbformat": 4, "nbformat_minor": 2} ................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download