Exemplo n.º 1
0
def run():
    # This is used in case we want to use a freezing program to create an .exe
    #if getattr(sys, 'frozen', False):
    #    os.chdir(sys._MEIPASS)

    guiEnabled = int(input("Enable GUI?: (1 == yes)\n"))
    guiEnabled = (guiEnabled == 1)
    viewEnabled = False
    if guiEnabled:
        viewEnabled = int(input("Display view?: (1 == yes)\n"))
        viewEnabled = (viewEnabled == 1)

    modelName = None
    modelPath = None
    loadedModelName = None
    algorithm = None
    packageName = None
    parameters = None
    model_in_subfolder = False
    loadModel = int(input("Do you want to load a model? (1 == yes)\n"))
    loadModel = (loadModel == 1)
    if loadModel:
        while packageName is None:
            packageName = None
            print("#########################################")
            print("Saved Models: \n")
            for folder in [i for i in os.listdir("savedModels/")]:
                print(folder)
            modelName = input("Enter the model name (name of directory in savedModels): (Empty string == break)\n")
            # If user presses enter, quit model loading
            if str(modelName) == "":
                loadModel = False
                modelName = None
                break
            # If user inputs wrong model name, ask for input again
            modelPath = "savedModels/" + modelName + "/"
            if not os.path.exists(modelPath):
                print("Invalid model name, no model found under ", modelPath)
                continue
            # CHECK FOR SUBFOLDERS
            if str(modelName)[0] != "$":
                while packageName is None:
                    print("------------------------------------")
                    print("Folder Submodels: \n")
                    for folder in [i for i in os.listdir(modelPath) if os.path.isdir(modelPath + "/" + i)]:
                        print(folder)
                    subModelName = input("Enter the submodel name: (Empty string == break)\n")
                    # If user presses enter, leave model
                    if str(subModelName) == "":
                        break
                    subPath = modelPath + subModelName + "/"
                    if not os.path.exists(subPath):
                        print("Invalid model name, no model found under ", subPath)
                        continue
                    packageName = "savedModels." + modelName + "." + subModelName
                    loadedModelName = subPath
                    # modelName = path
                    model_in_subfolder = True
                if packageName is None:
                    continue

            if packageName is None:
                packageName = "savedModels." + modelName
                loadedModelName = modelPath
                # ModelName = None will autogenereate a name
                modelName = None
        if packageName is not None:
            parameters = importlib.import_module('.networkParameters', package=packageName)
            algorithm = algorithmNameToNumber(parameters.ALGORITHM)
            # model.setPath(modelName)

    if not loadModel:
        parameters = importlib.import_module('.networkParameters', package="model")

        algorithm = int(input("What learning algorithm do you want to use?\n" + \
                              "'Q-Learning' == 0, 'Actor-Critic' == 2,\n"))
    tweaking = int(input("Do you want to tweak parameters? (1 == yes)\n"))
    tweakedTotal = []
    if tweaking == 1:
        while True:
            tweakedParameter = str(input("Enter name of parameter to be tweaked:\n"))
            paramLineNumber = checkValidParameter(tweakedParameter)
            if paramLineNumber is not None:
                paramValue = str(input("Enter parameter value:\n"))
                tweakedTotal.append([tweakedParameter, paramValue, paramLineNumber])
            if 1 != int(input("Tweak another parameter? (1 == yes)\n")):
                break
        modelPath = "savedModels/" + nameSavedModelFolder(tweakedTotal)
        model_in_subfolder = True

    if int(input("Give saveModel folder a custom name? (1 == yes)\n")) == 1:
        modelPath = "savedModels/" + str(input("Input folder name:\n"))


    model = Model(guiEnabled, viewEnabled, parameters, True)
    if parameters.JOB_TRAINING_STEPS != 0 and parameters.JOB_STEP_START > 0:
        model.loadModel(loadedModelName)
        print("Loaded into load path: " + model.getPath())

    else:
        model.initModelFolder(modelPath, loadedModelName, model_in_subfolder)
        print("Created new path: " + model.getPath())

    if tweakedTotal:
        modifyParameterValue(tweakedTotal, model)

    numberOfHumans = 0
    mouseEnabled = True
    humanTraining = False
    if guiEnabled and viewEnabled:
        numberOfHumans = int(input("Please enter the number of human players: (" + str(MAXHUMANPLAYERS) + " max)\n"))
        if fitsLimitations(numberOfHumans, MAXHUMANPLAYERS):
            createHumans(numberOfHumans, model)
            if 2 >= numberOfHumans > 0:
                humanTraining = int(input("Do you want to train the network using human input? (1 == yes)\n"))
                mouseEnabled = not humanTraining
            if numberOfHumans > 0 and not humanTraining:
                mouseEnabled = int(input("Do you want control Player1 using the mouse? (1 == yes)\n"))


    enableTrainMode = humanTraining if humanTraining is not None else False
    if not humanTraining:
        enableTrainMode = int(input("Do you want to train the network?: (1 == yes)\n"))
    model.setTrainingEnabled(enableTrainMode == 1)

    parameters = importlib.import_module('.networkParameters', package=model.getPath().replace("/", ".")[:-1])
    numberOfNNBots = parameters.NUM_NN_BOTS
    numberOfGreedyBots = parameters.NUM_GREEDY_BOTS
    numberOfBots = numberOfNNBots + numberOfGreedyBots

    Bot.init_exp_replayer(parameters, loadedModelName)

    setSeedAccordingToFolderNumber(model_in_subfolder, loadModel, modelPath, enableTrainMode)

    createBots(numberOfNNBots, model, "NN", parameters, algorithm, loadModel)
    createBots(numberOfGreedyBots, model, "Greedy", parameters)
    createBots(parameters.NUM_RANDOM_BOTS, model, "Random", parameters)
    model.addDataFilesToDictionary()

    if guiEnabled and viewEnabled and not model.hasHuman():
        spectate = int(input("Do want to spectate an individual bot's FoV? (1 = yes)\n"))
        if spectate == 1:
            model.addPlayerSpectator()

    if numberOfNNBots == 0:
        model.setTrainingEnabled(False)

    if numberOfBots == 0 and not viewEnabled:
        modelMustHavePlayers()

    model.initialize(loadModel)

    screenWidth, screenHeight = defineScreenSize(numberOfHumans)

    testResults = None
    if guiEnabled:
        view = View(model, screenWidth, screenHeight, parameters)
        controller = Controller(model, viewEnabled, view, mouseEnabled)
        view.draw()
        while controller.running:
            controller.process_input()
            model.update()
    else:
        maxSteps = parameters.MAX_SIMULATION_STEPS
        jobSteps = maxSteps if parameters.JOB_SIMULATION_STEPS == 0 else parameters.JOB_SIMULATION_STEPS
        jobStart = parameters.JOB_STEP_START
        smallPart = max(int(maxSteps / 100), 1) # constitutes one percent of total training time
        testPercentage = smallPart * 5
        if jobStart == 0:
            testResults = []
        else:
            print("max:", maxSteps, "start:", jobStart, "steps:", jobSteps)
            with open(model.getPath() + 'testResults.pkl', 'rb') as inputFile:
                testResults = pkl.load(inputFile)
        for step in range(jobStart, jobStart + jobSteps):
            model.update()
            if step % smallPart == 0 and step != 0:
                print("Trained: ", round(step / maxSteps * 100, 1), "%")
                # Test every 5% of training
            if parameters.ENABLE_TESTING:
                if step % testPercentage == 0:
                    testResults = updateTestResults(testResults, model, round(step / maxSteps * 100, 1), parameters)

        jobStart_line = checkValidParameter("JOB_STEP_START")
        epsilon_line = checkValidParameter("EPSILON")
        endParams = []
        endParams.append(["JOB_STEP_START", jobStart + jobSteps, jobStart_line])
        endParams.append(["EPSILON", model.getBots()[0].getLearningAlg().getNoise(), epsilon_line])
        modifyParameterValue(endParams, model)

        if parameters.ENABLE_TESTING and parameters.JOB_TRAINING_STEPS == 0 or \
                parameters.JOB_SIMULATION_STEPS + parameters.JOB_STEP_START >= parameters.MAX_SIMULATION_STEPS:
            testResults = updateTestResults(testResults, model, 100, parameters)
            meanMassesOfTestResults = [val[0] for val in testResults]
            exportTestResults(meanMassesOfTestResults, model.getPath() + "data/", "testMassOverTime")
            meanMassesOfPelletResults = [val[2] for val in testResults]
            exportTestResults(meanMassesOfPelletResults, model.getPath() + "data/", "Pellet_CollectionMassOverTime")
            plotTesting(testResults, model.getPath(), testPercentage, maxSteps, "Test", 0)
            plotTesting(testResults, model.getPath(), testPercentage, maxSteps, "Pellet_Collection", 2)
            
            if parameters.MULTIPLE_BOTS_PRESENT:
                meanMassesOfGreedyResults = [val[4] for val in testResults]
                exportTestResults(meanMassesOfGreedyResults, model.getPath() + "data/", "VS_1_GreedyMassOverTime")
                plotTesting(testResults, model.getPath(), testPercentage, maxSteps, "Vs_Greedy", 4)
            if parameters.VIRUS_SPAWN:
                meanMassesOfPelletVirusResults = [val[6] for val in testResults]
                exportTestResults(meanMassesOfPelletVirusResults, model.getPath() + "data/", "Pellet_Collection_Virus_MassOverTime")
                plotTesting(testResults, model.getPath(), testPercentage, maxSteps, "Pellet_Collection_with_Viruses", 6)
                if parameters.MULTIPLE_BOTS_PRESENT:
                    meanMassesOfGreedyVirusResults = [val[8] for val in testResults]
                    exportTestResults(meanMassesOfGreedyVirusResults, model.getPath() + "data/", "VS_1_Greedy_Virus_MassOverTime")
                    plotTesting(testResults, model.getPath(), testPercentage, maxSteps, "Vs_Greedy_with_Viruses", 8)


            print("Training done.")
            print("")

    if model.getTrainingEnabled():
        model.save(True)
        model.saveModels()
        if parameters.JOB_TRAINING_STEPS == 0 or \
                parameters.JOB_SIMULATION_STEPS + parameters.JOB_STEP_START >= parameters.MAX_SIMULATION_STEPS:

            runTests(model, parameters)
            if model_in_subfolder:
                print(os.path.join(modelPath))
                createCombinedModelGraphs(os.path.join(modelPath))

            print("Total average time per update: ", round(numpy.mean(model.timings), 5))

            bots = model.getBots()
            for bot_idx, bot in enumerate([bot for bot in model.getBots() if bot.getType() == "NN"]):
                player = bot.getPlayer()
                print("")
                print("Network parameters for ", player, ":")
                attributes = dir(parameters)
                for attribute in attributes:
                    if not attribute.startswith('__'):
                        print(attribute, " = ", getattr(parameters, attribute))
                print("")
                print("Mass Info for ", player, ":")
                massListPath = model.getPath() + "/data/" +  model.getDataFiles()["NN" + str(bot_idx) + "_mass"]
                with open(massListPath, 'r') as f:
                    massList = list(map(float, f))
                mean = numpy.mean(massList)
                median = numpy.median(massList)
                variance = numpy.std(massList)
                print("Median = ", median, " Mean = ", mean, " Std = ", variance)
                print("")
        elif testResults is not None:
            with open(model.getPath() + "replay_buffer.pkl", 'wb') as output:
                print(len(model.getBots()[0].getExpReplayer()), "buffLength")
                pkl.dump(model.getBots()[0].getExpReplayer(), output, pkl.HIGHEST_PROTOCOL)
            with open(model.getPath() + "testResults.pkl", 'wb') as output:
                pkl.dump(testResults, output, pkl.HIGHEST_PROTOCOL)

            submitNewJob(model.getPath())