В продължение на част 4 от „„Създаване на бот за автоматично заснемане на машинно обучение за CS:GO.““ Още веднъж използвах Tensorflow Keras за обучение на мрежовите тегла, но този път за версията на CNN.

Не е елегантно, това, което си поставих за цел да постигна тук, беше да използвам повторно същия код TBVGG3 с минимална модификация за зареждане на тежести, обучени в Tensoflow Keras, използвайки Python. По същество премахнах целия код за обратно разпространение, направих някои малки промени в предаването напред, като добавих прост плътен слой, експортирах теглата от Keras като плоски файлове и след това заредих тези данни в многомерните масиви, използвани в C програмата.

Първата част от процеса беше да тренираме тежестите в Keras с помощта на Conv2D слоеве, това беше лесната част. В моето оригинално решение TBVGG3 преминах от GAP слой към средна стойност на GAP изходите и след това към модифицирана сигмоидна функция. В Keras изглежда не можах да постигна този тип трансформация, използвайки стандартни слоеве, така че просто избрах проста корекция за преминаване от GAP слой към единичен плътен слой със сигмоиден изход, така;

model = Sequential([
 keras.Input(shape=(28, 28, 3)),
 layers.Conv2D(2, kernel_size=(3, 3), activation=”relu”),
 layers.MaxPooling2D(pool_size=(2, 2)),
 layers.Conv2D(4, kernel_size=(3, 3), activation=”relu”),
 layers.MaxPooling2D(pool_size=(2, 2)),
 layers.Conv2D(8, kernel_size=(3, 3), activation=”relu”),
 layers.GlobalAveragePooling2D(),
 layers.Flatten(),
 layers.Dense(1, activation=”sigmoid”),
])

Заслужава да се отбележи, че тази версия има по-малко ядра на слой от оригинала, това е така, защото изцедих толкова % от обучените резултати, колкото можах за най-малкия размер на мрежата.

След като тежестите бяха обучени, ги изравних и експортирах, но също така експортирах и несплескан изглед, за да мога да видя в какъв ред идват тежестите — имах предчувствие, че това няма да е директно копиране и поставяне на тежестите и че ще трябва да ги преподредя за C многомерния масив (и бях прав) в бъдещи сценарии ще напиша препратката в C, за да използвам теглата такива, каквито са от Keras. Но както и да е, този път експортирането на тежестите беше много по-лесно от преди;

np.set_printoptions(threshold=sys.maxsize)
for layer in model.layers:
 if layer.get_weights() != []:
  f = open("view.txt”, “w”)
  if f:
  f.write(str(layer.get_weights()))
  f.close()
  np.savetxt(“w”, layer.get_weights()[0].flatten(), delimiter=”,”)
  np.savetxt(“b”, layer.get_weights()[1].flatten(), delimiter=”,”)

Това обаче направи кода за импортиране малко по-тежък в замяна, тъй като теглата трябваше да бъдат пренаредени.

След като импортирах тежестите, изпробвах решението без добавения плътен слой и имах ужасни резултати, след това добавих плътния слой и добре .. нищо, никакво активиране. Мислех, че това е странно, затова премахнах сигмоида, за да видя какво се въвежда в него и можех да видя, че получавам стойности между -100 и 0. Нямам представа защо, но предполагам, че това се дължи на някаква оптимизация, използвана от Tensorflow? Добрата новина е, че изведените стойности бяха както се очакваше, само в нечетен диапазон, така че за да ги мащабирам обратно до диапазон 0–1, просто трябваше да умножа изхода по -0,01, реципрочната стойност на деленето на -100 което беше малко по-ефективно от традиционния 1 / (1 + exp(-x))sigmoid. Готино.

И така, как се представи? Кодът, който съдържа този бот, беше същият код, използван в част 4 за версията на FNN, и използвах същите „хиперпараметри“;

#define SCAN_VARIANCE 3
#define SCAN_DELAY 10000
#define ACTIVATION_SENITIVITY 0.75
#define REPEAT_ACTIVATION 2
#define FIRE_RATE_LIMIT_MS 800

И ако трябва да бъда честен с вас, версията на CNN в този случай беше малко по-лоша. Защо? Може да се дължи на това, че FNN има по-малко време за изчисление и по този начин изчислява активациите по-бързо, или че тази задача е по-добре решена чрез откриване на обекти за изрязване на бисквитки вместо съвпадение на функции поради малкия вход от 28x28 пиксела - разбира се, това може да е същият размер, който се използва от набора от данни MNIST, но трябва да се има предвид, че MNIST е много по-просто представяне за захранване на мрежа, това са практически плътни черни линии на бял фон, които представляват ръкописни цифрови знаци или „цифри“, с които CS:GO захранваме мрежови много сложни и шумни изображения.

Все пак имам план и той е да направя друга конволюционна мрежа, обучена в Keras, но този път да използвам прозорец за сканиране, който може да капсулира цялата форма на модел на играч на средно разстояние от играча. Нещо около 96х192 пиксела. Ще запазя всички проби като растерни изображения, а не като предварително нормализирани масиви float32 и след това ще оставя Keras да се справи с нормализирането, за да позволи на потребителите малко повече гъвкавост по отношение на набора от данни.

Може обаче да имате един последен горещ въпрос, как тренирането на конволюционната мрежа в Keras с помощта на оптимизатора на Adam и mean_squared_error се сравнява с използването на SGD или NAG с mean_absolute_error като в оригинала? Е, SGD и NAG имаха пренебрежимо малка разлика между тях, но тренираха по-добре с mean_absolute_error постигайки високи 80 до ниски 90 в степента на откриване, когато се сравнява със същия набор от данни, използван в обучението/годността, докато Адам тренираше по-добре с mean_squared_error и като цяло имаше нива на откриване от 94%+. Ще направи ли някаква забележима разлика в играта? не точно.

Този път пуснах този проект в единичен zip файл, за да съдържа неелегантната бъркотия, която представлява това решение. Ако искате да си поиграете, можете да го изтеглите тук.

Не се притеснявайте, това далеч не е завършено! Габен, по-добре трепери в ботушите ти... защото идвам за CS:GO и няма да спра, докато всеки контратерорист не бъде бързо свален чрез контролирани от машинно обучение изстрели в главата.

It’s on.

Очаквайте част 6, обещавам ви перфектни снимки на главата в близко бъдеще.

Редактиране: Проведох някои тестове, използвайки примерен прозорец 96x192, но не беше подходящо достатъчно бърз за обработка в реално време поради пречките на X11 XGetImage(), но има много по-малко пропуски огън. Сега създадох нов набор от проби 28x28 два пъти по-голям от стария и имах по-добри резултати в модела FNN. Ще се придържам към примерния прозорец с размери 28x28 пиксела в бъдещите повторения.

Също така преобучих версията на FNN с нов набор от данни и тя е най-добрата досега, изтеглете я тук.

„Продължете да четете тази поредица от статии в част 6 тук.“