機器學習算法:用強化學習走出旅途的困境

問題描述

這是一個圖論問題,其實可以使用窮舉法搜索,但是機器學習裏便於練習就把它變成了強化學習算法。
現在你外出旅行到了一個你不熟悉的城鎮,我們抽象爲城鎮中有六個點,這六個點存在着某種連接關係,無論你在哪個位置,都需要走到第六個點上纔算成功。用鄰接矩陣表示如下。
110000111100011101011110000111001011 \begin{matrix} 1&1& 0& 0& 0& 0\\ 1 &1& 1& 1& 0& 0\\ 0 &1& 1& 1& 0& 1\\ 0& 1 &1 &1 &1 &0\\ 0& 0& 0 &1 &1& 1\\ 0 &0 &1& 0& 1& 1\\ \end{matrix}
我們暫且放下數據結構中的深度遍歷搜索圖算法。來看一下隨機算法的速度——當然慢於確定性算法。使用C++作爲編程工具,強化學習算法Sarsa和Q-learning實現如下,實際上我們發現,Q-learning算法與Sarsa算法的運行速度相當,但是Sarsa算法傾向於走的路更長一些。
我們選取的獎賞矩陣如下所示
50infinfinfinf0500infinfinf050inf100inf0050infinfinfinf05100infinf0inf0inf \begin{matrix} -5& 0 &-inf &-inf& -inf &-inf\\ 0 &-5 &0 &0 &-inf& -inf\\ -inf &0 &-5& 0 &-inf& 100\\ -inf &0& 0& -5 &0& -inf\\ -inf &-inf &-inf& 0 &-5 &100\\ -inf &-inf &0& -inf &0& -inf\\ \end{matrix}

Sarsa算法

類的結構

/*強化學習算法Sarsa*/
	class Sarsa
	{
	public:
		Sarsa() = default;
		mat& run(const mat&r,const mat&t, int iter=1000);//輸入獎賞矩陣和轉移矩陣
		void main();//測試函數
	private:
		mat qmat;
	};

算法核心

mat & machineLearning::Sarsa::run(const mat & r, const mat & t, int iter)
{
	//從0號節點到n_row-1號節點
	qmat.randu(r.n_rows, r.n_cols);
	const double mu{ 0.7 }, gamma{ 0.4 }, epsilon{0.1};
	const int target{ static_cast<int>(r.n_rows - 1) };
	int now{}, reward{}, next{}, action{}, nextaction{};
	for (int i{ 0 }; i < iter; ++i)
	{
		//選擇一個初始位置
		now = std::rand()%r.n_rows;
		if (randu() < epsilon)//貪心選擇
		{
			vector<int> index{};
			for (int j{ 0 }; j < t.n_rows; ++j)
			{
				if (t(now, j) != 0)
					index.push_back(j);
			}
			action = index[std::rand() % index.size()];
		}
		else//選取最大值的動作
		{
			action = (t.row(now) != 0).index_max();
		}
		while (now != target)
		{
			reward = r(now, action);
			next = action;
			if (randu() < epsilon)//貪心選擇
			{
				vector<int> index{};
				for (int j{ 0 }; j < t.n_rows; ++j)
				{
					if (t(next, j) != 0)
						index.push_back(j);
				}
				nextaction = index[std::rand() % index.size()];
			}
			else//選取最大值的動作
			{
				nextaction = (t.row(now) != 0).index_max();
			}
			qmat(now, action) += mu * (reward + gamma * qmat(next, nextaction) - qmat(now, action));
			now = next;
			action = nextaction;
		}
	}
	return qmat;
}

測試程序

void machineLearning::Sarsa::main()
{

	double inf{ std::numeric_limits<double>::max() };
	mat t, r;
	t.load("t.dat",arma::arma_ascii);
	r.load("r.dat", arma::arma_ascii);
	run(r, t,3000).print("result:");
}

Q-learning算法/TD(0)算法

TD(0)算法相對於上述的Sarsa算法相比更爲簡單。在變量上只用記憶now和action,不用記憶next和nextaction變量,因爲q-learning只根據當前情況下的情況做出判斷,從不考慮下一個情況。

mat & machineLearning::Qlearning::run(const mat & r, const mat & t, int iter)
{
	//從0號節點到n_row-1號節點
	qmat.randu(r.n_rows, r.n_cols);
	const double mu{ 0.7 }, gamma{ 0.4 }, epsilon{ 0.1 };
	const int target{ static_cast<int>(r.n_rows - 1) };
	int now{}, reward{}, action{};
	for (int i{ 0 }; i < iter; ++i)
	{
		//選擇一個初始位置
		now = std::rand() % r.n_rows;
		while (now != target)
		{
			if (randu() < epsilon)//貪心選擇
			{
				vector<int> index{};
				for (int j{ 0 }; j < t.n_rows; ++j)
				{
					if (t(now, j) != 0)
						index.push_back(j);
				}
				action = index[std::rand() % index.size()];
			}
			else//選取最大值的動作
			{
				action = (t.row(now) != 0).index_max();
			}
			reward = r(now, action);
			qmat(now, action) += mu * (reward + gamma * qmat.row(action).max() - qmat(now, action));
			now = action;
		}
	}
	return qmat;
}

運行結果

1.4216.000006.4211.0540.1316.05400016.05435.13416.0540100.34016.05440.13411.05440.134000016.05435.134100.34000000 \begin{matrix} 1.42&16.0 &0&0&0&0\\ 6.42& 11.05 & 40.13& 16.054 & 0 & 0\\ 0& 16.054 &35.134 &16.054 &0 &100.34\\ 0& 16.054 &40.134 &11.054 & 40.134& 0\\ 0 &0 & 0& 16.054 & 35.134 &100.34\\ 0& 0& 0& 0 & 0& 0\\ \end{matrix}
結果這麼看,假如你從0號節點出發,那麼你會向值較高的節點前進,因爲獎勵多,所以你選擇1號節點,然後是2號,到達5號節點完成任務。其他節點也是類似。
需要注意的是,不能使用0初始化,否則會出現很多錯誤!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章