Using Binary Heaps in A* Pathfinding

PathfindingProject Unity的寻路插件,支持同屏多个AI进行寻路,很好用!分享给大家 立即下载

Using Binary Heaps in A* Pathfinding

By Patrick Lester ( Updated April 11, 2003)


This article is a sidebar for my main article, “A* Pathfinding for Beginners.” You should read that article, or understand A* thoroughly, before proceeding with this article.

One of the slowest parts of the A* pathfinding algorithm is finding the square or node on the open list with the lowest F score. Depending on the size of your map, you could have dozens, hundreds or even thousands of nodes to search through at any given time when you are using A*. Needless to say, repeatedly searching through a list this big can slow things down a lot. The amount of time it takes to do this, however, can be greatly influenced by the way you choose to save your open list items.

Sorted and Unsorted Open Lists: A Simple Approach

A really simple way to save the open list is to save each item as needed, and go through the whole list each time you need to grab something off of the list, looking for the lowest cost item. This provides fast insertions into the list, but the slowest possible removal time, since you need to check each item on the list to make sure you have the lowest F cost item.

You can generally improve your performance by keeping your list sorted. This takes a little more up-front work, however, because every time you add an item to the list, you need to insert it in the proper place. Removing items, however, is fast. You just grab the first item off of the list, which will have the lowest possible F cost.

There are lots of ways to keep your data sorted (selection sorts, bubble sorts, quick sorts, etc.) and you can find articles on these on the internet by simply searching on those terms in your favorite search engine. But we can at least touch on some ideas here. A really simple approach would be to start at the beginning of your list every time you need to add a new item, and then successively compare the F cost of the current node you are adding to the list with each item already on the list. Once you find a node on the open list with an equal or higher F cost, you could insert the new item before that item on the list. Depending on the computer language you are using, linked lists using classes or structs (types in Blitz) are probably a good method here.

This approach could be improved by keeping track of the average F cost of items already on your list, and using that to decide whether to start at the beginning of the list (as described above) or to start at the end of the list and work toward the front of the list. In general, insertions of new items with lower than average F costs would start at the beginning of the list and work forwards, while insertions of new items with higher than average F costs would start at the end and work backwards. This approach will cut your search time in half.

A more complicated, but faster approach could be to take this idea to the next level and use a quick sort, which basically starts by comparing the F cost of the new item to the item at the middle of the list. If the new item has a lower F cost, you would then compare it to the item 1/4 of the way through the list, if lower than that you would compare it to the one 1/8 of the way, and so on, successively dividing your list in half and comparing the new item to the current items on the list until it finds its proper spot. This is a pretty generic description, so you will want to look up quick sorting on the internet to find out more about how it works. Suffice it to say, this will generally be quicker than any of the techniques described so far.

Binary Heaps

Binary heaps are very similar to the quick sort method just described, and they are often used by people who are serious about keeping their A* functions as fast as possible. In my experience, using a binary heap will speed up your pathfinding by 2-3 times on average, and more on larger maps with lots of nodes (say a map 100 x 100 nodes or more). Fair warning, however -- binary heaps are a bit tricky, and may not be worth the headache unless you are using a map with lots of nodes, where speed gains are crucial.

The rest of this article is devoted to explaining binary heaps and their use in A*. There is also a Further Reading section at the end of the article which will provide you additional perspectives, if mine leaves you totally mystified.

Still interested? Okay, here goes ...

In a sorted list, every item on the list is in its proper order, lowest-to-highest or highest-to-lowest. This is helpful, but is actually more than we really need. We don’t actually care if item number 127 is lower than number 128 on the list. All we really want is the lowest F cost item to be easily accessible at the top of the list. The rest of the list can be a jumble, for all we care. Keeping the rest of the list properly sorted is just extra unneeded work until, of course, we need the next lowest F cost item.

Basically, what we really need is something called a “heap” or, more specifically, a binary heap. A binary heap is bunch of items where either the lowest or highest value item (depending on what you want) is at the top of the heap. Since we are looking for the lowest F cost item, we will put that at the top of our heap. This item has two children, each of which has an F cost equal to, or a little higher than it, and each of these children has two children of its own that has an F cost that is equal to, or a little higher than it ... and so on. Here is what one heap could look like:

Notice that the lowest item on the list (10) is at the top and the second lowest (20) is one of its children. After that, however, all bets are off. In this particular binary heap, the third lowest item on the list is 24, which is two steps down from the top, and lower than 30, which is only one step from the top on the left side. Simply put, it doesn’t matter what the value of other items are in the heap, each individual item in the heap needs only to be equal to or higher than its parent, and equal to or lower than both of its children. Those conditions are met here, so this is a valid binary heap.

All right, you are probably thinking, this is modestly interesting, but how do you actually use it in any practical sense? Well, one of the interesting things about a heap is that you can save it in a simple, one dimensional array.

In this array, the item at the top of the heap would be in the first position of the array (position 1, not position zero, which is possible in an array). Its two children would be in positions 2 and 3. The four children of these two items would be in positions 4-7.

In general, the two children of any item in the heap can be found in the array by multiplying the item’s current position in the array by two (to find the first child) and by two and adding one (to find the second child). So, for example, the two children of the third item in our heap (with a value of 20), can be found in positions 2*3 = 6, and 2*3 +1 = 7 of the array. In this case, the numbers in those positions are 30 and 24, respectively, which makes sense when you look at the heap.

You don’t really need to know this, but it is worth noting that there are no holes in this heap. With 7 items, it completely fills out every row of a three-level heap. This isn’t necessary, however. For our heap to be valid, we only need to fill out every row above the bottom level. We can have any number of items on the bottom level itself, however, and new items are added from left to right on that level. The method described in this article does that, so you don’t really need to worry about it.

Adding Items to the Heap

We will need to consider a few more things before we can actually use a heap for pathfinding purposes, but for now let’s just learn the basics of using a binary heap in general. I’d suggest skimming through this part to understand the basics. I will give you a formula that takes care of all of this for you a little later on in the article, but it is still important to understand what is going on.

In general, to add an item to the heap, we place it at the very end of the array. We then compare it to its parent, which is at location (items in heap)/2, rounding all fractions down. If the new item’s F score is lower, we swap these two items. We then compare the new item with its new parent, which is at (current position in heap)/2, rounding fractions down. If its F value is lower, we swap again. We repeat this process until the item is not lower than its parent, or until the item has bubbled all the way to the top, which is in position #1 in the array.

Let’s say we were adding an item with an F score of 17 to our existing heap. We currently have 7 items in the heap, so the new item would be placed in position number 8. This is what the heap looks like. The new item is underlined.

10 30 20 34 38 30 24 17

We would then compare this item it to its parent, which is in position 8/2 = position 4. The F value of the item currently in position 4 is 34. Since 17 is lower than 34, we swap them. Now our heap looks like this:

10 30 20 17 38 30 24 34

Then we compare it with its new parent. Since we are in position 4 we compare it to the item in position number 4/2 = 2. That item has an F score of 30. Since 17 is lower than 30, we swap them, and now our heap looks like this:

10 17 20 30 38 30 24 34

We then compare it to its new parent. Since we are now in position #2, we compare it with the item in position number 2/2 = 1, which is the top of the heap. In this case, 17 is not lower than 10, so we stop and leave the heap the way it is.

Removing Items from the Heap

Removing items from the heap involves a similar process, but sort of in reverse. First, we remove the item in slot #1, which is now empty. Then we take the last item in the heap, and move it up to slot #1. In our heap above, this is what we would end up with. The previously last item in the heap is underlined.

34 17 20 30 38 30 24

Next we compare the item to each of its two children, which are at locations (current position * 2) and  (current position * 2 + 1). If it has a lower F score than both of its two children, it stays where it is. If not, we swap it with the lower of the two children. So, in this case, the two children of the item in slot #1 are in position 1*2 = 2 and 1*2+1 = 3. It turns out that 34 is not lower than both children, so we swap it with the lower of the two, which is 17. This is what we end up with:

17 34 20 30 38 30 24

Next we compare the item with its two new children, which are in positions 2*2 = 4, and 2*2+1 = 5. It turns out that it is not lower than both of its children, so we swap it with the lower of the two children (which is 30 in slot 4). Now we have this:

17 30 20 34 38 30 24

Finally we compare the item with its new children. As usual, these children would be in positions 4*2 = 8, and 4*2 +1 = 9. But there aren’t any children in those positions because the list isn’t that big. We have reached the bottom level of the heap, so we stop.

Why is a Binary Heap so Fast?

Now that you know the basics of insertion and removal from a heap, you should begin to see why it is so much faster than, say, an insertion sort. Imagine that you have an open list with 1000 nodes on it, which is not impossible on a sizable map with a lot of nodes (remember, a map just 100 x 100 nodes has 10,000 nodes on it). If you were to do a simple insertion sort, started at the beginning of the list, and proceeded until you found the proper spot to insert the new item, you would on average need to make 500 comparisons before inserting it in the right place.

Using a binary heap, you would only need to make an average of 1-3 comparisons to insert it in the right spot, starting from the bottom. You would also need to make an average of about 9 comparisons to remove an item from the open list and reorder the heap appropriately. In A*, you generally remove one node on every pass (the lowest F cost item), and usually add anywhere from 0 to 5 new nodes (using the 2D approach described in the main article). This can total up to about 1% of the time it takes to do an insertion sort on the same number of nodes. The difference becomes geometrically more important the larger (i.e. more nodes on) your map. Smaller maps, by comparison, gain less and less of an advantage, which is why binary heaps become progressively less worth the trouble the smaller your map, and the fewer nodes you use.

By the way, just because you are using a binary heap doesn’t mean that your pathfinding algorithm will be 100 times faster (or whatever). There is some overhead involved, which is described below. Plus, there is more to the A* algorithm than simply sorting the open list. Nevertheless, in my experience using a binary heap will still make your pathfinding algorithm 2-3 times faster in most cases, and even more on longer paths.

Creating the Open List Array

Now that we know what a heap is, how do we use it? The first thing we need to do is dimension our one-dimensional array properly. To do this, first we need to figure out how big it can possibly get. In general, the list can’t get any bigger than the total number of nodes on our map (assuming a worst-case scenario where we search the whole map for a path). In a square, two-dimensional map like the one I described in the main pathfinding article, we won’t have more than mapWidth x mapHeight nodes. So that is how big our 1 dimensional array should be. For the sake of this example, we will call this array openList(). The top item in the heap would be stored in openList(1), the second item in the heap would be openList(2), and so on.  

Using Pointers

Now that we have a one-dimensional heap/array that is the right size, we are almost ready to start using it for pathfinding purposes. Before we go any further, however, let’s look at our original heap again, before we added or subtracted anything.

Currently, it is just a list of F values, and they are arranged properly. But we are missing an important element. Sure, we have a bunch of F values arranged in binary heap order, but we have no clue what squares on our map they are associated with. Basically, what we have right now just tells us that 10 is the lowest F score in the heap. But which square on our pathfinding map does that refer to?

To fix this problem, we need to change the values of the items in the array. Instead of storing the F value in the array, we need to store a unique identifying number that tells us what square it is referring to. My approach is to create a unique ID associated with each new item added to the heap called squaresChecked. Every time we add an item to the open list, we increase squaresChecked by one and use this as the unique ID for the new item added to the open list. The first item added to open list will item #1, the second item is item #2, and so on.

Finally, we need to save the actual F cost of that square in a separate one dimensional array, which I call Fcost(). As with the openList array, we will dimension it to the size (mapWidth x mapHeight). We will also store the x and y coordinates of the node on the map in similar one-dimensional arrays, which I will call openX() and openY(). Visually, this looks like the following illustration:

While this looks a little more complicated, it is the same heap we used in the earlier illustration. We just have a lot more information now.

Item #5, with the lowest Fcost of 10, is still at the top of the heap, and in the first column of our one dimensional array. But now we are storing its unique ID number of 5, rather than its F cost in the heap. In other words, openList(1) = 5. This unique number is then used to look up the item’s Fcost, and x and y locations on the map. The Fcost of this item is Fcost(5) = 10, its x location on the map is openX(5) = 12, and its y location on the map is openY(5) = 22.

This top item in the heap has two children, items number 2 and 6, which have Fcosts of 30 and 20 respectively and are in slots 2 and 3 in openList(), and so on. Basically, we have exactly the same heap we had earlier, just with a lot more information about where the item is on the map, what its Fcost is, etc.

Adding New Items to the Heap (Part 2)

Okay, so let’s actually apply this technique to sorting our open list in a way that is usable in an A* pathfinding algorithm. In general, we use exactly the same techniques that were described earlier.

The first item we add to the open list, which is generally the starting node, is assigned a unique ID number, which is 1, and then put in position #1 in the open list. In other words, openList(1) = 1. We also keep track of the number of items on our open list, which is also 1 for now. We record this number in a variable called numberOfOpenListItems.

As we add new nodes to the open list, first we figure out their G, H and F scores, as described in the main A* article. Then we add them to the binary heap as described earlier in this article.

First we assign the new item a unique ID#, which is the purpose of the squaresChecked variable. We basically add 1 to this every time we add a new node to the open list, and we assign this number to the new node. We then add 1 to numberOfOpenListItems. Then we add it to the bottom of the open list. Basically, all of this translates into the following:

  squaresChecked = squaresChecked +1
  numberOfOpenListItems = numberOfOpenListItems+1
  openList(numberOfOpenListItems) = squaresChecked

Then we make successive comparisons with its parent until it rises to its proper spot in the heap. Here is some code that will do that :

  m = numberOfOpenListItems
  While m <> 1 ;While item hasn't bubbled to the top (m=1)

     ;Check if child is <= parent. If so, swap them.
     If Fcost(openList(m)) <= Fcost(openList(m/2)) Then
        temp = openList(m/2)
        openList(m/2) = openList(m)
        openList(m) = temp
        m = m/2 
     Else
   
    
        Exit ;exit the while/wend loop
     End If
  Wend
   

Deleting Items from the Heap (Part 2)

Of course, we don’t just build a heap, we also need to delete items from the heap when we don’t need them anymore. Specifically, in A* pathfinding we need to delete the lowest F cost item from the top of the heap after we have checked it and switched it to the closed list.

As was described earlier in the article, you start by moving the last item in the heap over to first position, and then reduce the number of items in the list by one. In pseudocode, this would be:

  openList(1) = openList(numberOfOpenListItems)
  numberOfOpenListItems = numberOfOpenListItems - 1

Next we need to do successive comparisons between this value and each of its two children. If it has a higher F score than one or both of the two children, we swap it with the lower of the two children. Then we compare the item with its two new children (since it is lower in the heap). If it has a higher F score than one or both of its two children, we swap it with the lower of the two. We repeat this process until the item has found its proper place in the heap, which may end up toward the bottom, but not necessarily. Here is what the pseudocode would look like:

v = 1
;Repeat the following until the item sinks to its proper spot in the binary heap.
Repeat
  u = v
  If 2*u+1 <= numberOfOpenListItems ;if both children exist
    ;Select the lowest of the two children.
    If Fcost(openList(u)) >= Fcost(openList(2*u))then v = 2*u ;SEE NOTE BELOW
    If Fcost(openList(v)) >= Fcost(openList(2*u+1))then v = 2*u+1 ;SEE NOTE BELOW

  Else If 2*u <= numberOfOpenListItems ;if only child #1 exists
    ;Check if the F cost is greater than the child
    If Fcost(openList(u)) >= Fcost(openList(2*u))then v = 2*u
  End If
  If u <> v then ; If parent's F > one or both of its children, swap them
    temp = openList(u)
    openList(u) = openList(v)
    openList(v) = temp
  Else
    Exit ;if item <= both children, exit repeat/forever loop
  End if
Forever ;Repeat forever

Please note the bolding (in red) of u and v in two lines of the code. On the second line, you want to use v, not u, which may not be immediately obvious. This ensures that you end up swapping with the lower of the two children. Failing to do that will give you an invalid heap, and screw up your pathfinding completely.

Resorting an Existing Open List Item

As is described in the main article, occasionally you will find that the F score of an existing open list item can change. When that happens, you don’t need to take the item out of the list and start all over. Simply start in its current location, and compare it to its parent using its new (lower) F score. If its F score is low enough to warrant a swap with that parent, then you need to do so (or you will have an invalid heap, and everything will break down). In general, you use the same code described in the “Adding an Item to the Heap” section of this article, with the following additional consideration:

Unfortunately, because your data is in a giant, seemingly unordered heap, you need to go through the whole heap to find the existing open list item. Basically you will be looking for the square with the correct x and y coordinates, as indicated by openX(openList()) and openY(openList()). After you find it, however, you can proceed normally, making the necessary comparisons and swaps starting from that point in the heap.

Final Notes

Okay, I am hoping that if you are still reading at this point, you aren’t totally confused. If you aren’t intimidated, and want to code up a binary heap for your own pathfinding algorithm, then this is what I would suggest.

First, forget about binary heaps for a while. Focus first on getting your A* pathfinding algorithm working correctly and bug free using a simpler sorting method. You don’t really need it to work fast at first, you just need it to work.

Second, before you add a binary heap to the code, try coding a stand alone binary heap function that does what you want, adding and subtracting items from the heap in an appropriate way. Make sure you write the program so you can see what it is doing at each step in the process, perhaps printing the results to the screen as you go. You should also include some escape key code in the program that allows you to break out of the whole thing if necessary. It is very easy to get trapped in an endless loop if you don’t write a binary heap correctly.

Once you are confident that you have both programs working smoothly, save working backup copies of both, and then start working on putting the two together. Unless you are much smarter than me, you will probably have problems at first. Tell tale signs are error messages and/or seeing pathfinding critters bug out in all sorts of weird directions. Eventually, however, you will get it all working.

Further Reading

As always, there are lots of other good articles out there on the web that describe this topic. Here are some to get you started. The first one explains things graphically. The second shows how to implement binary heaps using a simple array (if my explanation was baffling). The third discusses the use of heaps in pathfinding, generally.  

Finally, you might want to consider looking at my pathfinding code, which can be found here. It mirrors the pseudocode in this article, is heavily commented, and is written in both C++ and Blitz, a Basic language that is easier to understand than most. All you coders who don't use C++ should find the Basic version easy to understand.

Well, that’s it. I welcome comments on this (admittedly) complex topic, and I can be reached at:

Until then, as always, good luck

A+Pathfinding+Project+Pro+v4.1.16 A+Pathfinding+Project+Pro+v4.1.16学习研究使用 立即下载

相关推荐

The A* Pathfinding Project

Unity3d A*寻路 The A* Pathfinding Project Unity3d A*寻路

(转)在A*寻路中使用二叉堆

[翻译]在A*寻路中使用二叉堆 Posted on 2005-03-28 17:47 Panic 阅读(191) 评论(0)  编辑 收藏 <!--<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"xmlns:dc="http://purl.org/dc/elements/1.1/"xmlns:trackba

DooDu的专栏 1952

A* Pathfinding Project Pro 3.8.6

A* Pathfinding Project Pro 3.8.6 - 超牛的寻路插件

A*寻路算法再初探

在看下面这篇文章之前,先介绍几个理论知识,有助于理解A*算法。   启发式搜索:启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标。这样可以省略大量无畏的搜索路径,提到了效率。在启发式搜索中,对位置的估价是十分重要的。采用了不同的估价可以有不同的效果。 估价函数:从当前节点移动到目标节点的预估费用;这个估计就是启发式的。在寻路

shaderdx的专栏 1825

Unity A Pathfinding Project Pro 4.1.12 A*寻路插件

Unity A Pathfinding Project Pro 4.1.12 A*寻路插件,强大的寻路插件库,内含多种寻路算法,最新版本

Plot3d 网格数据格式

PLOT3D是一个计算机图形程序,旨在可视化计算流体力学的网格和解决方案。PLOT3D文件可以是ASCII, 也可是Fortran unformatted 或 C binary形式。PLOT3D文件分为网格文件(XYZ 文件), 空气动力学结果文件 (Q 文件)和通用结果文件(函数文件 + 函数名称文件)。网格文件中可加入所谓的IBlank参数。

weixin_62592231的博客 3721

在A*寻路中使用二叉堆

在A*寻路中使用二叉堆  译者序:<br />  这一篇文章,是“A* Pathfinding for Beginners.”,也就是我翻译的另一篇文章《A*寻路初探 》的补充,在这篇文章里,作者再一次展现了他阐述复杂话题的非凡能力,用通俗易懂的语句清晰的解释了容易让人迷惑的问题。还是那句话,如果你看了这篇文章仍然无法领会作者的意图,那只能怪我的翻译太蹩脚了。请参考原文做进一步的理解。<br />  这里讲解的二叉堆,其实是以堆的形式存在的二叉树,这个特殊的结构把A*算法对开启列表的排序需求演绎的出神入化,

水上漂的专栏 955

车辆动力学从入门到进阶之路(传统篇)

新手如何入门车辆动力学开发领域,本文为您引路!

CrazyRabbit的博客 1万+

A*方法总结

好,现在你已经看完了整个说明,让我们把每一步的操作写在一起: 把起始格添加到开启列表。 重复如下的工作:a) 寻找开启列表中F值最低的格子。我们称它为当前格。b) 把它切换到关闭列表。c) 对相邻的8格中的每一个?如果它不可通过或者已经在关闭列表中,略过它。反之如下。 如果它不在开启列表中,把它添加进去。把当前格作为这一格的父节点。记录这一格的F,G,和H值。 如果它已经在开启列表中,用G值为

逍遥剑客 3644

Halcon实战:5分钟搞定自定义直线卡尺工具(附完整代码下载)

本文详细介绍了如何使用Halcon快速开发自定义直线卡尺工具,通过交互式ROI绘制、边缘检测和直线拟合三个核心函数,实现高效工业视觉检测。文章包含完整代码下载,帮助开发者在5分钟内掌握这一实用工具的开发技巧,提升直线检测的精度和效率。

perl8的博客 251

cordic算法的FPGA实现

cordic 算法的MATLAB仿真及verilog实现

qq_38360574的博客 1676

[转]Using Binary Heaps in A* Pathfinding

By Patrick Lester ( Updated April 11, 2003) This article is a sidebar for my main article, “A* Pathfinding for Beginners.” You should read that article, or understand A* thoroughly, before proceedi...

weixin_30642029的博客 123

Qi标准下的充电协议及其记忆技巧

记忆无线充电协议中的。

m0_73991989的博客 1320

二叉堆 -- Binary Heaps

首先解释一下名词:二叉堆。什么是二叉?显而易见,即为两个分支。那么剩下的就是堆这个词,这个词比较难以解释,可以说成是

zxz414644665的专栏 2223

Linkage Mapper 工具参数详解——Building Network and Map Linkages

此文档用于解析使用LinkageMapper各输入输出参数详情以及可能的影响,并介绍了如何解释模型输出结果和输出参数,适合刚入手的人。篇幅很长很啰嗦,是因为每个参数都解释的万分细致。

sumuses的博客 6119

在 SAP BTP 中通过 MTA 自动创建 Service Broker 的原理与实战

本文探讨了如何在SAP BTP的Cloud Foundry环境中通过MTA部署自动创建和注册Service Broker。传统手动注册方式存在依赖管理员、环境一致性差等问题。通过MTA部署可实现自动化Broker注册,利用占位符生成安全凭证,并确保平台端与应用端认证一致。文章详细解析了关键配置参数,包括create-service-broker标志、Broker名称、认证凭据和访问URL的设置方法。这种基础设施即代码(IaC)方式能提升DevOps实践水平,使服务注册成为应用部署流水线的有机组成部分。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 201

二进制的使用Using Binary

本文会列举本人在学习算法过程中遇到的常用二进制操作

qq_40173721的博客 689

Aurix TC3xx系列MCU DMA模块配置方法(二)

本文主要基于英飞凌Aurix TC3xx系列MCU,通过EB tresos配置工具,介绍DMA驱动模块的配置方法。

m0_38045338的博客 2850

A*寻路初探

原文出处:A* Pathfinding for Beginners译者序  很久以前就知道了A*算法,但是从未认真读过相关的文章,也没有看过代码,只是脑子里有个模糊的概念。这次决定从头开始,研究一下这个被人推崇备至的简单方法,作为学习人工智能的开始。这篇文章非常知名,国内应该有不少人翻译过它,我没有查找,觉得翻译本身也是对自身英文水平的锻炼。经过努力,终于完成了文档,也明白的A*算法的原理

showlong 专栏「C++」@ http://www.fuel4d.com 2060

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

A星寻路算法介绍

这篇文章还可以在这里找到 英语 Tweet 这篇blog是由iOS Tutorial Team的成员  Johann Fradj发表的,他目前是一位全职的资深iOS开发工程师。他是Hot Apps Factory的创始人,该公司开发了App Cooker。   学习A星寻路算法是如何工作的! 你是否在做一款游戏的时候想创造一些怪兽或者游戏主

燕窝 2869

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

warning:this project is not a myeclipse hibernate project .

web 项目中打开 hibernate.cfg.xml 文件时提示:The project is not a myEclipse hibernate project.这是由于使用版本控制SVN的时候,工程根目录下的:.project和.myhibernatedata 文件不在版本控制范围内,因此组内的成员更新资源后,缺少.project 内的 &lt;nature&gt;com.genuitec....

weixin_38927419的博客 337
上一篇: A* pathfinding for beginners
下一篇: P2P之UDP穿透NAT的原理与实现
amdk_7
博客等级 码龄22年 12粉丝 2原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值